Lines Matching +full:device +full:- +full:id
1 // SPDX-License-Identifier: GPL-2.0-only
3 * drivers/extcon/extcon.c - External Connector (extcon) framework.
20 #include <linux/device.h>
33 unsigned int id; member
39 .id = EXTCON_NONE,
46 .id = EXTCON_USB,
51 .id = EXTCON_USB_HOST,
52 .name = "USB-HOST",
58 .id = EXTCON_CHG_USB_SDP,
63 .id = EXTCON_CHG_USB_DCP,
68 .id = EXTCON_CHG_USB_CDP,
73 .id = EXTCON_CHG_USB_ACA,
78 .id = EXTCON_CHG_USB_FAST,
79 .name = "FAST-CHARGER",
83 .id = EXTCON_CHG_USB_SLOW,
84 .name = "SLOW-CHARGER",
88 .id = EXTCON_CHG_WPT,
93 .id = EXTCON_CHG_USB_PD,
100 .id = EXTCON_JACK_MICROPHONE,
105 .id = EXTCON_JACK_HEADPHONE,
110 .id = EXTCON_JACK_LINE_IN,
111 .name = "LINE-IN",
115 .id = EXTCON_JACK_LINE_OUT,
116 .name = "LINE-OUT",
120 .id = EXTCON_JACK_VIDEO_IN,
121 .name = "VIDEO-IN",
125 .id = EXTCON_JACK_VIDEO_OUT,
126 .name = "VIDEO-OUT",
130 .id = EXTCON_JACK_SPDIF_IN,
131 .name = "SPDIF-IN",
135 .id = EXTCON_JACK_SPDIF_OUT,
136 .name = "SPDIF-OUT",
142 .id = EXTCON_DISP_HDMI,
147 .id = EXTCON_DISP_MHL,
152 .id = EXTCON_DISP_DVI,
157 .id = EXTCON_DISP_VGA,
162 .id = EXTCON_DISP_DP,
167 .id = EXTCON_DISP_HMD,
174 .id = EXTCON_DOCK,
179 .id = EXTCON_JIG,
184 .id = EXTCON_MECHANICAL,
192 * struct extcon_cable - An internal data for an external connector.
193 * @edev: the extcon device
230 if (!edev->mutually_exclusive) in check_mutually_exclusive()
233 for (i = 0; edev->mutually_exclusive[i]; i++) { in check_mutually_exclusive()
235 u32 correspondants = new_state & edev->mutually_exclusive[i]; in check_mutually_exclusive()
246 static int find_cable_index_by_id(struct extcon_dev *edev, const unsigned int id) in find_cable_index_by_id() argument
250 /* Find the the index of extcon cable in edev->supported_cable */ in find_cable_index_by_id()
251 for (i = 0; i < edev->max_supported; i++) { in find_cable_index_by_id()
252 if (edev->supported_cable[i] == id) in find_cable_index_by_id()
256 return -EINVAL; in find_cable_index_by_id()
271 return -EINVAL; in get_extcon_type()
277 return !!(edev->state & BIT(index)); in is_extcon_attached()
283 int state = !!(edev->state & BIT(index)); in is_extcon_changed()
287 static bool is_extcon_property_supported(unsigned int id, unsigned int prop) in is_extcon_property_supported() argument
296 /* Check whether a specific extcon id supports the property or not. */ in is_extcon_property_supported()
297 return !!(extcon_info[id].type & type); in is_extcon_property_supported()
301 unsigned int id, int index,unsigned int prop) in is_extcon_property_capability() argument
311 cable = &edev->cables[index]; in is_extcon_property_capability()
315 ret = test_bit(prop - EXTCON_PROP_USB_MIN, cable->usb_bits); in is_extcon_property_capability()
318 ret = test_bit(prop - EXTCON_PROP_CHG_MIN, cable->chg_bits); in is_extcon_property_capability()
321 ret = test_bit(prop - EXTCON_PROP_JACK_MIN, cable->jack_bits); in is_extcon_property_capability()
324 ret = test_bit(prop - EXTCON_PROP_DISP_MIN, cable->disp_bits); in is_extcon_property_capability()
327 ret = -EINVAL; in is_extcon_property_capability()
333 static void init_property(struct extcon_dev *edev, unsigned int id, int index) in init_property() argument
335 unsigned int type = extcon_info[id].type; in init_property()
336 struct extcon_cable *cable = &edev->cables[index]; in init_property()
339 memset(cable->usb_propval, 0, sizeof(cable->usb_propval)); in init_property()
341 memset(cable->chg_propval, 0, sizeof(cable->chg_propval)); in init_property()
343 memset(cable->jack_propval, 0, sizeof(cable->jack_propval)); in init_property()
345 memset(cable->disp_propval, 0, sizeof(cable->disp_propval)); in init_property()
348 static ssize_t state_show(struct device *dev, struct device_attribute *attr, in state_show()
354 if (edev->max_supported == 0) in state_show()
355 return sprintf(buf, "%u\n", edev->state); in state_show()
357 for (i = 0; i < edev->max_supported; i++) { in state_show()
359 extcon_info[edev->supported_cable[i]].name, in state_show()
360 !!(edev->state & BIT(i))); in state_show()
367 static ssize_t name_show(struct device *dev, struct device_attribute *attr, in name_show()
372 return sprintf(buf, "%s\n", edev->name); in name_show()
376 static ssize_t cable_name_show(struct device *dev, in cable_name_show()
381 int i = cable->cable_index; in cable_name_show()
384 extcon_info[cable->edev->supported_cable[i]].name); in cable_name_show()
387 static ssize_t cable_state_show(struct device *dev, in cable_state_show()
393 int i = cable->cable_index; in cable_state_show()
396 extcon_get_state(cable->edev, cable->edev->supported_cable[i])); in cable_state_show()
400 * extcon_sync() - Synchronize the state for an external connector.
401 * @edev: the extcon device
408 int extcon_sync(struct extcon_dev *edev, unsigned int id) in extcon_sync() argument
421 return -EINVAL; in extcon_sync()
423 index = find_cable_index_by_id(edev, id); in extcon_sync()
427 spin_lock_irqsave(&edev->lock, flags); in extcon_sync()
428 state = !!(edev->state & BIT(index)); in extcon_sync()
429 spin_unlock_irqrestore(&edev->lock, flags); in extcon_sync()
435 raw_notifier_call_chain(&edev->nh[index], state, edev); in extcon_sync()
441 raw_notifier_call_chain(&edev->nh_all, state, edev); in extcon_sync()
443 spin_lock_irqsave(&edev->lock, flags); in extcon_sync()
448 spin_unlock_irqrestore(&edev->lock, flags); in extcon_sync()
450 dev_err(&edev->dev, "out of memory in extcon_set_state\n"); in extcon_sync()
451 kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE); in extcon_sync()
453 return -ENOMEM; in extcon_sync()
456 length = name_show(&edev->dev, NULL, prop_buf); in extcon_sync()
458 if (prop_buf[length - 1] == '\n') in extcon_sync()
459 prop_buf[length - 1] = 0; in extcon_sync()
464 length = state_show(&edev->dev, NULL, prop_buf); in extcon_sync()
466 if (prop_buf[length - 1] == '\n') in extcon_sync()
467 prop_buf[length - 1] = 0; in extcon_sync()
474 spin_unlock_irqrestore(&edev->lock, flags); in extcon_sync()
475 kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp); in extcon_sync()
483 * extcon_get_state() - Get the state of an external connector.
484 * @edev: the extcon device
485 * @id: the unique id indicating an external connector
489 int extcon_get_state(struct extcon_dev *edev, const unsigned int id) in extcon_get_state() argument
495 return -EINVAL; in extcon_get_state()
497 index = find_cable_index_by_id(edev, id); in extcon_get_state()
501 spin_lock_irqsave(&edev->lock, flags); in extcon_get_state()
503 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_state()
510 * extcon_set_state() - Set the state of an external connector.
511 * @edev: the extcon device
512 * @id: the unique id indicating an external connector
522 int extcon_set_state(struct extcon_dev *edev, unsigned int id, bool state) in extcon_set_state() argument
528 return -EINVAL; in extcon_set_state()
530 index = find_cable_index_by_id(edev, id); in extcon_set_state()
534 spin_lock_irqsave(&edev->lock, flags); in extcon_set_state()
541 (edev->state & ~BIT(index)) | (state & BIT(index)))) { in extcon_set_state()
542 ret = -EPERM; in extcon_set_state()
551 init_property(edev, id, index); in extcon_set_state()
555 edev->state |= BIT(index); in extcon_set_state()
557 edev->state &= ~(BIT(index)); in extcon_set_state()
559 spin_unlock_irqrestore(&edev->lock, flags); in extcon_set_state()
566 * extcon_set_state_sync() - Set the state of an external connector with sync.
567 * @edev: the extcon device
568 * @id: the unique id indicating an external connector
577 int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id, bool state) in extcon_set_state_sync() argument
582 index = find_cable_index_by_id(edev, id); in extcon_set_state_sync()
587 spin_lock_irqsave(&edev->lock, flags); in extcon_set_state_sync()
589 spin_unlock_irqrestore(&edev->lock, flags); in extcon_set_state_sync()
593 ret = extcon_set_state(edev, id, state); in extcon_set_state_sync()
597 return extcon_sync(edev, id); in extcon_set_state_sync()
602 * extcon_get_property() - Get the property value of an external connector.
603 * @edev: the extcon device
604 * @id: the unique id indicating an external connector
605 * @prop: the property id indicating an extcon property
615 int extcon_get_property(struct extcon_dev *edev, unsigned int id, in extcon_get_property() argument
626 return -EINVAL; in extcon_get_property()
629 if (!is_extcon_property_supported(id, prop)) in extcon_get_property()
630 return -EINVAL; in extcon_get_property()
632 /* Find the cable index of external connector by using id */ in extcon_get_property()
633 index = find_cable_index_by_id(edev, id); in extcon_get_property()
637 spin_lock_irqsave(&edev->lock, flags); in extcon_get_property()
640 if (!is_extcon_property_capability(edev, id, index, prop)) { in extcon_get_property()
641 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_property()
642 return -EPERM; in extcon_get_property()
651 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_property()
655 cable = &edev->cables[index]; in extcon_get_property()
660 *prop_val = cable->usb_propval[prop - EXTCON_PROP_USB_MIN]; in extcon_get_property()
663 *prop_val = cable->chg_propval[prop - EXTCON_PROP_CHG_MIN]; in extcon_get_property()
666 *prop_val = cable->jack_propval[prop - EXTCON_PROP_JACK_MIN]; in extcon_get_property()
669 *prop_val = cable->disp_propval[prop - EXTCON_PROP_DISP_MIN]; in extcon_get_property()
672 ret = -EINVAL; in extcon_get_property()
676 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_property()
683 * extcon_set_property() - Set the property value of an external connector.
684 * @edev: the extcon device
685 * @id: the unique id indicating an external connector
686 * @prop: the property id indicating an extcon property
694 int extcon_set_property(struct extcon_dev *edev, unsigned int id, in extcon_set_property() argument
703 return -EINVAL; in extcon_set_property()
706 if (!is_extcon_property_supported(id, prop)) in extcon_set_property()
707 return -EINVAL; in extcon_set_property()
709 /* Find the cable index of external connector by using id */ in extcon_set_property()
710 index = find_cable_index_by_id(edev, id); in extcon_set_property()
714 spin_lock_irqsave(&edev->lock, flags); in extcon_set_property()
717 if (!is_extcon_property_capability(edev, id, index, prop)) { in extcon_set_property()
718 spin_unlock_irqrestore(&edev->lock, flags); in extcon_set_property()
719 return -EPERM; in extcon_set_property()
722 cable = &edev->cables[index]; in extcon_set_property()
727 cable->usb_propval[prop - EXTCON_PROP_USB_MIN] = prop_val; in extcon_set_property()
730 cable->chg_propval[prop - EXTCON_PROP_CHG_MIN] = prop_val; in extcon_set_property()
733 cable->jack_propval[prop - EXTCON_PROP_JACK_MIN] = prop_val; in extcon_set_property()
736 cable->disp_propval[prop - EXTCON_PROP_DISP_MIN] = prop_val; in extcon_set_property()
739 ret = -EINVAL; in extcon_set_property()
743 spin_unlock_irqrestore(&edev->lock, flags); in extcon_set_property()
750 * extcon_set_property_sync() - Set property of an external connector with sync.
759 int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id, in extcon_set_property_sync() argument
765 ret = extcon_set_property(edev, id, prop, prop_val); in extcon_set_property_sync()
769 return extcon_sync(edev, id); in extcon_set_property_sync()
774 * extcon_get_property_capability() - Get the capability of the property
776 * @edev: the extcon device
777 * @id: the unique id indicating an external connector
778 * @prop: the property id indicating an extcon property
782 int extcon_get_property_capability(struct extcon_dev *edev, unsigned int id, in extcon_get_property_capability() argument
788 return -EINVAL; in extcon_get_property_capability()
791 if (!is_extcon_property_supported(id, prop)) in extcon_get_property_capability()
792 return -EINVAL; in extcon_get_property_capability()
794 /* Find the cable index of external connector by using id */ in extcon_get_property_capability()
795 index = find_cable_index_by_id(edev, id); in extcon_get_property_capability()
799 return is_extcon_property_capability(edev, id, index, prop); in extcon_get_property_capability()
804 * extcon_set_property_capability() - Set the capability of the property
806 * @edev: the extcon device
807 * @id: the unique id indicating an external connector
808 * @prop: the property id indicating an extcon property
816 int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id, in extcon_set_property_capability() argument
823 return -EINVAL; in extcon_set_property_capability()
826 if (!is_extcon_property_supported(id, prop)) in extcon_set_property_capability()
827 return -EINVAL; in extcon_set_property_capability()
829 /* Find the cable index of external connector by using id. */ in extcon_set_property_capability()
830 index = find_cable_index_by_id(edev, id); in extcon_set_property_capability()
838 cable = &edev->cables[index]; in extcon_set_property_capability()
842 __set_bit(prop - EXTCON_PROP_USB_MIN, cable->usb_bits); in extcon_set_property_capability()
845 __set_bit(prop - EXTCON_PROP_CHG_MIN, cable->chg_bits); in extcon_set_property_capability()
848 __set_bit(prop - EXTCON_PROP_JACK_MIN, cable->jack_bits); in extcon_set_property_capability()
851 __set_bit(prop - EXTCON_PROP_DISP_MIN, cable->disp_bits); in extcon_set_property_capability()
854 ret = -EINVAL; in extcon_set_property_capability()
862 * extcon_get_extcon_dev() - Get the extcon device instance from the name.
865 * Return the pointer of extcon device if success or ERR_PTR(err) if fail.
872 return ERR_PTR(-EINVAL); in extcon_get_extcon_dev()
876 if (!strcmp(sd->name, extcon_name)) in extcon_get_extcon_dev()
887 * extcon_register_notifier() - Register a notifier block to get notified by
889 * @edev: the extcon device
890 * @id: the unique id indicating an external connector
895 * is the pointer of extcon device.
899 int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, in extcon_register_notifier() argument
906 return -EINVAL; in extcon_register_notifier()
908 idx = find_cable_index_by_id(edev, id); in extcon_register_notifier()
912 spin_lock_irqsave(&edev->lock, flags); in extcon_register_notifier()
913 ret = raw_notifier_chain_register(&edev->nh[idx], nb); in extcon_register_notifier()
914 spin_unlock_irqrestore(&edev->lock, flags); in extcon_register_notifier()
921 * extcon_unregister_notifier() - Unregister a notifier block from the extcon.
922 * @edev: the extcon device
923 * @id: the unique id indicating an external connector
928 int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id, in extcon_unregister_notifier() argument
935 return -EINVAL; in extcon_unregister_notifier()
937 idx = find_cable_index_by_id(edev, id); in extcon_unregister_notifier()
941 spin_lock_irqsave(&edev->lock, flags); in extcon_unregister_notifier()
942 ret = raw_notifier_chain_unregister(&edev->nh[idx], nb); in extcon_unregister_notifier()
943 spin_unlock_irqrestore(&edev->lock, flags); in extcon_unregister_notifier()
950 * extcon_register_notifier_all() - Register a notifier block for all connectors.
951 * @edev: the extcon device
955 * the state change of all supported external connectors from extcon device.
957 * the current state and the third pameter is the pointer of extcon device.
968 return -EINVAL; in extcon_register_notifier_all()
970 spin_lock_irqsave(&edev->lock, flags); in extcon_register_notifier_all()
971 ret = raw_notifier_chain_register(&edev->nh_all, nb); in extcon_register_notifier_all()
972 spin_unlock_irqrestore(&edev->lock, flags); in extcon_register_notifier_all()
979 * extcon_unregister_notifier_all() - Unregister a notifier block from extcon.
980 * @edev: the extcon device
992 return -EINVAL; in extcon_unregister_notifier_all()
994 spin_lock_irqsave(&edev->lock, flags); in extcon_unregister_notifier_all()
995 ret = raw_notifier_chain_unregister(&edev->nh_all, nb); in extcon_unregister_notifier_all()
996 spin_unlock_irqrestore(&edev->lock, flags); in extcon_unregister_notifier_all()
1015 extcon_class->dev_groups = extcon_groups; in create_extcon_class()
1021 static void extcon_dev_release(struct device *dev) in extcon_dev_release()
1026 static void dummy_sysfs_dev_release(struct device *dev) in dummy_sysfs_dev_release()
1031 * extcon_dev_allocate() - Allocate the memory of extcon device.
1035 * Note that this function allocates the memory for extcon device
1036 * and initialize default setting for the extcon device.
1046 return ERR_PTR(-EINVAL); in extcon_dev_allocate()
1050 return ERR_PTR(-ENOMEM); in extcon_dev_allocate()
1052 edev->max_supported = 0; in extcon_dev_allocate()
1053 edev->supported_cable = supported_cable; in extcon_dev_allocate()
1059 * extcon_dev_free() - Free the memory of extcon device.
1060 * @edev: the extcon device
1069 * extcon_dev_register() - Register an new extcon device
1070 * @edev: the extcon device to be registered
1077 * of an extcon device by using the extcon_dev_allocate(). And the extcon
1085 static atomic_t edev_no = ATOMIC_INIT(-1); in extcon_dev_register()
1093 if (!edev || !edev->supported_cable) in extcon_dev_register()
1094 return -EINVAL; in extcon_dev_register()
1096 for (; edev->supported_cable[index] != EXTCON_NONE; index++); in extcon_dev_register()
1098 edev->max_supported = index; in extcon_dev_register()
1100 dev_err(&edev->dev, in extcon_dev_register()
1102 return -EINVAL; in extcon_dev_register()
1105 edev->dev.class = extcon_class; in extcon_dev_register()
1106 edev->dev.release = extcon_dev_release; in extcon_dev_register()
1108 edev->name = dev_name(edev->dev.parent); in extcon_dev_register()
1109 if (IS_ERR_OR_NULL(edev->name)) { in extcon_dev_register()
1110 dev_err(&edev->dev, in extcon_dev_register()
1111 "extcon device name is null\n"); in extcon_dev_register()
1112 return -EINVAL; in extcon_dev_register()
1114 dev_set_name(&edev->dev, "extcon%lu", in extcon_dev_register()
1117 if (edev->max_supported) { in extcon_dev_register()
1121 edev->cables = kcalloc(edev->max_supported, in extcon_dev_register()
1124 if (!edev->cables) { in extcon_dev_register()
1125 ret = -ENOMEM; in extcon_dev_register()
1128 for (index = 0; index < edev->max_supported; index++) { in extcon_dev_register()
1129 cable = &edev->cables[index]; in extcon_dev_register()
1133 for (index--; index >= 0; index--) { in extcon_dev_register()
1134 cable = &edev->cables[index]; in extcon_dev_register()
1135 kfree(cable->attr_g.name); in extcon_dev_register()
1137 ret = -ENOMEM; in extcon_dev_register()
1142 cable->edev = edev; in extcon_dev_register()
1143 cable->cable_index = index; in extcon_dev_register()
1144 cable->attrs[0] = &cable->attr_name.attr; in extcon_dev_register()
1145 cable->attrs[1] = &cable->attr_state.attr; in extcon_dev_register()
1146 cable->attrs[2] = NULL; in extcon_dev_register()
1147 cable->attr_g.name = str; in extcon_dev_register()
1148 cable->attr_g.attrs = cable->attrs; in extcon_dev_register()
1150 sysfs_attr_init(&cable->attr_name.attr); in extcon_dev_register()
1151 cable->attr_name.attr.name = "name"; in extcon_dev_register()
1152 cable->attr_name.attr.mode = 0444; in extcon_dev_register()
1153 cable->attr_name.show = cable_name_show; in extcon_dev_register()
1155 sysfs_attr_init(&cable->attr_state.attr); in extcon_dev_register()
1156 cable->attr_state.attr.name = "state"; in extcon_dev_register()
1157 cable->attr_state.attr.mode = 0444; in extcon_dev_register()
1158 cable->attr_state.show = cable_state_show; in extcon_dev_register()
1162 if (edev->max_supported && edev->mutually_exclusive) { in extcon_dev_register()
1166 for (index = 0; edev->mutually_exclusive[index]; index++) in extcon_dev_register()
1169 edev->attrs_muex = kcalloc(index + 1, in extcon_dev_register()
1172 if (!edev->attrs_muex) { in extcon_dev_register()
1173 ret = -ENOMEM; in extcon_dev_register()
1177 edev->d_attrs_muex = kcalloc(index, in extcon_dev_register()
1180 if (!edev->d_attrs_muex) { in extcon_dev_register()
1181 ret = -ENOMEM; in extcon_dev_register()
1182 kfree(edev->attrs_muex); in extcon_dev_register()
1186 for (index = 0; edev->mutually_exclusive[index]; index++) { in extcon_dev_register()
1188 edev->mutually_exclusive[index]); in extcon_dev_register()
1190 for (index--; index >= 0; index--) { in extcon_dev_register()
1191 kfree(edev->d_attrs_muex[index].attr. in extcon_dev_register()
1194 kfree(edev->d_attrs_muex); in extcon_dev_register()
1195 kfree(edev->attrs_muex); in extcon_dev_register()
1196 ret = -ENOMEM; in extcon_dev_register()
1199 sysfs_attr_init(&edev->d_attrs_muex[index].attr); in extcon_dev_register()
1200 edev->d_attrs_muex[index].attr.name = name; in extcon_dev_register()
1201 edev->d_attrs_muex[index].attr.mode = 0000; in extcon_dev_register()
1202 edev->attrs_muex[index] = &edev->d_attrs_muex[index] in extcon_dev_register()
1205 edev->attr_g_muex.name = muex_name; in extcon_dev_register()
1206 edev->attr_g_muex.attrs = edev->attrs_muex; in extcon_dev_register()
1210 if (edev->max_supported) { in extcon_dev_register()
1211 edev->extcon_dev_type.groups = in extcon_dev_register()
1212 kcalloc(edev->max_supported + 2, in extcon_dev_register()
1215 if (!edev->extcon_dev_type.groups) { in extcon_dev_register()
1216 ret = -ENOMEM; in extcon_dev_register()
1220 edev->extcon_dev_type.name = dev_name(&edev->dev); in extcon_dev_register()
1221 edev->extcon_dev_type.release = dummy_sysfs_dev_release; in extcon_dev_register()
1223 for (index = 0; index < edev->max_supported; index++) in extcon_dev_register()
1224 edev->extcon_dev_type.groups[index] = in extcon_dev_register()
1225 &edev->cables[index].attr_g; in extcon_dev_register()
1226 if (edev->mutually_exclusive) in extcon_dev_register()
1227 edev->extcon_dev_type.groups[index] = in extcon_dev_register()
1228 &edev->attr_g_muex; in extcon_dev_register()
1230 edev->dev.type = &edev->extcon_dev_type; in extcon_dev_register()
1233 ret = device_register(&edev->dev); in extcon_dev_register()
1235 put_device(&edev->dev); in extcon_dev_register()
1239 spin_lock_init(&edev->lock); in extcon_dev_register()
1240 edev->nh = devm_kcalloc(&edev->dev, edev->max_supported, in extcon_dev_register()
1241 sizeof(*edev->nh), GFP_KERNEL); in extcon_dev_register()
1242 if (!edev->nh) { in extcon_dev_register()
1243 ret = -ENOMEM; in extcon_dev_register()
1247 for (index = 0; index < edev->max_supported; index++) in extcon_dev_register()
1248 RAW_INIT_NOTIFIER_HEAD(&edev->nh[index]); in extcon_dev_register()
1250 RAW_INIT_NOTIFIER_HEAD(&edev->nh_all); in extcon_dev_register()
1252 dev_set_drvdata(&edev->dev, edev); in extcon_dev_register()
1253 edev->state = 0; in extcon_dev_register()
1256 list_add(&edev->entry, &extcon_dev_list); in extcon_dev_register()
1262 if (edev->max_supported) in extcon_dev_register()
1263 kfree(edev->extcon_dev_type.groups); in extcon_dev_register()
1265 if (edev->max_supported && edev->mutually_exclusive) { in extcon_dev_register()
1266 for (index = 0; edev->mutually_exclusive[index]; index++) in extcon_dev_register()
1267 kfree(edev->d_attrs_muex[index].attr.name); in extcon_dev_register()
1268 kfree(edev->d_attrs_muex); in extcon_dev_register()
1269 kfree(edev->attrs_muex); in extcon_dev_register()
1272 for (index = 0; index < edev->max_supported; index++) in extcon_dev_register()
1273 kfree(edev->cables[index].attr_g.name); in extcon_dev_register()
1275 if (edev->max_supported) in extcon_dev_register()
1276 kfree(edev->cables); in extcon_dev_register()
1283 * extcon_dev_unregister() - Unregister the extcon device.
1284 * @edev: the extcon device to be unregistered.
1297 list_del(&edev->entry); in extcon_dev_unregister()
1300 if (IS_ERR_OR_NULL(get_device(&edev->dev))) { in extcon_dev_unregister()
1301 dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n", in extcon_dev_unregister()
1302 dev_name(&edev->dev)); in extcon_dev_unregister()
1306 device_unregister(&edev->dev); in extcon_dev_unregister()
1308 if (edev->mutually_exclusive && edev->max_supported) { in extcon_dev_unregister()
1309 for (index = 0; edev->mutually_exclusive[index]; in extcon_dev_unregister()
1311 kfree(edev->d_attrs_muex[index].attr.name); in extcon_dev_unregister()
1312 kfree(edev->d_attrs_muex); in extcon_dev_unregister()
1313 kfree(edev->attrs_muex); in extcon_dev_unregister()
1316 for (index = 0; index < edev->max_supported; index++) in extcon_dev_unregister()
1317 kfree(edev->cables[index].attr_g.name); in extcon_dev_unregister()
1319 if (edev->max_supported) { in extcon_dev_unregister()
1320 kfree(edev->extcon_dev_type.groups); in extcon_dev_unregister()
1321 kfree(edev->cables); in extcon_dev_unregister()
1324 put_device(&edev->dev); in extcon_dev_unregister()
1331 * extcon_find_edev_by_node - Find the extcon device from devicetree.
1334 * Return the pointer of extcon device if success or ERR_PTR(err) if fail.
1342 if (edev->dev.parent && edev->dev.parent->of_node == node) in extcon_find_edev_by_node()
1344 edev = ERR_PTR(-EPROBE_DEFER); in extcon_find_edev_by_node()
1352 * extcon_get_edev_by_phandle - Get the extcon device from devicetree.
1353 * @dev : the instance to the given device
1356 * Return the pointer of extcon device if success or ERR_PTR(err) if fail.
1358 struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) in extcon_get_edev_by_phandle()
1364 return ERR_PTR(-EINVAL); in extcon_get_edev_by_phandle()
1366 if (!dev->of_node) { in extcon_get_edev_by_phandle()
1367 dev_dbg(dev, "device does not have a device node entry\n"); in extcon_get_edev_by_phandle()
1368 return ERR_PTR(-EINVAL); in extcon_get_edev_by_phandle()
1371 node = of_parse_phandle(dev->of_node, "extcon", index); in extcon_get_edev_by_phandle()
1374 dev->of_node); in extcon_get_edev_by_phandle()
1375 return ERR_PTR(-ENODEV); in extcon_get_edev_by_phandle()
1388 return ERR_PTR(-ENOSYS); in extcon_find_edev_by_node()
1391 struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) in extcon_get_edev_by_phandle()
1393 return ERR_PTR(-ENOSYS); in extcon_get_edev_by_phandle()
1402 * extcon_get_edev_name() - Get the name of the extcon device.
1403 * @edev: the extcon device
1407 return !edev ? NULL : edev->name; in extcon_get_edev_name()