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 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
412 * @id: the unique id indicating an external connector
419 int extcon_sync(struct extcon_dev *edev, unsigned int id) in extcon_sync() argument
432 return -EINVAL; in extcon_sync()
434 index = find_cable_index_by_id(edev, id); in extcon_sync()
438 spin_lock_irqsave(&edev->lock, flags); in extcon_sync()
439 state = !!(edev->state & BIT(index)); in extcon_sync()
440 spin_unlock_irqrestore(&edev->lock, flags); in extcon_sync()
446 raw_notifier_call_chain(&edev->nh[index], state, edev); in extcon_sync()
452 raw_notifier_call_chain(&edev->nh_all, state, edev); in extcon_sync()
454 spin_lock_irqsave(&edev->lock, flags); in extcon_sync()
459 spin_unlock_irqrestore(&edev->lock, flags); in extcon_sync()
461 dev_err(&edev->dev, "out of memory in extcon_set_state\n"); in extcon_sync()
462 kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE); in extcon_sync()
464 return -ENOMEM; in extcon_sync()
467 length = name_show(&edev->dev, NULL, prop_buf); in extcon_sync()
469 if (prop_buf[length - 1] == '\n') in extcon_sync()
470 prop_buf[length - 1] = 0; in extcon_sync()
475 length = state_show(&edev->dev, NULL, prop_buf); in extcon_sync()
477 if (prop_buf[length - 1] == '\n') in extcon_sync()
478 prop_buf[length - 1] = 0; in extcon_sync()
485 spin_unlock_irqrestore(&edev->lock, flags); in extcon_sync()
486 kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp); in extcon_sync()
494 * extcon_get_state() - Get the state of an external connector.
495 * @edev: the extcon device
496 * @id: the unique id indicating an external connector
500 int extcon_get_state(struct extcon_dev *edev, const unsigned int id) in extcon_get_state() argument
506 return -EINVAL; in extcon_get_state()
508 index = find_cable_index_by_id(edev, id); in extcon_get_state()
512 spin_lock_irqsave(&edev->lock, flags); in extcon_get_state()
514 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_state()
521 * extcon_set_state() - Set the state of an external connector.
522 * @edev: the extcon device
523 * @id: the unique id indicating an external connector
533 int extcon_set_state(struct extcon_dev *edev, unsigned int id, bool state) in extcon_set_state() argument
539 return -EINVAL; in extcon_set_state()
541 index = find_cable_index_by_id(edev, id); in extcon_set_state()
545 spin_lock_irqsave(&edev->lock, flags); in extcon_set_state()
552 (edev->state & ~BIT(index)) | (state & BIT(index)))) { in extcon_set_state()
553 ret = -EPERM; in extcon_set_state()
562 init_property(edev, id, index); in extcon_set_state()
566 edev->state |= BIT(index); in extcon_set_state()
568 edev->state &= ~(BIT(index)); in extcon_set_state()
570 spin_unlock_irqrestore(&edev->lock, flags); in extcon_set_state()
577 * extcon_set_state_sync() - Set the state of an external connector with sync.
578 * @edev: the extcon device
579 * @id: the unique id indicating an external connector
588 int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id, bool state) in extcon_set_state_sync() argument
592 ret = extcon_set_state(edev, id, state); in extcon_set_state_sync()
596 return extcon_sync(edev, id); in extcon_set_state_sync()
601 * extcon_get_property() - Get the property value of an external connector.
602 * @edev: the extcon device
603 * @id: the unique id indicating an external connector
604 * @prop: the property id indicating an extcon property
614 int extcon_get_property(struct extcon_dev *edev, unsigned int id, in extcon_get_property() argument
625 return -EINVAL; in extcon_get_property()
628 if (!is_extcon_property_supported(id, prop)) in extcon_get_property()
629 return -EINVAL; in extcon_get_property()
631 /* Find the cable index of external connector by using id */ in extcon_get_property()
632 index = find_cable_index_by_id(edev, id); in extcon_get_property()
636 spin_lock_irqsave(&edev->lock, flags); in extcon_get_property()
639 if (!is_extcon_property_capability(edev, id, index, prop)) { in extcon_get_property()
640 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_property()
641 return -EPERM; in extcon_get_property()
650 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_property()
654 cable = &edev->cables[index]; in extcon_get_property()
659 *prop_val = cable->usb_propval[prop - EXTCON_PROP_USB_MIN]; in extcon_get_property()
662 *prop_val = cable->chg_propval[prop - EXTCON_PROP_CHG_MIN]; in extcon_get_property()
665 *prop_val = cable->jack_propval[prop - EXTCON_PROP_JACK_MIN]; in extcon_get_property()
668 *prop_val = cable->disp_propval[prop - EXTCON_PROP_DISP_MIN]; in extcon_get_property()
671 ret = -EINVAL; in extcon_get_property()
675 spin_unlock_irqrestore(&edev->lock, flags); in extcon_get_property()
682 * extcon_set_property() - Set the property value of an external connector.
683 * @edev: the extcon device
684 * @id: the unique id indicating an external connector
685 * @prop: the property id indicating an extcon property
693 int extcon_set_property(struct extcon_dev *edev, unsigned int id, in extcon_set_property() argument
702 return -EINVAL; in extcon_set_property()
705 if (!is_extcon_property_supported(id, prop)) in extcon_set_property()
706 return -EINVAL; in extcon_set_property()
708 /* Find the cable index of external connector by using id */ in extcon_set_property()
709 index = find_cable_index_by_id(edev, id); in extcon_set_property()
713 spin_lock_irqsave(&edev->lock, flags); in extcon_set_property()
716 if (!is_extcon_property_capability(edev, id, index, prop)) { in extcon_set_property()
717 spin_unlock_irqrestore(&edev->lock, flags); in extcon_set_property()
718 return -EPERM; in extcon_set_property()
721 cable = &edev->cables[index]; in extcon_set_property()
726 cable->usb_propval[prop - EXTCON_PROP_USB_MIN] = prop_val; in extcon_set_property()
729 cable->chg_propval[prop - EXTCON_PROP_CHG_MIN] = prop_val; in extcon_set_property()
732 cable->jack_propval[prop - EXTCON_PROP_JACK_MIN] = prop_val; in extcon_set_property()
735 cable->disp_propval[prop - EXTCON_PROP_DISP_MIN] = prop_val; in extcon_set_property()
738 ret = -EINVAL; in extcon_set_property()
742 spin_unlock_irqrestore(&edev->lock, flags); in extcon_set_property()
749 * extcon_set_property_sync() - Set property of an external connector with sync.
750 * @edev: the extcon device
751 * @id: the unique id indicating an external connector
752 * @prop: the property id indicating an extcon property
761 int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id, in extcon_set_property_sync() argument
767 ret = extcon_set_property(edev, id, prop, prop_val); in extcon_set_property_sync()
771 return extcon_sync(edev, id); in extcon_set_property_sync()
776 * extcon_get_property_capability() - Get the capability of the property
778 * @edev: the extcon device
779 * @id: the unique id indicating an external connector
780 * @prop: the property id indicating an extcon property
784 int extcon_get_property_capability(struct extcon_dev *edev, unsigned int id, in extcon_get_property_capability() argument
790 return -EINVAL; in extcon_get_property_capability()
793 if (!is_extcon_property_supported(id, prop)) in extcon_get_property_capability()
794 return -EINVAL; in extcon_get_property_capability()
796 /* Find the cable index of external connector by using id */ in extcon_get_property_capability()
797 index = find_cable_index_by_id(edev, id); in extcon_get_property_capability()
801 return is_extcon_property_capability(edev, id, index, prop); in extcon_get_property_capability()
806 * extcon_set_property_capability() - Set the capability of the property
808 * @edev: the extcon device
809 * @id: the unique id indicating an external connector
810 * @prop: the property id indicating an extcon property
818 int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id, in extcon_set_property_capability() argument
825 return -EINVAL; in extcon_set_property_capability()
828 if (!is_extcon_property_supported(id, prop)) in extcon_set_property_capability()
829 return -EINVAL; in extcon_set_property_capability()
831 /* Find the cable index of external connector by using id. */ in extcon_set_property_capability()
832 index = find_cable_index_by_id(edev, id); in extcon_set_property_capability()
840 cable = &edev->cables[index]; in extcon_set_property_capability()
844 __set_bit(prop - EXTCON_PROP_USB_MIN, cable->usb_bits); in extcon_set_property_capability()
847 __set_bit(prop - EXTCON_PROP_CHG_MIN, cable->chg_bits); in extcon_set_property_capability()
850 __set_bit(prop - EXTCON_PROP_JACK_MIN, cable->jack_bits); in extcon_set_property_capability()
853 __set_bit(prop - EXTCON_PROP_DISP_MIN, cable->disp_bits); in extcon_set_property_capability()
856 ret = -EINVAL; in extcon_set_property_capability()
864 * extcon_get_extcon_dev() - Get the extcon device instance from the name.
867 * Return the pointer of extcon device if success or ERR_PTR(err) if fail.
868 * NOTE: This function returns -EPROBE_DEFER so it may only be called from
876 return ERR_PTR(-EINVAL); in extcon_get_extcon_dev()
880 if (!strcmp(sd->name, extcon_name)) in extcon_get_extcon_dev()
883 sd = ERR_PTR(-EPROBE_DEFER); in extcon_get_extcon_dev()
891 * extcon_register_notifier() - Register a notifier block to get notified by
893 * @edev: the extcon device
894 * @id: the unique id indicating an external connector
899 * is the pointer of extcon device.
903 int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, in extcon_register_notifier() argument
910 return -EINVAL; in extcon_register_notifier()
912 idx = find_cable_index_by_id(edev, id); in extcon_register_notifier()
916 spin_lock_irqsave(&edev->lock, flags); in extcon_register_notifier()
917 ret = raw_notifier_chain_register(&edev->nh[idx], nb); in extcon_register_notifier()
918 spin_unlock_irqrestore(&edev->lock, flags); in extcon_register_notifier()
925 * extcon_unregister_notifier() - Unregister a notifier block from the extcon.
926 * @edev: the extcon device
927 * @id: the unique id indicating an external connector
932 int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id, in extcon_unregister_notifier() argument
939 return -EINVAL; in extcon_unregister_notifier()
941 idx = find_cable_index_by_id(edev, id); in extcon_unregister_notifier()
945 spin_lock_irqsave(&edev->lock, flags); in extcon_unregister_notifier()
946 ret = raw_notifier_chain_unregister(&edev->nh[idx], nb); in extcon_unregister_notifier()
947 spin_unlock_irqrestore(&edev->lock, flags); in extcon_unregister_notifier()
954 * extcon_register_notifier_all() - Register a notifier block for all connectors.
955 * @edev: the extcon device
959 * the state change of all supported external connectors from extcon device.
961 * the current state and the third pameter is the pointer of extcon device.
972 return -EINVAL; in extcon_register_notifier_all()
974 spin_lock_irqsave(&edev->lock, flags); in extcon_register_notifier_all()
975 ret = raw_notifier_chain_register(&edev->nh_all, nb); in extcon_register_notifier_all()
976 spin_unlock_irqrestore(&edev->lock, flags); in extcon_register_notifier_all()
983 * extcon_unregister_notifier_all() - Unregister a notifier block from extcon.
984 * @edev: the extcon device
996 return -EINVAL; in extcon_unregister_notifier_all()
998 spin_lock_irqsave(&edev->lock, flags); in extcon_unregister_notifier_all()
999 ret = raw_notifier_chain_unregister(&edev->nh_all, nb); in extcon_unregister_notifier_all()
1000 spin_unlock_irqrestore(&edev->lock, flags); in extcon_unregister_notifier_all()
1019 extcon_class->dev_groups = extcon_groups; in create_extcon_class()
1025 static void extcon_dev_release(struct device *dev) in extcon_dev_release()
1030 static void dummy_sysfs_dev_release(struct device *dev) in dummy_sysfs_dev_release()
1035 * extcon_dev_allocate() - Allocate the memory of extcon device.
1039 * Note that this function allocates the memory for extcon device
1040 * and initialize default setting for the extcon device.
1050 return ERR_PTR(-EINVAL); in extcon_dev_allocate()
1054 return ERR_PTR(-ENOMEM); in extcon_dev_allocate()
1056 edev->max_supported = 0; in extcon_dev_allocate()
1057 edev->supported_cable = supported_cable; in extcon_dev_allocate()
1063 * extcon_dev_free() - Free the memory of extcon device.
1064 * @edev: the extcon device
1073 * extcon_dev_register() - Register an new extcon device
1074 * @edev: the extcon device to be registered
1081 * of an extcon device by using the extcon_dev_allocate(). And the extcon
1089 static atomic_t edev_no = ATOMIC_INIT(-1); in extcon_dev_register()
1097 if (!edev || !edev->supported_cable) in extcon_dev_register()
1098 return -EINVAL; in extcon_dev_register()
1100 for (; edev->supported_cable[index] != EXTCON_NONE; index++); in extcon_dev_register()
1102 edev->max_supported = index; in extcon_dev_register()
1104 dev_err(&edev->dev, in extcon_dev_register()
1106 return -EINVAL; in extcon_dev_register()
1109 edev->dev.class = extcon_class; in extcon_dev_register()
1110 edev->dev.release = extcon_dev_release; in extcon_dev_register()
1112 edev->name = dev_name(edev->dev.parent); in extcon_dev_register()
1113 if (IS_ERR_OR_NULL(edev->name)) { in extcon_dev_register()
1114 dev_err(&edev->dev, in extcon_dev_register()
1115 "extcon device name is null\n"); in extcon_dev_register()
1116 return -EINVAL; in extcon_dev_register()
1118 dev_set_name(&edev->dev, "extcon%lu", in extcon_dev_register()
1121 if (edev->max_supported) { in extcon_dev_register()
1125 edev->cables = kcalloc(edev->max_supported, in extcon_dev_register()
1128 if (!edev->cables) { in extcon_dev_register()
1129 ret = -ENOMEM; in extcon_dev_register()
1132 for (index = 0; index < edev->max_supported; index++) { in extcon_dev_register()
1133 cable = &edev->cables[index]; in extcon_dev_register()
1137 for (index--; index >= 0; index--) { in extcon_dev_register()
1138 cable = &edev->cables[index]; in extcon_dev_register()
1139 kfree(cable->attr_g.name); in extcon_dev_register()
1141 ret = -ENOMEM; in extcon_dev_register()
1146 cable->edev = edev; in extcon_dev_register()
1147 cable->cable_index = index; in extcon_dev_register()
1148 cable->attrs[0] = &cable->attr_name.attr; in extcon_dev_register()
1149 cable->attrs[1] = &cable->attr_state.attr; in extcon_dev_register()
1150 cable->attrs[2] = NULL; in extcon_dev_register()
1151 cable->attr_g.name = str; in extcon_dev_register()
1152 cable->attr_g.attrs = cable->attrs; in extcon_dev_register()
1154 sysfs_attr_init(&cable->attr_name.attr); in extcon_dev_register()
1155 cable->attr_name.attr.name = "name"; in extcon_dev_register()
1156 cable->attr_name.attr.mode = 0444; in extcon_dev_register()
1157 cable->attr_name.show = cable_name_show; in extcon_dev_register()
1159 sysfs_attr_init(&cable->attr_state.attr); in extcon_dev_register()
1160 cable->attr_state.attr.name = "state"; in extcon_dev_register()
1161 cable->attr_state.attr.mode = 0444; in extcon_dev_register()
1162 cable->attr_state.show = cable_state_show; in extcon_dev_register()
1166 if (edev->max_supported && edev->mutually_exclusive) { in extcon_dev_register()
1170 for (index = 0; edev->mutually_exclusive[index]; index++) in extcon_dev_register()
1173 edev->attrs_muex = kcalloc(index + 1, in extcon_dev_register()
1176 if (!edev->attrs_muex) { in extcon_dev_register()
1177 ret = -ENOMEM; in extcon_dev_register()
1181 edev->d_attrs_muex = kcalloc(index, in extcon_dev_register()
1184 if (!edev->d_attrs_muex) { in extcon_dev_register()
1185 ret = -ENOMEM; in extcon_dev_register()
1186 kfree(edev->attrs_muex); in extcon_dev_register()
1190 for (index = 0; edev->mutually_exclusive[index]; index++) { in extcon_dev_register()
1192 edev->mutually_exclusive[index]); in extcon_dev_register()
1194 for (index--; index >= 0; index--) { in extcon_dev_register()
1195 kfree(edev->d_attrs_muex[index].attr. in extcon_dev_register()
1198 kfree(edev->d_attrs_muex); in extcon_dev_register()
1199 kfree(edev->attrs_muex); in extcon_dev_register()
1200 ret = -ENOMEM; in extcon_dev_register()
1203 sysfs_attr_init(&edev->d_attrs_muex[index].attr); in extcon_dev_register()
1204 edev->d_attrs_muex[index].attr.name = name; in extcon_dev_register()
1205 edev->d_attrs_muex[index].attr.mode = 0000; in extcon_dev_register()
1206 edev->attrs_muex[index] = &edev->d_attrs_muex[index] in extcon_dev_register()
1209 edev->attr_g_muex.name = muex_name; in extcon_dev_register()
1210 edev->attr_g_muex.attrs = edev->attrs_muex; in extcon_dev_register()
1214 if (edev->max_supported) { in extcon_dev_register()
1215 edev->extcon_dev_type.groups = in extcon_dev_register()
1216 kcalloc(edev->max_supported + 2, in extcon_dev_register()
1219 if (!edev->extcon_dev_type.groups) { in extcon_dev_register()
1220 ret = -ENOMEM; in extcon_dev_register()
1224 edev->extcon_dev_type.name = dev_name(&edev->dev); in extcon_dev_register()
1225 edev->extcon_dev_type.release = dummy_sysfs_dev_release; in extcon_dev_register()
1227 for (index = 0; index < edev->max_supported; index++) in extcon_dev_register()
1228 edev->extcon_dev_type.groups[index] = in extcon_dev_register()
1229 &edev->cables[index].attr_g; in extcon_dev_register()
1230 if (edev->mutually_exclusive) in extcon_dev_register()
1231 edev->extcon_dev_type.groups[index] = in extcon_dev_register()
1232 &edev->attr_g_muex; in extcon_dev_register()
1234 edev->dev.type = &edev->extcon_dev_type; in extcon_dev_register()
1237 spin_lock_init(&edev->lock); in extcon_dev_register()
1238 if (edev->max_supported) { in extcon_dev_register()
1239 edev->nh = kcalloc(edev->max_supported, sizeof(*edev->nh), in extcon_dev_register()
1241 if (!edev->nh) { in extcon_dev_register()
1242 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()
1255 ret = device_register(&edev->dev); in extcon_dev_register()
1257 put_device(&edev->dev); in extcon_dev_register()
1262 list_add(&edev->entry, &extcon_dev_list); in extcon_dev_register()
1268 if (edev->max_supported) in extcon_dev_register()
1269 kfree(edev->nh); in extcon_dev_register()
1271 if (edev->max_supported) in extcon_dev_register()
1272 kfree(edev->extcon_dev_type.groups); in extcon_dev_register()
1274 if (edev->max_supported && edev->mutually_exclusive) { in extcon_dev_register()
1275 for (index = 0; edev->mutually_exclusive[index]; index++) in extcon_dev_register()
1276 kfree(edev->d_attrs_muex[index].attr.name); in extcon_dev_register()
1277 kfree(edev->d_attrs_muex); in extcon_dev_register()
1278 kfree(edev->attrs_muex); in extcon_dev_register()
1281 for (index = 0; index < edev->max_supported; index++) in extcon_dev_register()
1282 kfree(edev->cables[index].attr_g.name); in extcon_dev_register()
1284 if (edev->max_supported) in extcon_dev_register()
1285 kfree(edev->cables); in extcon_dev_register()
1292 * extcon_dev_unregister() - Unregister the extcon device.
1293 * @edev: the extcon device to be unregistered.
1306 list_del(&edev->entry); in extcon_dev_unregister()
1309 if (IS_ERR_OR_NULL(get_device(&edev->dev))) { in extcon_dev_unregister()
1310 dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n", in extcon_dev_unregister()
1311 dev_name(&edev->dev)); in extcon_dev_unregister()
1315 device_unregister(&edev->dev); in extcon_dev_unregister()
1317 if (edev->mutually_exclusive && edev->max_supported) { in extcon_dev_unregister()
1318 for (index = 0; edev->mutually_exclusive[index]; in extcon_dev_unregister()
1320 kfree(edev->d_attrs_muex[index].attr.name); in extcon_dev_unregister()
1321 kfree(edev->d_attrs_muex); in extcon_dev_unregister()
1322 kfree(edev->attrs_muex); in extcon_dev_unregister()
1325 for (index = 0; index < edev->max_supported; index++) in extcon_dev_unregister()
1326 kfree(edev->cables[index].attr_g.name); in extcon_dev_unregister()
1328 if (edev->max_supported) { in extcon_dev_unregister()
1329 kfree(edev->extcon_dev_type.groups); in extcon_dev_unregister()
1330 kfree(edev->cables); in extcon_dev_unregister()
1331 kfree(edev->nh); in extcon_dev_unregister()
1334 put_device(&edev->dev); in extcon_dev_unregister()
1341 * extcon_find_edev_by_node - Find the extcon device from devicetree.
1344 * Return the pointer of extcon device if success or ERR_PTR(err) if fail.
1352 if (edev->dev.parent && edev->dev.parent->of_node == node) in extcon_find_edev_by_node()
1354 edev = ERR_PTR(-EPROBE_DEFER); in extcon_find_edev_by_node()
1362 * extcon_get_edev_by_phandle - Get the extcon device from devicetree.
1363 * @dev : the instance to the given device
1366 * Return the pointer of extcon device if success or ERR_PTR(err) if fail.
1368 struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) in extcon_get_edev_by_phandle()
1374 return ERR_PTR(-EINVAL); in extcon_get_edev_by_phandle()
1376 if (!dev->of_node) { in extcon_get_edev_by_phandle()
1377 dev_dbg(dev, "device does not have a device node entry\n"); in extcon_get_edev_by_phandle()
1378 return ERR_PTR(-EINVAL); in extcon_get_edev_by_phandle()
1381 node = of_parse_phandle(dev->of_node, "extcon", index); in extcon_get_edev_by_phandle()
1384 dev->of_node); in extcon_get_edev_by_phandle()
1385 return ERR_PTR(-ENODEV); in extcon_get_edev_by_phandle()
1398 return ERR_PTR(-ENOSYS); in extcon_find_edev_by_node()
1401 struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) in extcon_get_edev_by_phandle()
1403 return ERR_PTR(-ENOSYS); in extcon_get_edev_by_phandle()
1412 * extcon_get_edev_name() - Get the name of the extcon device.
1413 * @edev: the extcon device
1417 return !edev ? NULL : edev->name; in extcon_get_edev_name()