software node: implement reference properties
[linux-block.git] / include / linux / property.h
index 9b3d4ca3a73a9eca0266e16c64c933034d7fb3a3..3df7089f0dbdd3f4f89c57dd3958ceeff448a3d2 100644 (file)
@@ -22,7 +22,7 @@ enum dev_prop_type {
        DEV_PROP_U32,
        DEV_PROP_U64,
        DEV_PROP_STRING,
-       DEV_PROP_MAX,
+       DEV_PROP_REF,
 };
 
 enum dev_dma_attr {
@@ -80,9 +80,14 @@ struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode,
                                            const char *name,
                                            unsigned int index);
 
+const char *fwnode_get_name(const struct fwnode_handle *fwnode);
+const char *fwnode_get_name_prefix(const struct fwnode_handle *fwnode);
 struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode);
 struct fwnode_handle *fwnode_get_next_parent(
        struct fwnode_handle *fwnode);
+unsigned int fwnode_count_parents(const struct fwnode_handle *fwn);
+struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwn,
+                                           unsigned int depth);
 struct fwnode_handle *fwnode_get_next_child_node(
        const struct fwnode_handle *fwnode, struct fwnode_handle *child);
 struct fwnode_handle *fwnode_get_next_available_child_node(
@@ -219,99 +224,133 @@ static inline int fwnode_property_count_u64(const struct fwnode_handle *fwnode,
        return fwnode_property_read_u64_array(fwnode, propname, NULL, 0);
 }
 
+struct software_node;
+
+/**
+ * struct software_node_ref_args - Reference property with additional arguments
+ * @node: Reference to a software node
+ * @nargs: Number of elements in @args array
+ * @args: Integer arguments
+ */
+struct software_node_ref_args {
+       const struct software_node *node;
+       unsigned int nargs;
+       u64 args[NR_FWNODE_REFERENCE_ARGS];
+};
+
 /**
  * struct property_entry - "Built-in" device property representation.
  * @name: Name of the property.
  * @length: Length of data making up the value.
- * @is_array: True when the property is an array.
+ * @is_inline: True when the property value is stored inline.
  * @type: Type of the data in unions.
- * @pointer: Pointer to the property (an array of items of the given type).
- * @value: Value of the property (when it is a single item of the given type).
+ * @pointer: Pointer to the property when it is not stored inline.
+ * @value: Value of the property when it is stored inline.
  */
 struct property_entry {
        const char *name;
        size_t length;
-       bool is_array;
+       bool is_inline;
        enum dev_prop_type type;
        union {
+               const void *pointer;
                union {
-                       const u8 *u8_data;
-                       const u16 *u16_data;
-                       const u32 *u32_data;
-                       const u64 *u64_data;
-                       const char * const *str;
-               } pointer;
-               union {
-                       u8 u8_data;
-                       u16 u16_data;
-                       u32 u32_data;
-                       u64 u64_data;
-                       const char *str;
+                       u8 u8_data[sizeof(u64) / sizeof(u8)];
+                       u16 u16_data[sizeof(u64) / sizeof(u16)];
+                       u32 u32_data[sizeof(u64) / sizeof(u32)];
+                       u64 u64_data[sizeof(u64) / sizeof(u64)];
+                       const char *str[sizeof(u64) / sizeof(char *)];
                } value;
        };
 };
 
 /*
- * Note: the below four initializers for the anonymous union are carefully
+ * Note: the below initializers for the anonymous union are carefully
  * crafted to avoid gcc-4.4.4's problems with initialization of anon unions
  * and structs.
  */
 
-#define PROPERTY_ENTRY_INTEGER_ARRAY(_name_, _type_, _Type_, _val_)    \
+#define __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_)                          \
+       sizeof(((struct property_entry *)NULL)->value._elem_[0])
+
+#define __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_, _elsize_, _Type_,    \
+                                         _val_, _len_)                 \
 (struct property_entry) {                                              \
        .name = _name_,                                                 \
-       .length = ARRAY_SIZE(_val_) * sizeof(_type_),                   \
-       .is_array = true,                                               \
+       .length = (_len_) * (_elsize_),                                 \
        .type = DEV_PROP_##_Type_,                                      \
-       { .pointer = { ._type_##_data = _val_ } },                      \
+       { .pointer = _val_ },                                           \
 }
 
-#define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_)                 \
-       PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u8, U8, _val_)
-#define PROPERTY_ENTRY_U16_ARRAY(_name_, _val_)                        \
-       PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u16, U16, _val_)
-#define PROPERTY_ENTRY_U32_ARRAY(_name_, _val_)                        \
-       PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u32, U32, _val_)
-#define PROPERTY_ENTRY_U64_ARRAY(_name_, _val_)                        \
-       PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u64, U64, _val_)
-
-#define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_)             \
-(struct property_entry) {                                      \
-       .name = _name_,                                         \
-       .length = ARRAY_SIZE(_val_) * sizeof(const char *),     \
-       .is_array = true,                                       \
-       .type = DEV_PROP_STRING,                                \
-       { .pointer = { .str = _val_ } },                        \
+#define __PROPERTY_ENTRY_ARRAY_LEN(_name_, _elem_, _Type_, _val_, _len_)\
+       __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_,                       \
+                               __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_),  \
+                               _Type_, _val_, _len_)
+
+#define PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, _len_)              \
+       __PROPERTY_ENTRY_ARRAY_LEN(_name_, u8_data, U8, _val_, _len_)
+#define PROPERTY_ENTRY_U16_ARRAY_LEN(_name_, _val_, _len_)             \
+       __PROPERTY_ENTRY_ARRAY_LEN(_name_, u16_data, U16, _val_, _len_)
+#define PROPERTY_ENTRY_U32_ARRAY_LEN(_name_, _val_, _len_)             \
+       __PROPERTY_ENTRY_ARRAY_LEN(_name_, u32_data, U32, _val_, _len_)
+#define PROPERTY_ENTRY_U64_ARRAY_LEN(_name_, _val_, _len_)             \
+       __PROPERTY_ENTRY_ARRAY_LEN(_name_, u64_data, U64, _val_, _len_)
+#define PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, _len_)          \
+       __PROPERTY_ENTRY_ARRAY_LEN(_name_, str, STRING, _val_, _len_)
+#define PROPERTY_ENTRY_REF_ARRAY_LEN(_name_, _val_, _len_)             \
+       __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_,                       \
+                               sizeof(struct software_node_ref_args),  \
+                               REF, _val_, _len_)
+
+#define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_)                         \
+       PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
+#define PROPERTY_ENTRY_U16_ARRAY(_name_, _val_)                                \
+       PROPERTY_ENTRY_U16_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
+#define PROPERTY_ENTRY_U32_ARRAY(_name_, _val_)                                \
+       PROPERTY_ENTRY_U32_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
+#define PROPERTY_ENTRY_U64_ARRAY(_name_, _val_)                                \
+       PROPERTY_ENTRY_U64_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
+#define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_)                     \
+       PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
+#define PROPERTY_ENTRY_REF_ARRAY(_name_, _val_)                        \
+       PROPERTY_ENTRY_REF_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
+
+#define __PROPERTY_ENTRY_ELEMENT(_name_, _elem_, _Type_, _val_)                \
+(struct property_entry) {                                              \
+       .name = _name_,                                                 \
+       .length = __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_),                \
+       .is_inline = true,                                              \
+       .type = DEV_PROP_##_Type_,                                      \
+       { .value = { ._elem_[0] = _val_ } },                            \
 }
 
