diff options
-rw-r--r-- | drivers/extcon/extcon-class.c | 69 | ||||
-rw-r--r-- | include/linux/extcon.h | 13 |
2 files changed, 82 insertions, 0 deletions
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 7ab21aa6eaa1..f6df68989651 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c | |||
@@ -819,6 +819,75 @@ void extcon_dev_unregister(struct extcon_dev *edev) | |||
819 | } | 819 | } |
820 | EXPORT_SYMBOL_GPL(extcon_dev_unregister); | 820 | EXPORT_SYMBOL_GPL(extcon_dev_unregister); |
821 | 821 | ||
822 | static void devm_extcon_dev_unreg(struct device *dev, void *res) | ||
823 | { | ||
824 | extcon_dev_unregister(*(struct extcon_dev **)res); | ||
825 | } | ||
826 | |||
827 | static int devm_extcon_dev_match(struct device *dev, void *res, void *data) | ||
828 | { | ||
829 | struct extcon_dev **r = res; | ||
830 | |||
831 | if (!r || !*r) { | ||
832 | WARN_ON(!r || !*r); | ||
833 | return 0; | ||
834 | } | ||
835 | |||
836 | return *r == data; | ||
837 | } | ||
838 | |||
839 | /** | ||
840 | * devm_extcon_dev_register() - Resource-managed extcon_dev_register() | ||
841 | * @dev: device to allocate extcon device | ||
842 | * @edev: the new extcon device to register | ||
843 | * | ||
844 | * Managed extcon_dev_register() function. If extcon device is attached with | ||
845 | * this function, that extcon device is automatically unregistered on driver | ||
846 | * detach. Internally this function calls extcon_dev_register() function. | ||
847 | * To get more information, refer that function. | ||
848 | * | ||
849 | * If extcon device is registered with this function and the device needs to be | ||
850 | * unregistered separately, devm_extcon_dev_unregister() should be used. | ||
851 | * | ||
852 | * Returns 0 if success or negaive error number if failure. | ||
853 | */ | ||
854 | int devm_extcon_dev_register(struct device *dev, struct extcon_dev *edev) | ||
855 | { | ||
856 | struct extcon_dev **ptr; | ||
857 | int ret; | ||
858 | |||
859 | ptr = devres_alloc(devm_extcon_dev_unreg, sizeof(*ptr), GFP_KERNEL); | ||
860 | if (!ptr) | ||
861 | return -ENOMEM; | ||
862 | |||
863 | ret = extcon_dev_register(edev); | ||
864 | if (ret) { | ||
865 | devres_free(ptr); | ||
866 | return ret; | ||
867 | } | ||
868 | |||
869 | *ptr = edev; | ||
870 | devres_add(dev, ptr); | ||
871 | |||
872 | return 0; | ||
873 | } | ||
874 | EXPORT_SYMBOL_GPL(devm_extcon_dev_register); | ||
875 | |||
876 | /** | ||
877 | * devm_extcon_dev_unregister() - Resource-managed extcon_dev_unregister() | ||
878 | * @dev: device the extcon belongs to | ||
879 | * @edev: the extcon device to unregister | ||
880 | * | ||
881 | * Unregister extcon device that is registered with devm_extcon_dev_register() | ||
882 | * function. | ||
883 | */ | ||
884 | void devm_extcon_dev_unregister(struct device *dev, struct extcon_dev *edev) | ||
885 | { | ||
886 | WARN_ON(devres_release(dev, devm_extcon_dev_unreg, | ||
887 | devm_extcon_dev_match, edev)); | ||
888 | } | ||
889 | EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister); | ||
890 | |||
822 | #ifdef CONFIG_OF | 891 | #ifdef CONFIG_OF |
823 | /* | 892 | /* |
824 | * extcon_get_edev_by_phandle - Get the extcon device from devicetree | 893 | * extcon_get_edev_by_phandle - Get the extcon device from devicetree |
diff --git a/include/linux/extcon.h b/include/linux/extcon.h index f488145bb2d4..548447be2d8f 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h | |||
@@ -185,6 +185,10 @@ struct extcon_specific_cable_nb { | |||
185 | */ | 185 | */ |
186 | extern int extcon_dev_register(struct extcon_dev *edev); | 186 | extern int extcon_dev_register(struct extcon_dev *edev); |
187 | extern void extcon_dev_unregister(struct extcon_dev *edev); | 187 | extern void extcon_dev_unregister(struct extcon_dev *edev); |
188 | extern int devm_extcon_dev_register(struct device *dev, | ||
189 | struct extcon_dev *edev); | ||
190 | extern void devm_extcon_dev_unregister(struct device *dev, | ||
191 | struct extcon_dev *edev); | ||
188 | extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name); | 192 | extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name); |
189 | 193 | ||
190 | /* | 194 | /* |
@@ -254,6 +258,15 @@ static inline int extcon_dev_register(struct extcon_dev *edev) | |||
254 | 258 | ||
255 | static inline void extcon_dev_unregister(struct extcon_dev *edev) { } | 259 | static inline void extcon_dev_unregister(struct extcon_dev *edev) { } |
256 | 260 | ||
261 | static inline int devm_extcon_dev_register(struct device *dev, | ||
262 | struct extcon_dev *edev) | ||
263 | { | ||
264 | return -EINVAL; | ||
265 | } | ||
266 | |||
267 | static inline void devm_extcon_dev_unregister(struct device *dev, | ||
268 | struct extcon_dev *edev) { } | ||
269 | |||
257 | static inline u32 extcon_get_state(struct extcon_dev *edev) | 270 | static inline u32 extcon_get_state(struct extcon_dev *edev) |
258 | { | 271 | { |
259 | return 0; | 272 | return 0; |