| .. | .. |
|---|
| 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 |
|---|