diff options
| -rw-r--r-- | drivers/base/core.c | 51 | ||||
| -rw-r--r-- | include/linux/acpi.h | 4 | ||||
| -rw-r--r-- | include/linux/device.h | 3 | ||||
| -rw-r--r-- | include/linux/fwnode.h | 1 |
4 files changed, 57 insertions, 2 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 07304a3b9ee2..c7e2a9a70865 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
| 14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
| 15 | #include <linux/fwnode.h> | ||
| 15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| @@ -2133,3 +2134,53 @@ define_dev_printk_level(dev_notice, KERN_NOTICE); | |||
| 2133 | define_dev_printk_level(_dev_info, KERN_INFO); | 2134 | define_dev_printk_level(_dev_info, KERN_INFO); |
| 2134 | 2135 | ||
| 2135 | #endif | 2136 | #endif |
| 2137 | |||
| 2138 | static inline bool fwnode_is_primary(struct fwnode_handle *fwnode) | ||
| 2139 | { | ||
| 2140 | return fwnode && !IS_ERR(fwnode->secondary); | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | /** | ||
| 2144 | * set_primary_fwnode - Change the primary firmware node of a given device. | ||
| 2145 | * @dev: Device to handle. | ||
| 2146 | * @fwnode: New primary firmware node of the device. | ||
| 2147 | * | ||
| 2148 | * Set the device's firmware node pointer to @fwnode, but if a secondary | ||
| 2149 | * firmware node of the device is present, preserve it. | ||
| 2150 | */ | ||
| 2151 | void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode) | ||
| 2152 | { | ||
| 2153 | if (fwnode) { | ||
| 2154 | struct fwnode_handle *fn = dev->fwnode; | ||
| 2155 | |||
| 2156 | if (fwnode_is_primary(fn)) | ||
| 2157 | fn = fn->secondary; | ||
| 2158 | |||
| 2159 | fwnode->secondary = fn; | ||
| 2160 | dev->fwnode = fwnode; | ||
| 2161 | } else { | ||
| 2162 | dev->fwnode = fwnode_is_primary(dev->fwnode) ? | ||
| 2163 | dev->fwnode->secondary : NULL; | ||
| 2164 | } | ||
| 2165 | } | ||
| 2166 | EXPORT_SYMBOL_GPL(set_primary_fwnode); | ||
| 2167 | |||
| 2168 | /** | ||
| 2169 | * set_secondary_fwnode - Change the secondary firmware node of a given device. | ||
| 2170 | * @dev: Device to handle. | ||
| 2171 | * @fwnode: New secondary firmware node of the device. | ||
| 2172 | * | ||
| 2173 | * If a primary firmware node of the device is present, set its secondary | ||
| 2174 | * pointer to @fwnode. Otherwise, set the device's firmware node pointer to | ||
| 2175 | * @fwnode. | ||
| 2176 | */ | ||
| 2177 | void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode) | ||
| 2178 | { | ||
| 2179 | if (fwnode) | ||
| 2180 | fwnode->secondary = ERR_PTR(-ENODEV); | ||
| 2181 | |||
| 2182 | if (fwnode_is_primary(dev->fwnode)) | ||
| 2183 | dev->fwnode->secondary = fwnode; | ||
| 2184 | else | ||
| 2185 | dev->fwnode = fwnode; | ||
| 2186 | } | ||
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index ec488d03b518..dd12127f171c 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
| @@ -54,8 +54,8 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) | |||
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | #define ACPI_COMPANION(dev) acpi_node((dev)->fwnode) | 56 | #define ACPI_COMPANION(dev) acpi_node((dev)->fwnode) |
| 57 | #define ACPI_COMPANION_SET(dev, adev) (dev)->fwnode = (adev) ? \ | 57 | #define ACPI_COMPANION_SET(dev, adev) set_primary_fwnode(dev, (adev) ? \ |
| 58 | acpi_fwnode_handle(adev) : NULL | 58 | acpi_fwnode_handle(adev) : NULL) |
| 59 | #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) | 59 | #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) |
| 60 | 60 | ||
| 61 | static inline bool has_acpi_companion(struct device *dev) | 61 | static inline bool has_acpi_companion(struct device *dev) |
diff --git a/include/linux/device.h b/include/linux/device.h index badef20b876a..324d02add7b4 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
| @@ -940,6 +940,9 @@ extern void unlock_device_hotplug(void); | |||
| 940 | extern int lock_device_hotplug_sysfs(void); | 940 | extern int lock_device_hotplug_sysfs(void); |
| 941 | extern int device_offline(struct device *dev); | 941 | extern int device_offline(struct device *dev); |
| 942 | extern int device_online(struct device *dev); | 942 | extern int device_online(struct device *dev); |
| 943 | extern void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode); | ||
| 944 | extern void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode); | ||
| 945 | |||
| 943 | /* | 946 | /* |
| 944 | * Root device objects for grouping under /sys/devices | 947 | * Root device objects for grouping under /sys/devices |
| 945 | */ | 948 | */ |
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 17bb5f039509..fc30b84b532a 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h | |||
| @@ -20,6 +20,7 @@ enum fwnode_type { | |||
| 20 | 20 | ||
| 21 | struct fwnode_handle { | 21 | struct fwnode_handle { |
| 22 | enum fwnode_type type; | 22 | enum fwnode_type type; |
| 23 | struct fwnode_handle *secondary; | ||
| 23 | }; | 24 | }; |
| 24 | 25 | ||
| 25 | #endif | 26 | #endif |
