.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
---|
1 | 2 | /* |
---|
2 | 3 | * property.h - Unified device property interface. |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2014, Intel Corporation |
---|
5 | 6 | * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
---|
6 | 7 | * Mika Westerberg <mika.westerberg@linux.intel.com> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License version 2 as |
---|
10 | | - * published by the Free Software Foundation. |
---|
11 | 8 | */ |
---|
12 | 9 | |
---|
13 | 10 | #ifndef _LINUX_PROPERTY_H_ |
---|
14 | 11 | #define _LINUX_PROPERTY_H_ |
---|
15 | 12 | |
---|
| 13 | +#include <linux/bits.h> |
---|
16 | 14 | #include <linux/fwnode.h> |
---|
17 | 15 | #include <linux/types.h> |
---|
18 | 16 | |
---|
.. | .. |
---|
24 | 22 | DEV_PROP_U32, |
---|
25 | 23 | DEV_PROP_U64, |
---|
26 | 24 | DEV_PROP_STRING, |
---|
27 | | - DEV_PROP_MAX, |
---|
| 25 | + DEV_PROP_REF, |
---|
28 | 26 | }; |
---|
29 | 27 | |
---|
30 | 28 | enum dev_dma_attr { |
---|
.. | .. |
---|
78 | 76 | unsigned int nargs, unsigned int index, |
---|
79 | 77 | struct fwnode_reference_args *args); |
---|
80 | 78 | |
---|
| 79 | +struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode, |
---|
| 80 | + const char *name, |
---|
| 81 | + unsigned int index); |
---|
| 82 | + |
---|
| 83 | +const char *fwnode_get_name(const struct fwnode_handle *fwnode); |
---|
| 84 | +const char *fwnode_get_name_prefix(const struct fwnode_handle *fwnode); |
---|
81 | 85 | struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode); |
---|
82 | 86 | struct fwnode_handle *fwnode_get_next_parent( |
---|
83 | 87 | struct fwnode_handle *fwnode); |
---|
| 88 | +struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode); |
---|
| 89 | +unsigned int fwnode_count_parents(const struct fwnode_handle *fwn); |
---|
| 90 | +struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwn, |
---|
| 91 | + unsigned int depth); |
---|
| 92 | +bool fwnode_is_ancestor_of(struct fwnode_handle *test_ancestor, |
---|
| 93 | + struct fwnode_handle *test_child); |
---|
84 | 94 | struct fwnode_handle *fwnode_get_next_child_node( |
---|
85 | 95 | const struct fwnode_handle *fwnode, struct fwnode_handle *child); |
---|
86 | 96 | struct fwnode_handle *fwnode_get_next_available_child_node( |
---|
.. | .. |
---|
163 | 173 | return device_property_read_u64_array(dev, propname, NULL, 0); |
---|
164 | 174 | } |
---|
165 | 175 | |
---|
| 176 | +static inline int device_property_string_array_count(struct device *dev, |
---|
| 177 | + const char *propname) |
---|
| 178 | +{ |
---|
| 179 | + return device_property_read_string_array(dev, propname, NULL, 0); |
---|
| 180 | +} |
---|
| 181 | + |
---|
166 | 182 | static inline bool fwnode_property_read_bool(const struct fwnode_handle *fwnode, |
---|
167 | 183 | const char *propname) |
---|
168 | 184 | { |
---|
.. | .. |
---|
217 | 233 | return fwnode_property_read_u64_array(fwnode, propname, NULL, 0); |
---|
218 | 234 | } |
---|
219 | 235 | |
---|
| 236 | +static inline int |
---|
| 237 | +fwnode_property_string_array_count(const struct fwnode_handle *fwnode, |
---|
| 238 | + const char *propname) |
---|
| 239 | +{ |
---|
| 240 | + return fwnode_property_read_string_array(fwnode, propname, NULL, 0); |
---|
| 241 | +} |
---|
| 242 | + |
---|
| 243 | +struct software_node; |
---|
| 244 | + |
---|
| 245 | +/** |
---|
| 246 | + * struct software_node_ref_args - Reference property with additional arguments |
---|
| 247 | + * @node: Reference to a software node |
---|
| 248 | + * @nargs: Number of elements in @args array |
---|
| 249 | + * @args: Integer arguments |
---|
| 250 | + */ |
---|
| 251 | +struct software_node_ref_args { |
---|
| 252 | + const struct software_node *node; |
---|
| 253 | + unsigned int nargs; |
---|
| 254 | + u64 args[NR_FWNODE_REFERENCE_ARGS]; |
---|
| 255 | +}; |
---|
| 256 | + |
---|
220 | 257 | /** |
---|
221 | 258 | * struct property_entry - "Built-in" device property representation. |
---|
222 | 259 | * @name: Name of the property. |
---|
223 | 260 | * @length: Length of data making up the value. |
---|
224 | | - * @is_array: True when the property is an array. |
---|
| 261 | + * @is_inline: True when the property value is stored inline. |
---|
225 | 262 | * @type: Type of the data in unions. |
---|
226 | | - * @pointer: Pointer to the property (an array of items of the given type). |
---|
227 | | - * @value: Value of the property (when it is a single item of the given type). |
---|
| 263 | + * @pointer: Pointer to the property when it is not stored inline. |
---|
| 264 | + * @value: Value of the property when it is stored inline. |
---|
228 | 265 | */ |
---|
229 | 266 | struct property_entry { |
---|
230 | 267 | const char *name; |
---|
231 | 268 | size_t length; |
---|
232 | | - bool is_array; |
---|
| 269 | + bool is_inline; |
---|
233 | 270 | enum dev_prop_type type; |
---|
234 | 271 | union { |
---|
| 272 | + const void *pointer; |
---|
235 | 273 | union { |
---|
236 | | - const u8 *u8_data; |
---|
237 | | - const u16 *u16_data; |
---|
238 | | - const u32 *u32_data; |
---|
239 | | - const u64 *u64_data; |
---|
240 | | - const char * const *str; |
---|
241 | | - } pointer; |
---|
242 | | - union { |
---|
243 | | - u8 u8_data; |
---|
244 | | - u16 u16_data; |
---|
245 | | - u32 u32_data; |
---|
246 | | - u64 u64_data; |
---|
247 | | - const char *str; |
---|
| 274 | + u8 u8_data[sizeof(u64) / sizeof(u8)]; |
---|
| 275 | + u16 u16_data[sizeof(u64) / sizeof(u16)]; |
---|
| 276 | + u32 u32_data[sizeof(u64) / sizeof(u32)]; |
---|
| 277 | + u64 u64_data[sizeof(u64) / sizeof(u64)]; |
---|
| 278 | + const char *str[sizeof(u64) / sizeof(char *)]; |
---|
248 | 279 | } value; |
---|
249 | 280 | }; |
---|
250 | 281 | }; |
---|
251 | 282 | |
---|
252 | 283 | /* |
---|
253 | | - * Note: the below four initializers for the anonymous union are carefully |
---|
| 284 | + * Note: the below initializers for the anonymous union are carefully |
---|
254 | 285 | * crafted to avoid gcc-4.4.4's problems with initialization of anon unions |
---|
255 | 286 | * and structs. |
---|
256 | 287 | */ |
---|
257 | 288 | |
---|
258 | | -#define PROPERTY_ENTRY_INTEGER_ARRAY(_name_, _type_, _Type_, _val_) \ |
---|
| 289 | +#define __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_) \ |
---|
| 290 | + sizeof(((struct property_entry *)NULL)->value._elem_[0]) |
---|
| 291 | + |
---|
| 292 | +#define __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_, _elsize_, _Type_, \ |
---|
| 293 | + _val_, _len_) \ |
---|
259 | 294 | (struct property_entry) { \ |
---|
260 | 295 | .name = _name_, \ |
---|
261 | | - .length = ARRAY_SIZE(_val_) * sizeof(_type_), \ |
---|
262 | | - .is_array = true, \ |
---|
| 296 | + .length = (_len_) * (_elsize_), \ |
---|
263 | 297 | .type = DEV_PROP_##_Type_, \ |
---|
264 | | - { .pointer = { ._type_##_data = _val_ } }, \ |
---|
| 298 | + { .pointer = _val_ }, \ |
---|
265 | 299 | } |
---|
266 | 300 | |
---|
267 | | -#define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_) \ |
---|
268 | | - PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u8, U8, _val_) |
---|
269 | | -#define PROPERTY_ENTRY_U16_ARRAY(_name_, _val_) \ |
---|
270 | | - PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u16, U16, _val_) |
---|
271 | | -#define PROPERTY_ENTRY_U32_ARRAY(_name_, _val_) \ |
---|
272 | | - PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u32, U32, _val_) |
---|
273 | | -#define PROPERTY_ENTRY_U64_ARRAY(_name_, _val_) \ |
---|
274 | | - PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u64, U64, _val_) |
---|
| 301 | +#define __PROPERTY_ENTRY_ARRAY_LEN(_name_, _elem_, _Type_, _val_, _len_)\ |
---|
| 302 | + __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_, \ |
---|
| 303 | + __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_), \ |
---|
| 304 | + _Type_, _val_, _len_) |
---|
275 | 305 | |
---|
276 | | -#define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_) \ |
---|
277 | | -(struct property_entry) { \ |
---|
278 | | - .name = _name_, \ |
---|
279 | | - .length = ARRAY_SIZE(_val_) * sizeof(const char *), \ |
---|
280 | | - .is_array = true, \ |
---|
281 | | - .type = DEV_PROP_STRING, \ |
---|
282 | | - { .pointer = { .str = _val_ } }, \ |
---|
| 306 | +#define PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, _len_) \ |
---|
| 307 | + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u8_data, U8, _val_, _len_) |
---|
| 308 | +#define PROPERTY_ENTRY_U16_ARRAY_LEN(_name_, _val_, _len_) \ |
---|
| 309 | + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u16_data, U16, _val_, _len_) |
---|
| 310 | +#define PROPERTY_ENTRY_U32_ARRAY_LEN(_name_, _val_, _len_) \ |
---|
| 311 | + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u32_data, U32, _val_, _len_) |
---|
| 312 | +#define PROPERTY_ENTRY_U64_ARRAY_LEN(_name_, _val_, _len_) \ |
---|
| 313 | + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u64_data, U64, _val_, _len_) |
---|
| 314 | +#define PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, _len_) \ |
---|
| 315 | + __PROPERTY_ENTRY_ARRAY_LEN(_name_, str, STRING, _val_, _len_) |
---|
| 316 | +#define PROPERTY_ENTRY_REF_ARRAY_LEN(_name_, _val_, _len_) \ |
---|
| 317 | + __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_, \ |
---|
| 318 | + sizeof(struct software_node_ref_args), \ |
---|
| 319 | + REF, _val_, _len_) |
---|
| 320 | + |
---|
| 321 | +#define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_) \ |
---|
| 322 | + PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) |
---|
| 323 | +#define PROPERTY_ENTRY_U16_ARRAY(_name_, _val_) \ |
---|
| 324 | + PROPERTY_ENTRY_U16_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) |
---|
| 325 | +#define PROPERTY_ENTRY_U32_ARRAY(_name_, _val_) \ |
---|
| 326 | + PROPERTY_ENTRY_U32_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) |
---|
| 327 | +#define PROPERTY_ENTRY_U64_ARRAY(_name_, _val_) \ |
---|
| 328 | + PROPERTY_ENTRY_U64_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) |
---|
| 329 | +#define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_) \ |
---|
| 330 | + PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) |
---|
| 331 | +#define PROPERTY_ENTRY_REF_ARRAY(_name_, _val_) \ |
---|
| 332 | + PROPERTY_ENTRY_REF_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) |
---|
| 333 | + |
---|
| 334 | +#define __PROPERTY_ENTRY_ELEMENT(_name_, _elem_, _Type_, _val_) \ |
---|
| 335 | +(struct property_entry) { \ |
---|
| 336 | + .name = _name_, \ |
---|
| 337 | + .length = __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_), \ |
---|
| 338 | + .is_inline = true, \ |
---|
| 339 | + .type = DEV_PROP_##_Type_, \ |
---|
| 340 | + { .value = { ._elem_[0] = _val_ } }, \ |
---|
283 | 341 | } |
---|
284 | 342 | |
---|
285 | | -#define PROPERTY_ENTRY_INTEGER(_name_, _type_, _Type_, _val_) \ |
---|
286 | | -(struct property_entry) { \ |
---|
287 | | - .name = _name_, \ |
---|
288 | | - .length = sizeof(_type_), \ |
---|
289 | | - .type = DEV_PROP_##_Type_, \ |
---|
290 | | - { .value = { ._type_##_data = _val_ } }, \ |
---|
291 | | -} |
---|
292 | | - |
---|
293 | | -#define PROPERTY_ENTRY_U8(_name_, _val_) \ |
---|
294 | | - PROPERTY_ENTRY_INTEGER(_name_, u8, U8, _val_) |
---|
295 | | -#define PROPERTY_ENTRY_U16(_name_, _val_) \ |
---|
296 | | - PROPERTY_ENTRY_INTEGER(_name_, u16, U16, _val_) |
---|
297 | | -#define PROPERTY_ENTRY_U32(_name_, _val_) \ |
---|
298 | | - PROPERTY_ENTRY_INTEGER(_name_, u32, U32, _val_) |
---|
299 | | -#define PROPERTY_ENTRY_U64(_name_, _val_) \ |
---|
300 | | - PROPERTY_ENTRY_INTEGER(_name_, u64, U64, _val_) |
---|
301 | | - |
---|
302 | | -#define PROPERTY_ENTRY_STRING(_name_, _val_) \ |
---|
303 | | -(struct property_entry) { \ |
---|
304 | | - .name = _name_, \ |
---|
305 | | - .length = sizeof(const char *), \ |
---|
306 | | - .type = DEV_PROP_STRING, \ |
---|
307 | | - { .value = { .str = _val_ } }, \ |
---|
308 | | -} |
---|
| 343 | +#define PROPERTY_ENTRY_U8(_name_, _val_) \ |
---|
| 344 | + __PROPERTY_ENTRY_ELEMENT(_name_, u8_data, U8, _val_) |
---|
| 345 | +#define PROPERTY_ENTRY_U16(_name_, _val_) \ |
---|
| 346 | + __PROPERTY_ENTRY_ELEMENT(_name_, u16_data, U16, _val_) |
---|
| 347 | +#define PROPERTY_ENTRY_U32(_name_, _val_) \ |
---|
| 348 | + __PROPERTY_ENTRY_ELEMENT(_name_, u32_data, U32, _val_) |
---|
| 349 | +#define PROPERTY_ENTRY_U64(_name_, _val_) \ |
---|
| 350 | + __PROPERTY_ENTRY_ELEMENT(_name_, u64_data, U64, _val_) |
---|
| 351 | +#define PROPERTY_ENTRY_STRING(_name_, _val_) \ |
---|
| 352 | + __PROPERTY_ENTRY_ELEMENT(_name_, str, STRING, _val_) |
---|
309 | 353 | |
---|
310 | 354 | #define PROPERTY_ENTRY_BOOL(_name_) \ |
---|
311 | 355 | (struct property_entry) { \ |
---|
312 | 356 | .name = _name_, \ |
---|
| 357 | + .is_inline = true, \ |
---|
| 358 | +} |
---|
| 359 | + |
---|
| 360 | +#define PROPERTY_ENTRY_REF(_name_, _ref_, ...) \ |
---|
| 361 | +(struct property_entry) { \ |
---|
| 362 | + .name = _name_, \ |
---|
| 363 | + .length = sizeof(struct software_node_ref_args), \ |
---|
| 364 | + .type = DEV_PROP_REF, \ |
---|
| 365 | + { .pointer = &(const struct software_node_ref_args) { \ |
---|
| 366 | + .node = _ref_, \ |
---|
| 367 | + .nargs = ARRAY_SIZE(((u64[]){ 0, ##__VA_ARGS__ })) - 1, \ |
---|
| 368 | + .args = { __VA_ARGS__ }, \ |
---|
| 369 | + } }, \ |
---|
313 | 370 | } |
---|
314 | 371 | |
---|
315 | 372 | struct property_entry * |
---|
.. | .. |
---|
348 | 405 | fwnode_graph_get_remote_node(const struct fwnode_handle *fwnode, u32 port, |
---|
349 | 406 | u32 endpoint); |
---|
350 | 407 | |
---|
| 408 | +static inline bool fwnode_graph_is_endpoint(struct fwnode_handle *fwnode) |
---|
| 409 | +{ |
---|
| 410 | + return fwnode_property_present(fwnode, "remote-endpoint"); |
---|
| 411 | +} |
---|
| 412 | + |
---|
| 413 | +/* |
---|
| 414 | + * Fwnode lookup flags |
---|
| 415 | + * |
---|
| 416 | + * @FWNODE_GRAPH_ENDPOINT_NEXT: In the case of no exact match, look for the |
---|
| 417 | + * closest endpoint ID greater than the specified |
---|
| 418 | + * one. |
---|
| 419 | + * @FWNODE_GRAPH_DEVICE_DISABLED: That the device to which the remote |
---|
| 420 | + * endpoint of the given endpoint belongs to, |
---|
| 421 | + * may be disabled. |
---|
| 422 | + */ |
---|
| 423 | +#define FWNODE_GRAPH_ENDPOINT_NEXT BIT(0) |
---|
| 424 | +#define FWNODE_GRAPH_DEVICE_DISABLED BIT(1) |
---|
| 425 | + |
---|
| 426 | +struct fwnode_handle * |
---|
| 427 | +fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode, |
---|
| 428 | + u32 port, u32 endpoint, unsigned long flags); |
---|
| 429 | + |
---|
351 | 430 | #define fwnode_graph_for_each_endpoint(fwnode, child) \ |
---|
352 | 431 | for (child = NULL; \ |
---|
353 | 432 | (child = fwnode_graph_get_next_endpoint(fwnode, child)); ) |
---|
.. | .. |
---|
355 | 434 | int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode, |
---|
356 | 435 | struct fwnode_endpoint *endpoint); |
---|
357 | 436 | |
---|
| 437 | +typedef void *(*devcon_match_fn_t)(struct fwnode_handle *fwnode, const char *id, |
---|
| 438 | + void *data); |
---|
| 439 | + |
---|
| 440 | +void *fwnode_connection_find_match(struct fwnode_handle *fwnode, |
---|
| 441 | + const char *con_id, void *data, |
---|
| 442 | + devcon_match_fn_t match); |
---|
| 443 | + |
---|
| 444 | +static inline void *device_connection_find_match(struct device *dev, |
---|
| 445 | + const char *con_id, void *data, |
---|
| 446 | + devcon_match_fn_t match) |
---|
| 447 | +{ |
---|
| 448 | + return fwnode_connection_find_match(dev_fwnode(dev), con_id, data, match); |
---|
| 449 | +} |
---|
| 450 | + |
---|
| 451 | +/* -------------------------------------------------------------------------- */ |
---|
| 452 | +/* Software fwnode support - when HW description is incomplete or missing */ |
---|
| 453 | + |
---|
| 454 | +/** |
---|
| 455 | + * struct software_node - Software node description |
---|
| 456 | + * @name: Name of the software node |
---|
| 457 | + * @parent: Parent of the software node |
---|
| 458 | + * @properties: Array of device properties |
---|
| 459 | + */ |
---|
| 460 | +struct software_node { |
---|
| 461 | + const char *name; |
---|
| 462 | + const struct software_node *parent; |
---|
| 463 | + const struct property_entry *properties; |
---|
| 464 | +}; |
---|
| 465 | + |
---|
| 466 | +bool is_software_node(const struct fwnode_handle *fwnode); |
---|
| 467 | +const struct software_node * |
---|
| 468 | +to_software_node(const struct fwnode_handle *fwnode); |
---|
| 469 | +struct fwnode_handle *software_node_fwnode(const struct software_node *node); |
---|
| 470 | + |
---|
| 471 | +const struct software_node * |
---|
| 472 | +software_node_find_by_name(const struct software_node *parent, |
---|
| 473 | + const char *name); |
---|
| 474 | + |
---|
| 475 | +int software_node_register_nodes(const struct software_node *nodes); |
---|
| 476 | +void software_node_unregister_nodes(const struct software_node *nodes); |
---|
| 477 | + |
---|
| 478 | +int software_node_register_node_group(const struct software_node **node_group); |
---|
| 479 | +void software_node_unregister_node_group(const struct software_node **node_group); |
---|
| 480 | + |
---|
| 481 | +int software_node_register(const struct software_node *node); |
---|
| 482 | +void software_node_unregister(const struct software_node *node); |
---|
| 483 | + |
---|
| 484 | +int software_node_notify(struct device *dev, unsigned long action); |
---|
| 485 | + |
---|
| 486 | +struct fwnode_handle * |
---|
| 487 | +fwnode_create_software_node(const struct property_entry *properties, |
---|
| 488 | + const struct fwnode_handle *parent); |
---|
| 489 | +void fwnode_remove_software_node(struct fwnode_handle *fwnode); |
---|
| 490 | + |
---|
| 491 | +int device_add_software_node(struct device *dev, const struct software_node *node); |
---|
| 492 | +void device_remove_software_node(struct device *dev); |
---|
| 493 | + |
---|
358 | 494 | #endif /* _LINUX_PROPERTY_H_ */ |
---|