]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/blob - drivers/extcon/extcon-class.c
ARM: davinci: da850: generate dtbs for da850 boards
[can-eth-gw-linux.git] / drivers / extcon / extcon-class.c
1 /*
2  *  drivers/extcon/extcon_class.c
3  *
4  *  External connector (extcon) class driver
5  *
6  * Copyright (C) 2012 Samsung Electronics
7  * Author: Donggeun Kim <dg77.kim@samsung.com>
8  * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
9  *
10  * based on android/drivers/switch/switch_class.c
11  * Copyright (C) 2008 Google, Inc.
12  * Author: Mike Lockwood <lockwood@android.com>
13  *
14  * This software is licensed under the terms of the GNU General Public
15  * License version 2, as published by the Free Software Foundation, and
16  * may be copied, distributed, and modified under those terms.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23 */
24
25 #include <linux/module.h>
26 #include <linux/types.h>
27 #include <linux/init.h>
28 #include <linux/device.h>
29 #include <linux/fs.h>
30 #include <linux/err.h>
31 #include <linux/extcon.h>
32 #include <linux/slab.h>
33 #include <linux/sysfs.h>
34
35 /*
36  * extcon_cable_name suggests the standard cable names for commonly used
37  * cable types.
38  *
39  * However, please do not use extcon_cable_name directly for extcon_dev
40  * struct's supported_cable pointer unless your device really supports
41  * every single port-type of the following cable names. Please choose cable
42  * names that are actually used in your extcon device.
43  */
44 const char *extcon_cable_name[] = {
45         [EXTCON_USB]            = "USB",
46         [EXTCON_USB_HOST]       = "USB-Host",
47         [EXTCON_TA]             = "TA",
48         [EXTCON_FAST_CHARGER]   = "Fast-charger",
49         [EXTCON_SLOW_CHARGER]   = "Slow-charger",
50         [EXTCON_CHARGE_DOWNSTREAM]      = "Charge-downstream",
51         [EXTCON_HDMI]           = "HDMI",
52         [EXTCON_MHL]            = "MHL",
53         [EXTCON_DVI]            = "DVI",
54         [EXTCON_VGA]            = "VGA",
55         [EXTCON_DOCK]           = "Dock",
56         [EXTCON_LINE_IN]        = "Line-in",
57         [EXTCON_LINE_OUT]       = "Line-out",
58         [EXTCON_MIC_IN]         = "Microphone",
59         [EXTCON_HEADPHONE_OUT]  = "Headphone",
60         [EXTCON_SPDIF_IN]       = "SPDIF-in",
61         [EXTCON_SPDIF_OUT]      = "SPDIF-out",
62         [EXTCON_VIDEO_IN]       = "Video-in",
63         [EXTCON_VIDEO_OUT]      = "Video-out",
64         [EXTCON_MECHANICAL]     = "Mechanical",
65
66         NULL,
67 };
68
69 static struct class *extcon_class;
70 #if defined(CONFIG_ANDROID)
71 static struct class_compat *switch_class;
72 #endif /* CONFIG_ANDROID */
73
74 static LIST_HEAD(extcon_dev_list);
75 static DEFINE_MUTEX(extcon_dev_list_lock);
76
77 /**
78  * check_mutually_exclusive - Check if new_state violates mutually_exclusive
79  *                          condition.
80  * @edev:       the extcon device
81  * @new_state:  new cable attach status for @edev
82  *
83  * Returns 0 if nothing violates. Returns the index + 1 for the first
84  * violated condition.
85  */
86 static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
87 {
88         int i = 0;
89
90         if (!edev->mutually_exclusive)
91                 return 0;
92
93         for (i = 0; edev->mutually_exclusive[i]; i++) {
94                 int count = 0, j;
95                 u32 correspondants = new_state & edev->mutually_exclusive[i];
96                 u32 exp = 1;
97
98                 for (j = 0; j < 32; j++) {
99                         if (exp & correspondants)
100                                 count++;
101                         if (count > 1)
102                                 return i + 1;
103                         exp <<= 1;
104                 }
105         }
106
107         return 0;
108 }
109
110 static ssize_t state_show(struct device *dev, struct device_attribute *attr,
111                           char *buf)
112 {
113         int i, count = 0;
114         struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
115
116         if (edev->print_state) {
117                 int ret = edev->print_state(edev, buf);
118
119                 if (ret >= 0)
120                         return ret;
121                 /* Use default if failed */
122         }
123
124         if (edev->max_supported == 0)
125                 return sprintf(buf, "%u\n", edev->state);
126
127         for (i = 0; i < SUPPORTED_CABLE_MAX; i++) {
128                 if (!edev->supported_cable[i])
129                         break;
130                 count += sprintf(buf + count, "%s=%d\n",
131                                  edev->supported_cable[i],
132                                  !!(edev->state & (1 << i)));
133         }
134
135         return count;
136 }
137
138 int extcon_set_state(struct extcon_dev *edev, u32 state);
139 static ssize_t state_store(struct device *dev, struct device_attribute *attr,
140                            const char *buf, size_t count)
141 {
142         u32 state;
143         ssize_t ret = 0;
144         struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
145
146         ret = sscanf(buf, "0x%x", &state);
147         if (ret == 0)
148                 ret = -EINVAL;
149         else
150                 ret = extcon_set_state(edev, state);
151
152         if (ret < 0)
153                 return ret;
154
155         return count;
156 }
157
158 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
159                 char *buf)
160 {
161         struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
162
163         /* Optional callback given by the user */
164         if (edev->print_name) {
165                 int ret = edev->print_name(edev, buf);
166                 if (ret >= 0)
167                         return ret;
168         }
169
170         return sprintf(buf, "%s\n", dev_name(edev->dev));
171 }
172
173 static ssize_t cable_name_show(struct device *dev,
174                                struct device_attribute *attr, char *buf)
175 {
176         struct extcon_cable *cable = container_of(attr, struct extcon_cable,
177                                                   attr_name);
178
179         return sprintf(buf, "%s\n",
180                        cable->edev->supported_cable[cable->cable_index]);
181 }
182
183 static ssize_t cable_state_show(struct device *dev,
184                                 struct device_attribute *attr, char *buf)
185 {
186         struct extcon_cable *cable = container_of(attr, struct extcon_cable,
187                                                   attr_state);
188
189         return sprintf(buf, "%d\n",
190                        extcon_get_cable_state_(cable->edev,
191                                                cable->cable_index));
192 }
193
194 static ssize_t cable_state_store(struct device *dev,
195                                  struct device_attribute *attr, const char *buf,
196                                  size_t count)
197 {
198         struct extcon_cable *cable = container_of(attr, struct extcon_cable,
199                                                   attr_state);
200         int ret, state;
201
202         ret = sscanf(buf, "%d", &state);
203         if (ret == 0)
204                 ret = -EINVAL;
205         else
206                 ret = extcon_set_cable_state_(cable->edev, cable->cable_index,
207                                               state);
208
209         if (ret < 0)
210                 return ret;
211         return count;
212 }
213
214 /**
215  * extcon_update_state() - Update the cable attach states of the extcon device
216  *                      only for the masked bits.
217  * @edev:       the extcon device
218  * @mask:       the bit mask to designate updated bits.
219  * @state:      new cable attach status for @edev
220  *
221  * Changing the state sends uevent with environment variable containing
222  * the name of extcon device (envp[0]) and the state output (envp[1]).
223  * Tizen uses this format for extcon device to get events from ports.
224  * Android uses this format as well.
225  *
226  * Note that the notifier provides which bits are changed in the state
227  * variable with the val parameter (second) to the callback.
228  */
229 int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
230 {
231         char name_buf[120];
232         char state_buf[120];
233         char *prop_buf;
234         char *envp[3];
235         int env_offset = 0;
236         int length;
237         unsigned long flags;
238
239         spin_lock_irqsave(&edev->lock, flags);
240
241         if (edev->state != ((edev->state & ~mask) | (state & mask))) {
242                 u32 old_state = edev->state;
243
244                 if (check_mutually_exclusive(edev, (edev->state & ~mask) |
245                                                    (state & mask))) {
246                         spin_unlock_irqrestore(&edev->lock, flags);
247                         return -EPERM;
248                 }
249
250                 edev->state &= ~mask;
251                 edev->state |= state & mask;
252
253                 raw_notifier_call_chain(&edev->nh, old_state, edev);
254
255                 /* This could be in interrupt handler */
256                 prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
257                 if (prop_buf) {
258                         length = name_show(edev->dev, NULL, prop_buf);
259                         if (length > 0) {
260                                 if (prop_buf[length - 1] == '\n')
261                                         prop_buf[length - 1] = 0;
262                                 snprintf(name_buf, sizeof(name_buf),
263                                         "NAME=%s", prop_buf);
264                                 envp[env_offset++] = name_buf;
265                         }
266                         length = state_show(edev->dev, NULL, prop_buf);
267                         if (length > 0) {
268                                 if (prop_buf[length - 1] == '\n')
269                                         prop_buf[length - 1] = 0;
270                                 snprintf(state_buf, sizeof(state_buf),
271                                         "STATE=%s", prop_buf);
272                                 envp[env_offset++] = state_buf;
273                         }
274                         envp[env_offset] = NULL;
275                         /* Unlock early before uevent */
276                         spin_unlock_irqrestore(&edev->lock, flags);
277
278                         kobject_uevent_env(&edev->dev->kobj, KOBJ_CHANGE, envp);
279                         free_page((unsigned long)prop_buf);
280                 } else {
281                         /* Unlock early before uevent */
282                         spin_unlock_irqrestore(&edev->lock, flags);
283
284                         dev_err(edev->dev, "out of memory in extcon_set_state\n");
285                         kobject_uevent(&edev->dev->kobj, KOBJ_CHANGE);
286                 }
287         } else {
288                 /* No changes */
289                 spin_unlock_irqrestore(&edev->lock, flags);
290         }
291
292         return 0;
293 }
294 EXPORT_SYMBOL_GPL(extcon_update_state);
295
296 /**
297  * extcon_set_state() - Set the cable attach states of the extcon device.
298  * @edev:       the extcon device
299  * @state:      new cable attach status for @edev
300  *
301  * Note that notifier provides which bits are changed in the state
302  * variable with the val parameter (second) to the callback.
303  */
304 int extcon_set_state(struct extcon_dev *edev, u32 state)
305 {
306         return extcon_update_state(edev, 0xffffffff, state);
307 }
308 EXPORT_SYMBOL_GPL(extcon_set_state);
309
310 /**
311  * extcon_find_cable_index() - Get the cable index based on the cable name.
312  * @edev:       the extcon device that has the cable.
313  * @cable_name: cable name to be searched.
314  *
315  * Note that accessing a cable state based on cable_index is faster than
316  * cable_name because using cable_name induces a loop with strncmp().
317  * Thus, when get/set_cable_state is repeatedly used, using cable_index
318  * is recommended.
319  */
320 int extcon_find_cable_index(struct extcon_dev *edev, const char *cable_name)
321 {
322         int i;
323
324         if (edev->supported_cable) {
325                 for (i = 0; edev->supported_cable[i]; i++) {
326                         if (!strncmp(edev->supported_cable[i],
327                                 cable_name, CABLE_NAME_MAX))
328                                 return i;
329                 }
330         }
331
332         return -EINVAL;
333 }
334 EXPORT_SYMBOL_GPL(extcon_find_cable_index);
335
336 /**
337  * extcon_get_cable_state_() - Get the status of a specific cable.
338  * @edev:       the extcon device that has the cable.
339  * @index:      cable index that can be retrieved by extcon_find_cable_index().
340  */
341 int extcon_get_cable_state_(struct extcon_dev *edev, int index)
342 {
343         if (index < 0 || (edev->max_supported && edev->max_supported <= index))
344                 return -EINVAL;
345
346         return !!(edev->state & (1 << index));
347 }
348 EXPORT_SYMBOL_GPL(extcon_get_cable_state_);
349
350 /**
351  * extcon_get_cable_state() - Get the status of a specific cable.
352  * @edev:       the extcon device that has the cable.
353  * @cable_name: cable name.
354  *
355  * Note that this is slower than extcon_get_cable_state_.
356  */
357 int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
358 {
359         return extcon_get_cable_state_(edev, extcon_find_cable_index
360                                                 (edev, cable_name));
361 }
362 EXPORT_SYMBOL_GPL(extcon_get_cable_state);
363
364 /**
365  * extcon_get_cable_state_() - Set the status of a specific cable.
366  * @edev:       the extcon device that has the cable.
367  * @index:      cable index that can be retrieved by extcon_find_cable_index().
368  * @cable_state:        the new cable status. The default semantics is
369  *                      true: attached / false: detached.
370  */
371 int extcon_set_cable_state_(struct extcon_dev *edev,
372                         int index, bool cable_state)
373 {
374         u32 state;
375
376         if (index < 0 || (edev->max_supported && edev->max_supported <= index))
377                 return -EINVAL;
378
379         state = cable_state ? (1 << index) : 0;
380         return extcon_update_state(edev, 1 << index, state);
381 }
382 EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
383
384 /**
385  * extcon_get_cable_state() - Set the status of a specific cable.
386  * @edev:       the extcon device that has the cable.
387  * @cable_name: cable name.
388  * @cable_state:        the new cable status. The default semantics is
389  *                      true: attached / false: detached.
390  *
391  * Note that this is slower than extcon_set_cable_state_.
392  */
393 int extcon_set_cable_state(struct extcon_dev *edev,
394                         const char *cable_name, bool cable_state)
395 {
396         return extcon_set_cable_state_(edev, extcon_find_cable_index
397                                         (edev, cable_name), cable_state);
398 }
399 EXPORT_SYMBOL_GPL(extcon_set_cable_state);
400
401 /**
402  * extcon_get_extcon_dev() - Get the extcon device instance from the name
403  * @extcon_name:        The extcon name provided with extcon_dev_register()
404  */
405 struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
406 {
407         struct extcon_dev *sd;
408
409         mutex_lock(&extcon_dev_list_lock);
410         list_for_each_entry(sd, &extcon_dev_list, entry) {
411                 if (!strcmp(sd->name, extcon_name))
412                         goto out;
413         }
414         sd = NULL;
415 out:
416         mutex_unlock(&extcon_dev_list_lock);
417         return sd;
418 }
419 EXPORT_SYMBOL_GPL(extcon_get_extcon_dev);
420
421 static int _call_per_cable(struct notifier_block *nb, unsigned long val,
422                            void *ptr)
423 {
424         struct extcon_specific_cable_nb *obj = container_of(nb,
425                         struct extcon_specific_cable_nb, internal_nb);
426         struct extcon_dev *edev = ptr;
427
428         if ((val & (1 << obj->cable_index)) !=
429             (edev->state & (1 << obj->cable_index))) {
430                 bool cable_state = true;
431
432                 obj->previous_value = val;
433
434                 if (val & (1 << obj->cable_index))
435                         cable_state = false;
436
437                 return obj->user_nb->notifier_call(obj->user_nb,
438                                 cable_state, ptr);
439         }
440
441         return NOTIFY_OK;
442 }
443
444 /**
445  * extcon_register_interest() - Register a notifier for a state change of a
446  *                            specific cable, not an entier set of cables of a
447  *                            extcon device.
448  * @obj:        an empty extcon_specific_cable_nb object to be returned.
449  * @extcon_name:        the name of extcon device.
450  * @cable_name:         the target cable name.
451  * @nb:         the notifier block to get notified.
452  *
453  * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets
454  * the struct for you.
455  *
456  * extcon_register_interest is a helper function for those who want to get
457  * notification for a single specific cable's status change. If a user wants
458  * to get notification for any changes of all cables of a extcon device,
459  * he/she should use the general extcon_register_notifier().
460  *
461  * Note that the second parameter given to the callback of nb (val) is
462  * "old_state", not the current state. The current state can be retrieved
463  * by looking at the third pameter (edev pointer)'s state value.
464  */
465 int extcon_register_interest(struct extcon_specific_cable_nb *obj,
466                              const char *extcon_name, const char *cable_name,
467                              struct notifier_block *nb)
468 {
469         if (!obj || !extcon_name || !cable_name || !nb)
470                 return -EINVAL;
471
472         obj->edev = extcon_get_extcon_dev(extcon_name);
473         if (!obj->edev)
474                 return -ENODEV;
475
476         obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
477         if (obj->cable_index < 0)
478                 return -ENODEV;
479
480         obj->user_nb = nb;
481
482         obj->internal_nb.notifier_call = _call_per_cable;
483
484         return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
485 }
486
487 /**
488  * extcon_unregister_interest() - Unregister the notifier registered by
489  *                              extcon_register_interest().
490  * @obj:        the extcon_specific_cable_nb object returned by
491  *              extcon_register_interest().
492  */
493 int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
494 {
495         if (!obj)
496                 return -EINVAL;
497
498         return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
499 }
500
501 /**
502  * extcon_register_notifier() - Register a notifiee to get notified by
503  *                            any attach status changes from the extcon.
504  * @edev:       the extcon device.
505  * @nb:         a notifier block to be registered.
506  *
507  * Note that the second parameter given to the callback of nb (val) is
508  * "old_state", not the current state. The current state can be retrieved
509  * by looking at the third pameter (edev pointer)'s state value.
510  */
511 int extcon_register_notifier(struct extcon_dev *edev,
512                         struct notifier_block *nb)
513 {
514         return raw_notifier_chain_register(&edev->nh, nb);
515 }
516 EXPORT_SYMBOL_GPL(extcon_register_notifier);
517
518 /**
519  * extcon_unregister_notifier() - Unregister a notifiee from the extcon device.
520  * @edev:       the extcon device.
521  * @nb:         a registered notifier block to be unregistered.
522  */
523 int extcon_unregister_notifier(struct extcon_dev *edev,
524                         struct notifier_block *nb)
525 {
526         return raw_notifier_chain_unregister(&edev->nh, nb);
527 }
528 EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
529
530 static struct device_attribute extcon_attrs[] = {
531         __ATTR(state, S_IRUGO | S_IWUSR, state_show, state_store),
532         __ATTR_RO(name),
533         __ATTR_NULL,
534 };
535
536 static int create_extcon_class(void)
537 {
538         if (!extcon_class) {
539                 extcon_class = class_create(THIS_MODULE, "extcon");
540                 if (IS_ERR(extcon_class))
541                         return PTR_ERR(extcon_class);
542                 extcon_class->dev_attrs = extcon_attrs;
543
544 #if defined(CONFIG_ANDROID)
545                 switch_class = class_compat_register("switch");
546                 if (WARN(!switch_class, "cannot allocate"))
547                         return -ENOMEM;
548 #endif /* CONFIG_ANDROID */
549         }
550
551         return 0;
552 }
553
554 static void extcon_cleanup(struct extcon_dev *edev, bool skip)
555 {
556         mutex_lock(&extcon_dev_list_lock);
557         list_del(&edev->entry);
558         mutex_unlock(&extcon_dev_list_lock);
559
560         if (!skip && get_device(edev->dev)) {
561                 int index;
562
563                 if (edev->mutually_exclusive && edev->max_supported) {
564                         for (index = 0; edev->mutually_exclusive[index];
565                              index++)
566                                 kfree(edev->d_attrs_muex[index].attr.name);
567                         kfree(edev->d_attrs_muex);
568                         kfree(edev->attrs_muex);
569                 }
570
571                 for (index = 0; index < edev->max_supported; index++)
572                         kfree(edev->cables[index].attr_g.name);
573
574                 if (edev->max_supported) {
575                         kfree(edev->extcon_dev_type.groups);
576                         kfree(edev->cables);
577                 }
578
579                 device_unregister(edev->dev);
580                 put_device(edev->dev);
581         }
582
583         kfree(edev->dev);
584 }
585
586 static void extcon_dev_release(struct device *dev)
587 {
588         struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
589
590         extcon_cleanup(edev, true);
591 }
592
593 static const char *muex_name = "mutually_exclusive";
594 static void dummy_sysfs_dev_release(struct device *dev)
595 {
596 }
597
598 /**
599  * extcon_dev_register() - Register a new extcon device
600  * @edev        : the new extcon device (should be allocated before calling)
601  * @dev         : the parent device for this extcon device.
602  *
603  * Among the members of edev struct, please set the "user initializing data"
604  * in any case and set the "optional callbacks" if required. However, please
605  * do not set the values of "internal data", which are initialized by
606  * this function.
607  */
608 int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
609 {
610         int ret, index = 0;
611
612         if (!extcon_class) {
613                 ret = create_extcon_class();
614                 if (ret < 0)
615                         return ret;
616         }
617
618         if (edev->supported_cable) {
619                 /* Get size of array */
620                 for (index = 0; edev->supported_cable[index]; index++)
621                         ;
622                 edev->max_supported = index;
623         } else {
624                 edev->max_supported = 0;
625         }
626
627         if (index > SUPPORTED_CABLE_MAX) {
628                 dev_err(edev->dev, "extcon: maximum number of supported cables exceeded.\n");
629                 return -EINVAL;
630         }
631
632         edev->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
633         if (!edev->dev)
634                 return -ENOMEM;
635         edev->dev->parent = dev;
636         edev->dev->class = extcon_class;
637         edev->dev->release = extcon_dev_release;
638
639         dev_set_name(edev->dev, edev->name ? edev->name : dev_name(dev));
640
641         if (edev->max_supported) {
642                 char buf[10];
643                 char *str;
644                 struct extcon_cable *cable;
645
646                 edev->cables = kzalloc(sizeof(struct extcon_cable) *
647                                        edev->max_supported, GFP_KERNEL);
648                 if (!edev->cables) {
649                         ret = -ENOMEM;
650                         goto err_sysfs_alloc;
651                 }
652                 for (index = 0; index < edev->max_supported; index++) {
653                         cable = &edev->cables[index];
654
655                         snprintf(buf, 10, "cable.%d", index);
656                         str = kzalloc(sizeof(char) * (strlen(buf) + 1),
657                                       GFP_KERNEL);
658                         if (!str) {
659                                 for (index--; index >= 0; index--) {
660                                         cable = &edev->cables[index];
661                                         kfree(cable->attr_g.name);
662                                 }
663                                 ret = -ENOMEM;
664
665                                 goto err_alloc_cables;
666                         }
667                         strcpy(str, buf);
668
669                         cable->edev = edev;
670                         cable->cable_index = index;
671                         cable->attrs[0] = &cable->attr_name.attr;
672                         cable->attrs[1] = &cable->attr_state.attr;
673                         cable->attrs[2] = NULL;
674                         cable->attr_g.name = str;
675                         cable->attr_g.attrs = cable->attrs;
676
677                         sysfs_attr_init(&cable->attr_name.attr);
678                         cable->attr_name.attr.name = "name";
679                         cable->attr_name.attr.mode = 0444;
680                         cable->attr_name.show = cable_name_show;
681
682                         sysfs_attr_init(&cable->attr_state.attr);
683                         cable->attr_state.attr.name = "state";
684                         cable->attr_state.attr.mode = 0644;
685                         cable->attr_state.show = cable_state_show;
686                         cable->attr_state.store = cable_state_store;
687                 }
688         }
689
690         if (edev->max_supported && edev->mutually_exclusive) {
691                 char buf[80];
692                 char *name;
693
694                 /* Count the size of mutually_exclusive array */
695                 for (index = 0; edev->mutually_exclusive[index]; index++)
696                         ;
697
698                 edev->attrs_muex = kzalloc(sizeof(struct attribute *) *
699                                            (index + 1), GFP_KERNEL);
700                 if (!edev->attrs_muex) {
701                         ret = -ENOMEM;
702                         goto err_muex;
703                 }
704
705                 edev->d_attrs_muex = kzalloc(sizeof(struct device_attribute) *
706                                              index, GFP_KERNEL);
707                 if (!edev->d_attrs_muex) {
708                         ret = -ENOMEM;
709                         kfree(edev->attrs_muex);
710                         goto err_muex;
711                 }
712
713                 for (index = 0; edev->mutually_exclusive[index]; index++) {
714                         sprintf(buf, "0x%x", edev->mutually_exclusive[index]);
715                         name = kzalloc(sizeof(char) * (strlen(buf) + 1),
716                                        GFP_KERNEL);
717                         if (!name) {
718                                 for (index--; index >= 0; index--) {
719                                         kfree(edev->d_attrs_muex[index].attr.
720                                               name);
721                                 }
722                                 kfree(edev->d_attrs_muex);
723                                 kfree(edev->attrs_muex);
724                                 ret = -ENOMEM;
725                                 goto err_muex;
726                         }
727                         strcpy(name, buf);
728                         sysfs_attr_init(&edev->d_attrs_muex[index].attr);
729                         edev->d_attrs_muex[index].attr.name = name;
730                         edev->d_attrs_muex[index].attr.mode = 0000;
731                         edev->attrs_muex[index] = &edev->d_attrs_muex[index]
732                                                         .attr;
733                 }
734                 edev->attr_g_muex.name = muex_name;
735                 edev->attr_g_muex.attrs = edev->attrs_muex;
736
737         }
738
739         if (edev->max_supported) {
740                 edev->extcon_dev_type.groups =
741                         kzalloc(sizeof(struct attribute_group *) *
742                                 (edev->max_supported + 2), GFP_KERNEL);
743                 if (!edev->extcon_dev_type.groups) {
744                         ret = -ENOMEM;
745                         goto err_alloc_groups;
746                 }
747
748                 edev->extcon_dev_type.name = dev_name(edev->dev);
749                 edev->extcon_dev_type.release = dummy_sysfs_dev_release;
750
751                 for (index = 0; index < edev->max_supported; index++)
752                         edev->extcon_dev_type.groups[index] =
753                                 &edev->cables[index].attr_g;
754                 if (edev->mutually_exclusive)
755                         edev->extcon_dev_type.groups[index] =
756                                 &edev->attr_g_muex;
757
758                 edev->dev->type = &edev->extcon_dev_type;
759         }
760
761         ret = device_register(edev->dev);
762         if (ret) {
763                 put_device(edev->dev);
764                 goto err_dev;
765         }
766 #if defined(CONFIG_ANDROID)
767         if (switch_class)
768                 ret = class_compat_create_link(switch_class, edev->dev,
769                                                NULL);
770 #endif /* CONFIG_ANDROID */
771
772         spin_lock_init(&edev->lock);
773
774         RAW_INIT_NOTIFIER_HEAD(&edev->nh);
775
776         dev_set_drvdata(edev->dev, edev);
777         edev->state = 0;
778
779         mutex_lock(&extcon_dev_list_lock);
780         list_add(&edev->entry, &extcon_dev_list);
781         mutex_unlock(&extcon_dev_list_lock);
782
783         return 0;
784
785 err_dev:
786         if (edev->max_supported)
787                 kfree(edev->extcon_dev_type.groups);
788 err_alloc_groups:
789         if (edev->max_supported && edev->mutually_exclusive) {
790                 for (index = 0; edev->mutually_exclusive[index]; index++)
791                         kfree(edev->d_attrs_muex[index].attr.name);
792                 kfree(edev->d_attrs_muex);
793                 kfree(edev->attrs_muex);
794         }
795 err_muex:
796         for (index = 0; index < edev->max_supported; index++)
797                 kfree(edev->cables[index].attr_g.name);
798 err_alloc_cables:
799         if (edev->max_supported)
800                 kfree(edev->cables);
801 err_sysfs_alloc:
802         kfree(edev->dev);
803         return ret;
804 }
805 EXPORT_SYMBOL_GPL(extcon_dev_register);
806
807 /**
808  * extcon_dev_unregister() - Unregister the extcon device.
809  * @edev:       the extcon device instance to be unregistered.
810  *
811  * Note that this does not call kfree(edev) because edev was not allocated
812  * by this class.
813  */
814 void extcon_dev_unregister(struct extcon_dev *edev)
815 {
816         extcon_cleanup(edev, false);
817 }
818 EXPORT_SYMBOL_GPL(extcon_dev_unregister);
819
820 static int __init extcon_class_init(void)
821 {
822         return create_extcon_class();
823 }
824 module_init(extcon_class_init);
825
826 static void __exit extcon_class_exit(void)
827 {
828         class_destroy(extcon_class);
829 }
830 module_exit(extcon_class_exit);
831
832 MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
833 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
834 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
835 MODULE_DESCRIPTION("External connector (extcon) class driver");
836 MODULE_LICENSE("GPL");