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,
172 .id = EXTCON_DISP_CVBS,
177 .id = EXTCON_DISP_EDP,
184 .id = EXTCON_DOCK,
189 .id = EXTCON_JIG,
194 .id = EXTCON_MECHANICAL,
202 * struct extcon_cable - An internal data for an external connector.
203 * @edev: the extcon device
240 if (!edev->mutually_exclusive) in check_mutually_exclusive()
243 for (i = 0; edev->mutually_exclusive[i]; i++) { in check_mutually_exclusive()
245 u32 correspondants = new_state & edev->mutually_exclusive[i]; in check_mutually_exclusive()
256 static int find_cable_index_by_id(struct extcon_dev *edev, const unsigned int id) in find_cable_index_by_id() argument
260 /* Find the the index of extcon cable in edev->supported_cable */ in find_cable_index_by_id()
261 for (i = 0; i < edev->max_supported; i++) { in find_cable_index_by_id()
262 if (edev->supported_cable[i] == id) in find_cable_index_by_id()
266 return -EINVAL; in find_cable_index_by_id()
281 return -EINVAL; in get_extcon_type()
287 return !!(edev->state & BIT(index)); in is_extcon_attached()
293 int state = !!(edev->state & BIT(index)); in is_extcon_changed()
297 static bool is_extcon_property_supported(unsigned int id, unsigned int prop) in is_extcon_property_supported() argument
306 /* Check whether a specific extcon id supports the property or not. */ in is_extcon_property_supported()
307 return !!(extcon_info[id].type & type); in is_extcon_property_supported()
311 unsigned int id, int index,unsigned int prop) in is_extcon_property_capability() argument
321 cable = &edev->cables[index]; in is_extcon_property_capability()
325 ret = test_bit(prop - EXTCON_PROP_USB_MIN, cable->usb_bits); in is_extcon_property_capability()
328 ret = test_bit(prop - EXTCON_PROP_CHG_MIN, cable->chg_bits); in is_extcon_property_capability()
331 ret = test_bit(prop - EXTCON_PROP_JACK_MIN, cable->jack_bits); in is_extcon_property_capability()
334 ret = test_bit(prop - EXTCON_PROP_DISP_MIN, cable->disp_bits); in is_extcon_property_capability()
337 ret = -EINVAL; in is_extcon_property_capability()
343 static void init_property(struct extcon_dev *edev, unsigned int id, int index) in init_property() argument
345 unsigned int type = extcon_info[id].type; in init_property()
346 struct extcon_cable *cable = &edev->cables[index]; in init_property()
349 memset(cable->usb_propval, 0, sizeof(cable->usb_propval)); in init_property()
351 memset(cable->chg_propval, 0, sizeof(cable->chg_propval)); in init_property()
353 memset(cable->jack_propval, 0, sizeof(cable->jack_propval)); in init_property()
355 memset(cable->disp_propval, 0, sizeof(cable->disp_propval)); in init_property()
358 static ssize_t state_show(struct device *dev, struct device_attribute *attr, in state_show()
364 if (edev->max_supported == 0) in state_show()
365 return sprintf(buf, "%u\n", edev->state); in state_show()
367 for (i = 0; i < edev->max_supported; i++) { in state_show()
369 extcon_info[edev->supported_cable[i]].name, in state_show()
370 !!(edev->state & BIT(i))); in state_show()
377 static ssize_t name_show(struct device *dev, struct device_attribute *attr, in name_show()
382 return sprintf(buf, "%s\n", edev->name); in name_show()
386 static ssize_t cable_name_show(struct device *dev, in cable_name_show()
391 int i = cable->cable_index; in cable_name_show()
394 extcon_info[cable->edev->supported_cable[i]].name); in cable_name_show()
397 static ssize_t cable_state_show(struct device *dev, in cable_state_show()
403 int i = cable->cable_index; in cable_state_show()
406 extcon_get_state(cable->edev, cable->edev->supported_cable[i])); in cable_state_show()
410 * extcon_sync() - Synchronize the state for an external connector.
411 * @edev: the extcon device
418 int extcon_sync(struct extcon_dev *edev, unsigned int id) in extcon_sync() argument
431 return -EINVAL; in extcon_sync()
433 index = find_cable_index_by_id(edev, id); in extcon_sync()
437 spin_lock_irqsave(&edev->lock, flags); in extcon_sync()
438 state = !!(edev->state & BIT(index)); in extcon_sync()
439 spin_unlock_irqrestore(&edev->lock, flags); in extcon_sync()
445 raw_notifier_call_chain(&edev->nh[index], state, edev); in extcon_sync()
451 raw_notifier_call_chain(&edev->nh_all, state, edev); in extcon_sync()
453 spin_lock_irqsave(&edev->lock, flags); in extcon_sync()
458 spin_unlock_irqrestore(&edev->lock, flags); in extcon_sync()
460 dev_err(&edev->dev, "out of memory in extcon_set_state\n"); in extcon_sync()
461 kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE); in extcon_sync()
463 return -ENOMEM; in extcon_sync()
466 length = name_show(&edev->dev, NULL, prop_buf); in extcon_sync()
468 if (prop_buf[length - 1] == '\n') in extcon_sync()
469 prop_buf[length - 1] = 0; in extcon_sync()
474 length = state_show(&edev->dev, NULL, prop_buf); in extcon_sync()
476 if (prop_buf[length - 1] == '\n') in extcon_sync()
477 prop_buf[length - 1] = 0; in extcon_sync()
484 spin_unlock_irqrestore(&edev->lock, flags); in extcon_sync()
485 kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp); in extcon_sync()
493 * extcon_get_state() - Get the state of an external connector.
494 * @edev: the extcon device
495 * @id: the unique id indicating an external connector
499 int extcon_get_state(struct extcon_dev *edev, const unsigned int id) in extcon_get_state() argument
505 return -EINVAL; in extcon_get_state()
507 index = find_cable_index_by_id(edev, id); in extcon_get_state()
511 spin_lock_irqsave(&edev->lock, flags); in extcon_get_state()
513 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_state()
520 * extcon_set_state() - Set the state of an external connector.
521 * @edev: the extcon device
522 * @id: the unique id indicating an external connector
532 int extcon_set_state(struct extcon_dev *edev, unsigned int id, bool state) in extcon_set_state() argument
538 return -EINVAL; in extcon_set_state()
540 index = find_cable_index_by_id(edev, id); in extcon_set_state()
544 spin_lock_irqsave(&edev->lock, flags); in extcon_set_state()
551 (edev->state & ~BIT(index)) | (state & BIT(index)))) { in extcon_set_state()
552 ret = -EPERM; in extcon_set_state()
561 init_property(edev, id, index); in extcon_set_state()
565 edev->state |= BIT(index); in extcon_set_state()
567 edev->state &= ~(BIT(index)); in extcon_set_state()
569 spin_unlock_irqrestore(&edev->lock, flags); in extcon_set_state()
576 * extcon_set_state_sync() - Set the state of an external connector with sync.
577 * @edev: the extcon device
578 * @id: the unique id indicating an external connector
587 int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id, bool state) in extcon_set_state_sync() argument
592 index = find_cable_index_by_id(edev, id); in extcon_set_state_sync()
597 spin_lock_irqsave(&edev->lock, flags); in extcon_set_state_sync()
599 spin_unlock_irqrestore(&edev->lock, flags); in extcon_set_state_sync()
603 ret = extcon_set_state(edev, id, state); in extcon_set_state_sync()
607 return extcon_sync(edev, id); in extcon_set_state_sync()
612 * extcon_get_property() - Get the property value of an external connector.
613 * @edev: the extcon device
614 * @id: the unique id indicating an external connector
615 * @prop: the property id indicating an extcon property
625 int extcon_get_property(struct extcon_dev *edev, unsigned int id, in extcon_get_property() argument
636 return -EINVAL; in extcon_get_property()
639 if (!is_extcon_property_supported(id, prop)) in extcon_get_property()
640 return -EINVAL; in extcon_get_property()
642 /* Find the cable index of external connector by using id */ in extcon_get_property()
643 index = find_cable_index_by_id(edev, id); in extcon_get_property()
647 spin_lock_irqsave(&edev->lock, flags); in extcon_get_property()
650 if (!is_extcon_property_capability(edev, id, index, prop)) { in extcon_get_property()
651 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_property()
652 return -EPERM; in extcon_get_property()
661 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_property()
665 cable = &edev->cables[index]; in extcon_get_property()
670 *prop_val = cable->usb_propval[prop - EXTCON_PROP_USB_MIN]; in extcon_get_property()
673 *prop_val = cable->chg_propval[prop - EXTCON_PROP_CHG_MIN]; in extcon_get_property()
676 *prop_val = cable->jack_propval[prop - EXTCON_PROP_JACK_MIN]; in extcon_get_property()
679 *prop_val = cable->disp_propval[prop - EXTCON_PROP_DISP_MIN]; in extcon_get_property()
682 ret = -EINVAL; in extcon_get_property()
686 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_property()
693 * extcon_set_property() - Set the property value of an external connector.
694 * @edev: the extcon device
695 * @id: the unique id indicating an external connector
696 * @prop: the property id indicating an extcon property
704 int extcon_set_property(struct extcon_dev *edev, unsigned int id, in extcon_set_property() argument
713 return -EINVAL; in extcon_set_property()
716 if (!is_extcon_property_supported(id, prop)) in extcon_set_property()
717 return -EINVAL; in extcon_set_property()
719 /* Find the cable index of external connector by using id */ in extcon_set_property()
720 index = find_cable_index_by_id(edev, id); in extcon_set_property()
724 spin_lock_irqsave(&edev->lock, flags); in extcon_set_property()
727 if (!is_extcon_property_capability(edev, id, index, prop)) { in extcon_set_property()
728 spin_unlock_irqrestore(&edev->lock, flags); in extcon_set_property()
729 return -EPERM; in extcon_set_property()
732 cable = &edev->cables[index]; in extcon_set_property()
737 cable->usb_propval[prop - EXTCON_PROP_USB_MIN] = prop_val; in extcon_set_property()
740 cable->chg_propval[prop - EXTCON_PROP_CHG_MIN] = prop_val; in extcon_set_property()
743 cable->jack_propval[prop - EXTCON_PROP_JACK_MIN] = prop_val; in extcon_set_property()
746 cable->disp_propval[prop - EXTCON_PROP_DISP_MIN] = prop_val; in extcon_set_property()
749 ret = -EINVAL; in extcon_set_property()
753 spin_unlock_irqrestore(&edev->lock, flags); in extcon_set_property()
760 * extcon_set_property_sync() - Set property of an external connector with sync.
769 int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id, in extcon_set_property_sync() argument
775 ret = extcon_set_property(edev, id, prop, prop_val); in extcon_set_property_sync()
779 return extcon_sync(edev, id); in extcon_set_property_sync()
784 * extcon_get_property_capability() - Get the capability of the property
786 * @edev: the extcon device
787 * @id: the unique id indicating an external connector
788 * @prop: the property id indicating an extcon property
792 int extcon_get_property_capability(struct extcon_dev *edev, unsigned int id, in extcon_get_property_capability() argument
798 return -EINVAL; in extcon_get_property_capability()
801 if (!is_extcon_property_supported(id, prop)) in extcon_get_property_capability()
802 return -EINVAL; in extcon_get_property_capability()
804 /* Find the cable index of external connector by using id */ in extcon_get_property_capability()
805 index = find_cable_index_by_id(edev, id); in extcon_get_property_capability()
809 return is_extcon_property_capability(edev, id, index, prop); in extcon_get_property_capability()
814 * extcon_set_property_capability() - Set the capability of the property
816 * @edev: the extcon device
817 * @id: the unique id indicating an external connector
818 * @prop: the property id indicating an extcon property
826 int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id, in extcon_set_property_capability() argument
833 return -EINVAL; in extcon_set_property_capability()
836 if (!is_extcon_property_supported(id, prop)) in extcon_set_property_capability()
837 return -EINVAL; in extcon_set_property_capability()
839 /* Find the cable index of external connector by using id. */ in extcon_set_property_capability()
840 index = find_cable_index_by_id(edev, id); in extcon_set_property_capability()
848 cable = &edev->cables[index]; in extcon_set_property_capability()
852 __set_bit(prop - EXTCON_PROP_USB_MIN, cable->usb_bits); in extcon_set_property_capability()
855 __set_bit(prop - EXTCON_PROP_CHG_MIN, cable->chg_bits); in extcon_set_property_capability()
858 __set_bit(prop - EXTCON_PROP_JACK_MIN, cable->jack_bits); in extcon_set_property_capability()
861 __set_bit(prop - EXTCON_PROP_DISP_MIN, cable->disp_bits); in extcon_set_property_capability()
864 ret = -EINVAL; in extcon_set_property_capability()
872 * extcon_get_extcon_dev() - Get the extcon device instance from the name.
875 * Return the pointer of extcon device if success or ERR_PTR(err) if fail.
882 return ERR_PTR(-EINVAL); in extcon_get_extcon_dev()
886 if (!strcmp(sd->name, extcon_name)) in extcon_get_extcon_dev()
897 * extcon_register_notifier() - Register a notifier block to get notified by
899 * @edev: the extcon device
900 * @id: the unique id indicating an external connector
905 * is the pointer of extcon device.
909 int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, in extcon_register_notifier() argument
916 return -EINVAL; in extcon_register_notifier()
918 idx = find_cable_index_by_id(edev, id); in extcon_register_notifier()
922 spin_lock_irqsave(&edev->lock, flags); in extcon_register_notifier()
923 ret = raw_notifier_chain_register(&edev->nh[idx], nb); in extcon_register_notifier()
924 spin_unlock_irqrestore(&edev->lock, flags); in extcon_register_notifier()
931 * extcon_unregister_notifier() - Unregister a notifier block from the extcon.
932 * @edev: the extcon device
933 * @id: the unique id indicating an external connector
938 int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id, in extcon_unregister_notifier() argument
945 return -EINVAL; in extcon_unregister_notifier()
947 idx = find_cable_index_by_id(edev, id); in extcon_unregister_notifier()
951 spin_lock_irqsave(&edev->lock, flags); in extcon_unregister_notifier()
952 ret = raw_notifier_chain_unregister(&edev->nh[idx], nb); in extcon_unregister_notifier()
953 spin_unlock_irqrestore(&edev->lock, flags); in extcon_unregister_notifier()
960 * extcon_register_notifier_all() - Register a notifier block for all connectors.
961 * @edev: the extcon device
965 * the state change of all supported external connectors from extcon device.
967 * the current state and the third pameter is the pointer of extcon device.
978 return -EINVAL; in extcon_register_notifier_all()
980 spin_lock_irqsave(&edev->lock, flags); in extcon_register_notifier_all()
981 ret = raw_notifier_chain_register(&edev->nh_all, nb); in extcon_register_notifier_all()
982 spin_unlock_irqrestore(&edev->lock, flags); in extcon_register_notifier_all()
989 * extcon_unregister_notifier_all() - Unregister a notifier block from extcon.
990 * @edev: the extcon device
1002 return -EINVAL; in extcon_unregister_notifier_all()
1004 spin_lock_irqsave(&edev->lock, flags); in extcon_unregister_notifier_all()
1005 ret = raw_notifier_chain_unregister(&edev->nh_all, nb); in extcon_unregister_notifier_all()
1006 spin_unlock_irqrestore(&edev->lock, flags); in extcon_unregister_notifier_all()
1025 extcon_class->dev_groups = extcon_groups; in create_extcon_class()
1031 static void extcon_dev_release(struct device *dev) in extcon_dev_release()
1036 static void dummy_sysfs_dev_release(struct device *dev) in dummy_sysfs_dev_release()
1041 * extcon_dev_allocate() - Allocate the memory of extcon device.
1045 * Note that this function allocates the memory for extcon device
1046 * and initialize default setting for the extcon device.
1056 return ERR_PTR(-EINVAL); in extcon_dev_allocate()
1060 return ERR_PTR(-ENOMEM); in extcon_dev_allocate()
1062 edev->max_supported = 0; in extcon_dev_allocate()
1063 edev->supported_cable = supported_cable; in extcon_dev_allocate()
1069 * extcon_dev_free() - Free the memory of extcon device.
1070 * @edev: the extcon device
1079 * extcon_dev_register() - Register an new extcon device
1080 * @edev: the extcon device to be registered
1087 * of an extcon device by using the extcon_dev_allocate(). And the extcon
1095 static atomic_t edev_no = ATOMIC_INIT(-1); in extcon_dev_register()
1103 if (!edev || !edev->supported_cable) in extcon_dev_register()
1104 return -EINVAL; in extcon_dev_register()
1106 for (; edev->supported_cable[index] != EXTCON_NONE; index++); in extcon_dev_register()
1108 edev->max_supported = index; in extcon_dev_register()
1110 dev_err(&edev->dev, in extcon_dev_register()
1112 return -EINVAL; in extcon_dev_register()
1115 edev->dev.class = extcon_class; in extcon_dev_register()
1116 edev->dev.release = extcon_dev_release; in extcon_dev_register()
1118 edev->name = dev_name(edev->dev.parent); in extcon_dev_register()
1119 if (IS_ERR_OR_NULL(edev->name)) { in extcon_dev_register()
1120 dev_err(&edev->dev, in extcon_dev_register()
1121 "extcon device name is null\n"); in extcon_dev_register()
1122 return -EINVAL; in extcon_dev_register()
1124 dev_set_name(&edev->dev, "extcon%lu", in extcon_dev_register()
1127 if (edev->max_supported) { in extcon_dev_register()
1131 edev->cables = kcalloc(edev->max_supported, in extcon_dev_register()
1134 if (!edev->cables) { in extcon_dev_register()
1135 ret = -ENOMEM; in extcon_dev_register()
1138 for (index = 0; index < edev->max_supported; index++) { in extcon_dev_register()
1139 cable = &edev->cables[index]; in extcon_dev_register()
1143 for (index--; index >= 0; index--) { in extcon_dev_register()
1144 cable = &edev->cables[index]; in extcon_dev_register()
1145 kfree(cable->attr_g.name); in extcon_dev_register()
1147 ret = -ENOMEM; in extcon_dev_register()
1152 cable->edev = edev; in extcon_dev_register()
1153 cable->cable_index = index; in extcon_dev_register()
1154 cable->attrs[0] = &cable->attr_name.attr; in extcon_dev_register()
1155 cable->attrs[1] = &cable->attr_state.attr; in extcon_dev_register()
1156 cable->attrs[2] = NULL; in extcon_dev_register()
1157 cable->attr_g.name = str; in extcon_dev_register()
1158 cable->attr_g.attrs = cable->attrs; in extcon_dev_register()
1160 sysfs_attr_init(&cable->attr_name.attr); in extcon_dev_register()
1161 cable->attr_name.attr.name = "name"; in extcon_dev_register()
1162 cable->attr_name.attr.mode = 0444; in extcon_dev_register()
1163 cable->attr_name.show = cable_name_show; in extcon_dev_register()
1165 sysfs_attr_init(&cable->attr_state.attr); in extcon_dev_register()
1166 cable->attr_state.attr.name = "state"; in extcon_dev_register()
1167 cable->attr_state.attr.mode = 0444; in extcon_dev_register()
1168 cable->attr_state.show = cable_state_show; in extcon_dev_register()
1172 if (edev->max_supported && edev->mutually_exclusive) { in extcon_dev_register()
1176 for (index = 0; edev->mutually_exclusive[index]; index++) in extcon_dev_register()
1179 edev->attrs_muex = kcalloc(index + 1, in extcon_dev_register()
1182 if (!edev->attrs_muex) { in extcon_dev_register()
1183 ret = -ENOMEM; in extcon_dev_register()
1187 edev->d_attrs_muex = kcalloc(index, in extcon_dev_register()
1190 if (!edev->d_attrs_muex) { in extcon_dev_register()
1191 ret = -ENOMEM; in extcon_dev_register()
1192 kfree(edev->attrs_muex); in extcon_dev_register()
1196 for (index = 0; edev->mutually_exclusive[index]; index++) { in extcon_dev_register()
1198 edev->mutually_exclusive[index]); in extcon_dev_register()
1200 for (index--; index >= 0; index--) { in extcon_dev_register()
1201 kfree(edev->d_attrs_muex[index].attr. in extcon_dev_register()
1204 kfree(edev->d_attrs_muex); in extcon_dev_register()
1205 kfree(edev->attrs_muex); in extcon_dev_register()
1206 ret = -ENOMEM; in extcon_dev_register()
1209 sysfs_attr_init(&edev->d_attrs_muex[index].attr); in extcon_dev_register()
1210 edev->d_attrs_muex[index].attr.name = name; in extcon_dev_register()
1211 edev->d_attrs_muex[index].attr.mode = 0000; in extcon_dev_register()
1212 edev->attrs_muex[index] = &edev->d_attrs_muex[index] in extcon_dev_register()
1215 edev->attr_g_muex.name = muex_name; in extcon_dev_register()
1216 edev->attr_g_muex.attrs = edev->attrs_muex; in extcon_dev_register()
1220 if (edev->max_supported) { in extcon_dev_register()
1221 edev->extcon_dev_type.groups = in extcon_dev_register()
1222 kcalloc(edev->max_supported + 2, in extcon_dev_register()
1225 if (!edev->extcon_dev_type.groups) { in extcon_dev_register()
1226 ret = -ENOMEM; in extcon_dev_register()
1230 edev->extcon_dev_type.name = dev_name(&edev->dev); in extcon_dev_register()
1231 edev->extcon_dev_type.release = dummy_sysfs_dev_release; in extcon_dev_register()
1233 for (index = 0; index < edev->max_supported; index++) in extcon_dev_register()
1234 edev->extcon_dev_type.groups[index] = in extcon_dev_register()
1235 &edev->cables[index].attr_g; in extcon_dev_register()
1236 if (edev->mutually_exclusive) in extcon_dev_register()
1237 edev->extcon_dev_type.groups[index] = in extcon_dev_register()
1238 &edev->attr_g_muex; in extcon_dev_register()
1240 edev->dev.type = &edev->extcon_dev_type; in extcon_dev_register()
1243 spin_lock_init(&edev->lock); in extcon_dev_register()
1244 if (edev->max_supported) { in extcon_dev_register()
1245 edev->nh = kcalloc(edev->max_supported, sizeof(*edev->nh), in extcon_dev_register()
1247 if (!edev->nh) { in extcon_dev_register()
1248 ret = -ENOMEM; in extcon_dev_register()
1253 for (index = 0; index < edev->max_supported; index++) in extcon_dev_register()
1254 RAW_INIT_NOTIFIER_HEAD(&edev->nh[index]); in extcon_dev_register()
1256 RAW_INIT_NOTIFIER_HEAD(&edev->nh_all); in extcon_dev_register()
1258 dev_set_drvdata(&edev->dev, edev); in extcon_dev_register()
1259 edev->state = 0; in extcon_dev_register()
1261 ret = device_register(&edev->dev); in extcon_dev_register()
1263 put_device(&edev->dev); in extcon_dev_register()
1268 list_add(&edev->entry, &extcon_dev_list); in extcon_dev_register()
1274 if (edev->max_supported) in extcon_dev_register()
1275 kfree(edev->nh); in extcon_dev_register()
1277 if (edev->max_supported) in extcon_dev_register()
1278 kfree(edev->extcon_dev_type.groups); in extcon_dev_register()
1280 if (edev->max_supported && edev->mutually_exclusive) { in extcon_dev_register()
1281 for (index = 0; edev->mutually_exclusive[index]; index++) in extcon_dev_register()
1282 kfree(edev->d_attrs_muex[index].attr.name); in extcon_dev_register()
1283 kfree(edev->d_attrs_muex); in extcon_dev_register()
1284 kfree(edev->attrs_muex); in extcon_dev_register()
1287 for (index = 0; index < edev->max_supported; index++) in extcon_dev_register()
1288 kfree(edev->cables[index].attr_g.name); in extcon_dev_register()
1290 if (edev->max_supported) in extcon_dev_register()
1291 kfree(edev->cables); in extcon_dev_register()
1298 * extcon_dev_unregister() - Unregister the extcon device.
1299 * @edev: the extcon device to be unregistered.
1312 list_del(&edev->entry); in extcon_dev_unregister()
1315 if (IS_ERR_OR_NULL(get_device(&edev->dev))) { in extcon_dev_unregister()
1316 dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n", in extcon_dev_unregister()
1317 dev_name(&edev->dev)); in extcon_dev_unregister()
1321 device_unregister(&edev->dev); in extcon_dev_unregister()
1323 if (edev->mutually_exclusive && edev->max_supported) { in extcon_dev_unregister()
1324 for (index = 0; edev->mutually_exclusive[index]; in extcon_dev_unregister()
1326 kfree(edev->d_attrs_muex[index].attr.name); in extcon_dev_unregister()
1327 kfree(edev->d_attrs_muex); in extcon_dev_unregister()
1328 kfree(edev->attrs_muex); in extcon_dev_unregister()
1331 for (index = 0; index < edev->max_supported; index++) in extcon_dev_unregister()
1332 kfree(edev->cables[index].attr_g.name); in extcon_dev_unregister()
1334 if (edev->max_supported) { in extcon_dev_unregister()
1335 kfree(edev->extcon_dev_type.groups); in extcon_dev_unregister()
1336 kfree(edev->cables); in extcon_dev_unregister()
1337 kfree(edev->nh); in extcon_dev_unregister()
1340 put_device(&edev->dev); in extcon_dev_unregister()
1347 * extcon_find_edev_by_node - Find the extcon device from devicetree.
1350 * Return the pointer of extcon device if success or ERR_PTR(err) if fail.
1358 if (edev->dev.parent && edev->dev.parent->of_node == node) in extcon_find_edev_by_node()
1360 edev = ERR_PTR(-EPROBE_DEFER); in extcon_find_edev_by_node()
1368 * extcon_get_edev_by_phandle - Get the extcon device from devicetree.
1369 * @dev : the instance to the given device
1372 * Return the pointer of extcon device if success or ERR_PTR(err) if fail.
1374 struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) in extcon_get_edev_by_phandle()
1380 return ERR_PTR(-EINVAL); in extcon_get_edev_by_phandle()
1382 if (!dev->of_node) { in extcon_get_edev_by_phandle()
1383 dev_dbg(dev, "device does not have a device node entry\n"); in extcon_get_edev_by_phandle()
1384 return ERR_PTR(-EINVAL); in extcon_get_edev_by_phandle()
1387 node = of_parse_phandle(dev->of_node, "extcon", index); in extcon_get_edev_by_phandle()
1390 dev->of_node); in extcon_get_edev_by_phandle()
1391 return ERR_PTR(-ENODEV); in extcon_get_edev_by_phandle()
1404 return ERR_PTR(-ENOSYS); in extcon_find_edev_by_node()
1407 struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) in extcon_get_edev_by_phandle()
1409 return ERR_PTR(-ENOSYS); in extcon_get_edev_by_phandle()
1418 * extcon_get_edev_name() - Get the name of the extcon device.
1419 * @edev: the extcon device
1423 return !edev ? NULL : edev->name; in extcon_get_edev_name()