-#define PROPERTY_ENTRY_INTEGER(_name_, _type_, _Type_, _val_)  \
-(struct property_entry) {                                      \
-       .name = _name_,                                         \
-       .length = sizeof(_type_),                               \
-       .type = DEV_PROP_##_Type_,                              \
-       { .value = { ._type_##_data = _val_ } },                \
-}
-
-#define PROPERTY_ENTRY_U8(_name_, _val_)               \
-       PROPERTY_ENTRY_INTEGER(_name_, u8, U8, _val_)
-#define PROPERTY_ENTRY_U16(_name_, _val_)              \
-       PROPERTY_ENTRY_INTEGER(_name_, u16, U16, _val_)
-#define PROPERTY_ENTRY_U32(_name_, _val_)              \
-       PROPERTY_ENTRY_INTEGER(_name_, u32, U32, _val_)
-#define PROPERTY_ENTRY_U64(_name_, _val_)              \
-       PROPERTY_ENTRY_INTEGER(_name_, u64, U64, _val_)
-
-#define PROPERTY_ENTRY_STRING(_name_, _val_)           \
-(struct property_entry) {                              \
-       .name = _name_,                                 \
-       .length = sizeof(const char *),                 \
-       .type = DEV_PROP_STRING,                        \
-       { .value = { .str = _val_ } },                  \
-}
+#define PROPERTY_ENTRY_U8(_name_, _val_)                               \
+       __PROPERTY_ENTRY_ELEMENT(_name_, u8_data, U8, _val_)
+#define PROPERTY_ENTRY_U16(_name_, _val_)                              \
+       __PROPERTY_ENTRY_ELEMENT(_name_, u16_data, U16, _val_)
+#define PROPERTY_ENTRY_U32(_name_, _val_)                              \
+       __PROPERTY_ENTRY_ELEMENT(_name_, u32_data, U32, _val_)
+#define PROPERTY_ENTRY_U64(_name_, _val_)                              \
+       __PROPERTY_ENTRY_ELEMENT(_name_, u64_data, U64, _val_)
+#define PROPERTY_ENTRY_STRING(_name_, _val_)                           \
+       __PROPERTY_ENTRY_ELEMENT(_name_, str, STRING, _val_)
 
 #define PROPERTY_ENTRY_BOOL(_name_)            \
 (struct property_entry) {                      \
        .name = _name_,                         \
+       .is_inline = true,                      \
+}
+
+#define PROPERTY_ENTRY_REF(_name_, _ref_, ...)                         \
+(struct property_entry) {                                              \
+       .name = _name_,                                                 \
+       .length = sizeof(struct software_node_ref_args),                \
+       .type = DEV_PROP_REF,                                           \
+       { .pointer = &(const struct software_node_ref_args) {           \
+               .node = _ref_,                                          \
+               .nargs = ARRAY_SIZE(((u64[]){ 0, ##__VA_ARGS__ })) - 1, \
+               .args = { __VA_ARGS__ },                                \
+       } },                                                            \
 }
 
 struct property_entry *
@@ -377,20 +416,6 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
 /* -------------------------------------------------------------------------- */
 /* Software fwnode support - when HW description is incomplete or missing */
 
-struct software_node;
-
-/**
- * struct software_node_ref_args - Reference with additional arguments
- * @node: Reference to a software node
- * @nargs: Number of elements in @args array
- * @args: Integer arguments
- */
-struct software_node_ref_args {
-       const struct software_node *node;
-       unsigned int nargs;
-       u64 args[NR_FWNODE_REFERENCE_ARGS];
-};
-
 /**
  * struct software_node_reference - Named software node reference property
  * @name: Name of the property
@@ -418,7 +443,8 @@ struct software_node {
 };
 
 bool is_software_node(const struct fwnode_handle *fwnode);
-const struct software_node *to_software_node(struct fwnode_handle *fwnode);
+const struct software_node *
+to_software_node(const struct fwnode_handle *fwnode);
 struct fwnode_handle *software_node_fwnode(const struct software_node *node);
 
 const struct software_node *