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 |