.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
---|
1 | 2 | /* |
---|
2 | 3 | * fwnode.h - Firmware device node object handle type definition. |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2015, Intel Corporation |
---|
5 | 6 | * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License version 2 as |
---|
9 | | - * published by the Free Software Foundation. |
---|
10 | 7 | */ |
---|
11 | 8 | |
---|
12 | 9 | #ifndef _LINUX_FWNODE_H_ |
---|
13 | 10 | #define _LINUX_FWNODE_H_ |
---|
14 | 11 | |
---|
15 | 12 | #include <linux/types.h> |
---|
| 13 | +#include <linux/list.h> |
---|
| 14 | +#include <linux/bits.h> |
---|
| 15 | +#include <linux/err.h> |
---|
16 | 16 | #include <linux/android_kabi.h> |
---|
17 | 17 | |
---|
18 | 18 | struct fwnode_operations; |
---|
19 | 19 | struct device; |
---|
20 | 20 | |
---|
| 21 | +/* |
---|
| 22 | + * fwnode link flags |
---|
| 23 | + * |
---|
| 24 | + * LINKS_ADDED: The fwnode has already be parsed to add fwnode links. |
---|
| 25 | + * NOT_DEVICE: The fwnode will never be populated as a struct device. |
---|
| 26 | + * INITIALIZED: The hardware corresponding to fwnode has been initialized. |
---|
| 27 | + */ |
---|
| 28 | +#define FWNODE_FLAG_LINKS_ADDED BIT(0) |
---|
| 29 | +#define FWNODE_FLAG_NOT_DEVICE BIT(1) |
---|
| 30 | +#define FWNODE_FLAG_INITIALIZED BIT(2) |
---|
| 31 | + |
---|
21 | 32 | struct fwnode_handle { |
---|
22 | 33 | struct fwnode_handle *secondary; |
---|
23 | 34 | const struct fwnode_operations *ops; |
---|
24 | 35 | struct device *dev; |
---|
| 36 | + struct list_head suppliers; |
---|
| 37 | + struct list_head consumers; |
---|
| 38 | + u8 flags; |
---|
| 39 | + ANDROID_KABI_RESERVE(1); |
---|
| 40 | +}; |
---|
25 | 41 | |
---|
| 42 | +struct fwnode_link { |
---|
| 43 | + struct fwnode_handle *supplier; |
---|
| 44 | + struct list_head s_hook; |
---|
| 45 | + struct fwnode_handle *consumer; |
---|
| 46 | + struct list_head c_hook; |
---|
26 | 47 | ANDROID_KABI_RESERVE(1); |
---|
27 | 48 | ANDROID_KABI_RESERVE(2); |
---|
28 | 49 | ANDROID_KABI_RESERVE(3); |
---|
29 | | - ANDROID_KABI_RESERVE(4); |
---|
30 | 50 | }; |
---|
31 | 51 | |
---|
32 | 52 | /** |
---|
.. | .. |
---|
59 | 79 | * struct fwnode_operations - Operations for fwnode interface |
---|
60 | 80 | * @get: Get a reference to an fwnode. |
---|
61 | 81 | * @put: Put a reference to an fwnode. |
---|
| 82 | + * @device_is_available: Return true if the device is available. |
---|
62 | 83 | * @device_get_match_data: Return the device driver match data. |
---|
63 | 84 | * @property_present: Return true if a property is present. |
---|
64 | | - * @property_read_integer_array: Read an array of integer properties. Return |
---|
65 | | - * zero on success, a negative error code |
---|
66 | | - * otherwise. |
---|
| 85 | + * @property_read_int_array: Read an array of integer properties. Return zero on |
---|
| 86 | + * success, a negative error code otherwise. |
---|
67 | 87 | * @property_read_string_array: Read an array of string properties. Return zero |
---|
68 | 88 | * on success, a negative error code otherwise. |
---|
| 89 | + * @get_name: Return the name of an fwnode. |
---|
| 90 | + * @get_name_prefix: Get a prefix for a node (for printing purposes). |
---|
69 | 91 | * @get_parent: Return the parent of an fwnode. |
---|
70 | 92 | * @get_next_child_node: Return the next child node in an iteration. |
---|
71 | 93 | * @get_named_child_node: Return a child node with a given name. |
---|
.. | .. |
---|
75 | 97 | * endpoint node. |
---|
76 | 98 | * @graph_get_port_parent: Return the parent node of a port node. |
---|
77 | 99 | * @graph_parse_endpoint: Parse endpoint for port and endpoint id. |
---|
78 | | - * @add_links: Called after the device corresponding to the fwnode is added |
---|
79 | | - * using device_add(). The function is expected to create device |
---|
80 | | - * links to all the suppliers of the device that are available at |
---|
81 | | - * the time this function is called. The function must NOT stop |
---|
82 | | - * at the first failed device link if other unlinked supplier |
---|
83 | | - * devices are present in the system. This is necessary for the |
---|
84 | | - * driver/bus sync_state() callbacks to work correctly. |
---|
85 | | - * |
---|
86 | | - * For example, say Device-C depends on suppliers Device-S1 and |
---|
87 | | - * Device-S2 and the dependency is listed in that order in the |
---|
88 | | - * firmware. Say, S1 gets populated from the firmware after |
---|
89 | | - * late_initcall_sync(). Say S2 is populated and probed way |
---|
90 | | - * before that in device_initcall(). When C is populated, if this |
---|
91 | | - * add_links() function doesn't continue past a "failed linking to |
---|
92 | | - * S1" and continue linking C to S2, then S2 will get a |
---|
93 | | - * sync_state() callback before C is probed. This is because from |
---|
94 | | - * the perspective of S2, C was never a consumer when its |
---|
95 | | - * sync_state() evaluation is done. To avoid this, the add_links() |
---|
96 | | - * function has to go through all available suppliers of the |
---|
97 | | - * device (that corresponds to this fwnode) and link to them |
---|
98 | | - * before returning. |
---|
99 | | - * |
---|
100 | | - * If some suppliers are not yet available (indicated by an error |
---|
101 | | - * return value), this function will be called again when other |
---|
102 | | - * devices are added to allow creating device links to any newly |
---|
103 | | - * available suppliers. |
---|
104 | | - * |
---|
105 | | - * Return 0 if device links have been successfully created to all |
---|
106 | | - * the known suppliers of this device or if the supplier |
---|
107 | | - * information is not known. |
---|
108 | | - * |
---|
109 | | - * Return -ENODEV if the suppliers needed for probing this device |
---|
110 | | - * have not been registered yet (because device links can only be |
---|
111 | | - * created to devices registered with the driver core). |
---|
112 | | - * |
---|
113 | | - * Return -EAGAIN if some of the suppliers of this device have not |
---|
114 | | - * been registered yet, but none of those suppliers are necessary |
---|
115 | | - * for probing the device. |
---|
| 100 | + * @add_links: Create fwnode links to all the suppliers of the fwnode. Return |
---|
| 101 | + * zero on success, a negative error code otherwise. |
---|
116 | 102 | */ |
---|
117 | 103 | struct fwnode_operations { |
---|
118 | 104 | struct fwnode_handle *(*get)(struct fwnode_handle *fwnode); |
---|
.. | .. |
---|
130 | 116 | (*property_read_string_array)(const struct fwnode_handle *fwnode_handle, |
---|
131 | 117 | const char *propname, const char **val, |
---|
132 | 118 | size_t nval); |
---|
| 119 | + const char *(*get_name)(const struct fwnode_handle *fwnode); |
---|
| 120 | + const char *(*get_name_prefix)(const struct fwnode_handle *fwnode); |
---|
133 | 121 | struct fwnode_handle *(*get_parent)(const struct fwnode_handle *fwnode); |
---|
134 | 122 | struct fwnode_handle * |
---|
135 | 123 | (*get_next_child_node)(const struct fwnode_handle *fwnode, |
---|
.. | .. |
---|
150 | 138 | (*graph_get_port_parent)(struct fwnode_handle *fwnode); |
---|
151 | 139 | int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode, |
---|
152 | 140 | struct fwnode_endpoint *endpoint); |
---|
153 | | - int (*add_links)(const struct fwnode_handle *fwnode, |
---|
154 | | - struct device *dev); |
---|
| 141 | + int (*add_links)(struct fwnode_handle *fwnode); |
---|
155 | 142 | }; |
---|
156 | 143 | |
---|
157 | 144 | #define fwnode_has_op(fwnode, op) \ |
---|
.. | .. |
---|
160 | 147 | (fwnode ? (fwnode_has_op(fwnode, op) ? \ |
---|
161 | 148 | (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : -ENXIO) : \ |
---|
162 | 149 | -EINVAL) |
---|
163 | | -#define fwnode_call_bool_op(fwnode, op, ...) \ |
---|
164 | | - (fwnode ? (fwnode_has_op(fwnode, op) ? \ |
---|
165 | | - (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : false) : \ |
---|
166 | | - false) |
---|
| 150 | + |
---|
| 151 | +#define fwnode_call_bool_op(fwnode, op, ...) \ |
---|
| 152 | + (fwnode_has_op(fwnode, op) ? \ |
---|
| 153 | + (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : false) |
---|
| 154 | + |
---|
167 | 155 | #define fwnode_call_ptr_op(fwnode, op, ...) \ |
---|
168 | 156 | (fwnode_has_op(fwnode, op) ? \ |
---|
169 | 157 | (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : NULL) |
---|
.. | .. |
---|
174 | 162 | } while (false) |
---|
175 | 163 | #define get_dev_from_fwnode(fwnode) get_device((fwnode)->dev) |
---|
176 | 164 | |
---|
177 | | -void fw_devlink_pause(void); |
---|
178 | | -void fw_devlink_resume(void); |
---|
| 165 | +static inline void fwnode_init(struct fwnode_handle *fwnode, |
---|
| 166 | + const struct fwnode_operations *ops) |
---|
| 167 | +{ |
---|
| 168 | + fwnode->ops = ops; |
---|
| 169 | + INIT_LIST_HEAD(&fwnode->consumers); |
---|
| 170 | + INIT_LIST_HEAD(&fwnode->suppliers); |
---|
| 171 | +} |
---|
| 172 | + |
---|
| 173 | +static inline void fwnode_dev_initialized(struct fwnode_handle *fwnode, |
---|
| 174 | + bool initialized) |
---|
| 175 | +{ |
---|
| 176 | + if (IS_ERR_OR_NULL(fwnode)) |
---|
| 177 | + return; |
---|
| 178 | + |
---|
| 179 | + if (initialized) |
---|
| 180 | + fwnode->flags |= FWNODE_FLAG_INITIALIZED; |
---|
| 181 | + else |
---|
| 182 | + fwnode->flags &= ~FWNODE_FLAG_INITIALIZED; |
---|
| 183 | +} |
---|
| 184 | + |
---|
| 185 | +extern u32 fw_devlink_get_flags(void); |
---|
| 186 | +extern bool fw_devlink_is_strict(void); |
---|
| 187 | +int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup); |
---|
| 188 | +void fwnode_links_purge(struct fwnode_handle *fwnode); |
---|
| 189 | + |
---|
179 | 190 | #endif |
---|