]> Git Repo - J-linux.git/blob - drivers/usb/typec/class.c
drivers: Introduce device lookup variants by name
[J-linux.git] / drivers / usb / typec / class.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * USB Type-C Connector Class
4  *
5  * Copyright (C) 2017, Intel Corporation
6  * Author: Heikki Krogerus <[email protected]>
7  */
8
9 #include <linux/device.h>
10 #include <linux/module.h>
11 #include <linux/mutex.h>
12 #include <linux/property.h>
13 #include <linux/slab.h>
14
15 #include "bus.h"
16
17 struct typec_plug {
18         struct device                   dev;
19         enum typec_plug_index           index;
20         struct ida                      mode_ids;
21 };
22
23 struct typec_cable {
24         struct device                   dev;
25         enum typec_plug_type            type;
26         struct usb_pd_identity          *identity;
27         unsigned int                    active:1;
28 };
29
30 struct typec_partner {
31         struct device                   dev;
32         unsigned int                    usb_pd:1;
33         struct usb_pd_identity          *identity;
34         enum typec_accessory            accessory;
35         struct ida                      mode_ids;
36 };
37
38 struct typec_port {
39         unsigned int                    id;
40         struct device                   dev;
41         struct ida                      mode_ids;
42
43         int                             prefer_role;
44         enum typec_data_role            data_role;
45         enum typec_role                 pwr_role;
46         enum typec_role                 vconn_role;
47         enum typec_pwr_opmode           pwr_opmode;
48         enum typec_port_type            port_type;
49         struct mutex                    port_type_lock;
50
51         enum typec_orientation          orientation;
52         struct typec_switch             *sw;
53         struct typec_mux                *mux;
54
55         const struct typec_capability   *cap;
56 };
57
58 #define to_typec_port(_dev_) container_of(_dev_, struct typec_port, dev)
59 #define to_typec_plug(_dev_) container_of(_dev_, struct typec_plug, dev)
60 #define to_typec_cable(_dev_) container_of(_dev_, struct typec_cable, dev)
61 #define to_typec_partner(_dev_) container_of(_dev_, struct typec_partner, dev)
62
63 static const struct device_type typec_partner_dev_type;
64 static const struct device_type typec_cable_dev_type;
65 static const struct device_type typec_plug_dev_type;
66
67 #define is_typec_partner(_dev_) (_dev_->type == &typec_partner_dev_type)
68 #define is_typec_cable(_dev_) (_dev_->type == &typec_cable_dev_type)
69 #define is_typec_plug(_dev_) (_dev_->type == &typec_plug_dev_type)
70
71 static DEFINE_IDA(typec_index_ida);
72 static struct class *typec_class;
73
74 /* ------------------------------------------------------------------------- */
75 /* Common attributes */
76
77 static const char * const typec_accessory_modes[] = {
78         [TYPEC_ACCESSORY_NONE]          = "none",
79         [TYPEC_ACCESSORY_AUDIO]         = "analog_audio",
80         [TYPEC_ACCESSORY_DEBUG]         = "debug",
81 };
82
83 static struct usb_pd_identity *get_pd_identity(struct device *dev)
84 {
85         if (is_typec_partner(dev)) {
86                 struct typec_partner *partner = to_typec_partner(dev);
87
88                 return partner->identity;
89         } else if (is_typec_cable(dev)) {
90                 struct typec_cable *cable = to_typec_cable(dev);
91
92                 return cable->identity;
93         }
94         return NULL;
95 }
96
97 static ssize_t id_header_show(struct device *dev, struct device_attribute *attr,
98                               char *buf)
99 {
100         struct usb_pd_identity *id = get_pd_identity(dev);
101
102         return sprintf(buf, "0x%08x\n", id->id_header);
103 }
104 static DEVICE_ATTR_RO(id_header);
105
106 static ssize_t cert_stat_show(struct device *dev, struct device_attribute *attr,
107                               char *buf)
108 {
109         struct usb_pd_identity *id = get_pd_identity(dev);
110
111         return sprintf(buf, "0x%08x\n", id->cert_stat);
112 }
113 static DEVICE_ATTR_RO(cert_stat);
114
115 static ssize_t product_show(struct device *dev, struct device_attribute *attr,
116                             char *buf)
117 {
118         struct usb_pd_identity *id = get_pd_identity(dev);
119
120         return sprintf(buf, "0x%08x\n", id->product);
121 }
122 static DEVICE_ATTR_RO(product);
123
124 static struct attribute *usb_pd_id_attrs[] = {
125         &dev_attr_id_header.attr,
126         &dev_attr_cert_stat.attr,
127         &dev_attr_product.attr,
128         NULL
129 };
130
131 static const struct attribute_group usb_pd_id_group = {
132         .name = "identity",
133         .attrs = usb_pd_id_attrs,
134 };
135
136 static const struct attribute_group *usb_pd_id_groups[] = {
137         &usb_pd_id_group,
138         NULL,
139 };
140
141 static void typec_report_identity(struct device *dev)
142 {
143         sysfs_notify(&dev->kobj, "identity", "id_header");
144         sysfs_notify(&dev->kobj, "identity", "cert_stat");
145         sysfs_notify(&dev->kobj, "identity", "product");
146 }
147
148 /* ------------------------------------------------------------------------- */
149 /* Alternate Modes */
150
151 static int altmode_match(struct device *dev, void *data)
152 {
153         struct typec_altmode *adev = to_typec_altmode(dev);
154         struct typec_device_id *id = data;
155
156         if (!is_typec_altmode(dev))
157                 return 0;
158
159         return ((adev->svid == id->svid) && (adev->mode == id->mode));
160 }
161
162 static void typec_altmode_set_partner(struct altmode *altmode)
163 {
164         struct typec_altmode *adev = &altmode->adev;
165         struct typec_device_id id = { adev->svid, adev->mode, };
166         struct typec_port *port = typec_altmode2port(adev);
167         struct altmode *partner;
168         struct device *dev;
169
170         dev = device_find_child(&port->dev, &id, altmode_match);
171         if (!dev)
172                 return;
173
174         /* Bind the port alt mode to the partner/plug alt mode. */
175         partner = to_altmode(to_typec_altmode(dev));
176         altmode->partner = partner;
177
178         /* Bind the partner/plug alt mode to the port alt mode. */
179         if (is_typec_plug(adev->dev.parent)) {
180                 struct typec_plug *plug = to_typec_plug(adev->dev.parent);
181
182                 partner->plug[plug->index] = altmode;
183         } else {
184                 partner->partner = altmode;
185         }
186 }
187
188 static void typec_altmode_put_partner(struct altmode *altmode)
189 {
190         struct altmode *partner = altmode->partner;
191         struct typec_altmode *adev;
192
193         if (!partner)
194                 return;
195
196         adev = &partner->adev;
197
198         if (is_typec_plug(adev->dev.parent)) {
199                 struct typec_plug *plug = to_typec_plug(adev->dev.parent);
200
201                 partner->plug[plug->index] = NULL;
202         } else {
203                 partner->partner = NULL;
204         }
205         put_device(&adev->dev);
206 }
207
208 static int typec_port_fwnode_match(struct device *dev, const void *fwnode)
209 {
210         return dev_fwnode(dev) == fwnode;
211 }
212
213 static void *typec_port_match(struct device_connection *con, int ep, void *data)
214 {
215         struct device *dev;
216
217         /*
218          * FIXME: Check does the fwnode supports the requested SVID. If it does
219          * we need to return ERR_PTR(-PROBE_DEFER) when there is no device.
220          */
221         if (con->fwnode)
222                 return class_find_device(typec_class, NULL, con->fwnode,
223                                          typec_port_fwnode_match);
224
225         dev = class_find_device_by_name(typec_class, con->endpoint[ep]);
226
227         return dev ? dev : ERR_PTR(-EPROBE_DEFER);
228 }
229
230 struct typec_altmode *
231 typec_altmode_register_notifier(struct device *dev, u16 svid, u8 mode,
232                                 struct notifier_block *nb)
233 {
234         struct typec_device_id id = { svid, mode, };
235         struct device *altmode_dev;
236         struct device *port_dev;
237         struct altmode *altmode;
238         int ret;
239
240         /* Find the port linked to the caller */
241         port_dev = device_connection_find_match(dev, NULL, NULL,
242                                                 typec_port_match);
243         if (IS_ERR_OR_NULL(port_dev))
244                 return port_dev ? ERR_CAST(port_dev) : ERR_PTR(-ENODEV);
245
246         /* Find the altmode with matching svid */
247         altmode_dev = device_find_child(port_dev, &id, altmode_match);
248
249         put_device(port_dev);
250
251         if (!altmode_dev)
252                 return ERR_PTR(-ENODEV);
253
254         altmode = to_altmode(to_typec_altmode(altmode_dev));
255
256         /* Register notifier */
257         ret = blocking_notifier_chain_register(&altmode->nh, nb);
258         if (ret) {
259                 put_device(altmode_dev);
260                 return ERR_PTR(ret);
261         }
262
263         return &altmode->adev;
264 }
265 EXPORT_SYMBOL_GPL(typec_altmode_register_notifier);
266
267 void typec_altmode_unregister_notifier(struct typec_altmode *adev,
268                                        struct notifier_block *nb)
269 {
270         struct altmode *altmode = to_altmode(adev);
271
272         blocking_notifier_chain_unregister(&altmode->nh, nb);
273         put_device(&adev->dev);
274 }
275 EXPORT_SYMBOL_GPL(typec_altmode_unregister_notifier);
276
277 /**
278  * typec_altmode_update_active - Report Enter/Exit mode
279  * @adev: Handle to the alternate mode
280  * @active: True when the mode has been entered
281  *
282  * If a partner or cable plug executes Enter/Exit Mode command successfully, the
283  * drivers use this routine to report the updated state of the mode.
284  */
285 void typec_altmode_update_active(struct typec_altmode *adev, bool active)
286 {
287         char dir[6];
288
289         if (adev->active == active)
290                 return;
291
292         if (!is_typec_port(adev->dev.parent) && adev->dev.driver) {
293                 if (!active)
294                         module_put(adev->dev.driver->owner);
295                 else
296                         WARN_ON(!try_module_get(adev->dev.driver->owner));
297         }
298
299         adev->active = active;
300         snprintf(dir, sizeof(dir), "mode%d", adev->mode);
301         sysfs_notify(&adev->dev.kobj, dir, "active");
302         sysfs_notify(&adev->dev.kobj, NULL, "active");
303         kobject_uevent(&adev->dev.kobj, KOBJ_CHANGE);
304 }
305 EXPORT_SYMBOL_GPL(typec_altmode_update_active);
306
307 /**
308  * typec_altmode2port - Alternate Mode to USB Type-C port
309  * @alt: The Alternate Mode
310  *
311  * Returns handle to the port that a cable plug or partner with @alt is
312  * connected to.
313  */
314 struct typec_port *typec_altmode2port(struct typec_altmode *alt)
315 {
316         if (is_typec_plug(alt->dev.parent))
317                 return to_typec_port(alt->dev.parent->parent->parent);
318         if (is_typec_partner(alt->dev.parent))
319                 return to_typec_port(alt->dev.parent->parent);
320         if (is_typec_port(alt->dev.parent))
321                 return to_typec_port(alt->dev.parent);
322
323         return NULL;
324 }
325 EXPORT_SYMBOL_GPL(typec_altmode2port);
326
327 static ssize_t
328 vdo_show(struct device *dev, struct device_attribute *attr, char *buf)
329 {
330         struct typec_altmode *alt = to_typec_altmode(dev);
331
332         return sprintf(buf, "0x%08x\n", alt->vdo);
333 }
334 static DEVICE_ATTR_RO(vdo);
335
336 static ssize_t
337 description_show(struct device *dev, struct device_attribute *attr, char *buf)
338 {
339         struct typec_altmode *alt = to_typec_altmode(dev);
340
341         return sprintf(buf, "%s\n", alt->desc ? alt->desc : "");
342 }
343 static DEVICE_ATTR_RO(description);
344
345 static ssize_t
346 active_show(struct device *dev, struct device_attribute *attr, char *buf)
347 {
348         struct typec_altmode *alt = to_typec_altmode(dev);
349
350         return sprintf(buf, "%s\n", alt->active ? "yes" : "no");
351 }
352
353 static ssize_t active_store(struct device *dev, struct device_attribute *attr,
354                             const char *buf, size_t size)
355 {
356         struct typec_altmode *adev = to_typec_altmode(dev);
357         struct altmode *altmode = to_altmode(adev);
358         bool enter;
359         int ret;
360
361         ret = kstrtobool(buf, &enter);
362         if (ret)
363                 return ret;
364
365         if (adev->active == enter)
366                 return size;
367
368         if (is_typec_port(adev->dev.parent)) {
369                 typec_altmode_update_active(adev, enter);
370
371                 /* Make sure that the partner exits the mode before disabling */
372                 if (altmode->partner && !enter && altmode->partner->adev.active)
373                         typec_altmode_exit(&altmode->partner->adev);
374         } else if (altmode->partner) {
375                 if (enter && !altmode->partner->adev.active) {
376                         dev_warn(dev, "port has the mode disabled\n");
377                         return -EPERM;
378                 }
379         }
380
381         /* Note: If there is no driver, the mode will not be entered */
382         if (adev->ops && adev->ops->activate) {
383                 ret = adev->ops->activate(adev, enter);
384                 if (ret)
385                         return ret;
386         }
387
388         return size;
389 }
390 static DEVICE_ATTR_RW(active);
391
392 static ssize_t
393 supported_roles_show(struct device *dev, struct device_attribute *attr,
394                      char *buf)
395 {
396         struct altmode *alt = to_altmode(to_typec_altmode(dev));
397         ssize_t ret;
398
399         switch (alt->roles) {
400         case TYPEC_PORT_SRC:
401                 ret = sprintf(buf, "source\n");
402                 break;
403         case TYPEC_PORT_SNK:
404                 ret = sprintf(buf, "sink\n");
405                 break;
406         case TYPEC_PORT_DRP:
407         default:
408                 ret = sprintf(buf, "source sink\n");
409                 break;
410         }
411         return ret;
412 }
413 static DEVICE_ATTR_RO(supported_roles);
414
415 static ssize_t
416 mode_show(struct device *dev, struct device_attribute *attr, char *buf)
417 {
418         struct typec_altmode *adev = to_typec_altmode(dev);
419
420         return sprintf(buf, "%u\n", adev->mode);
421 }
422 static DEVICE_ATTR_RO(mode);
423
424 static ssize_t
425 svid_show(struct device *dev, struct device_attribute *attr, char *buf)
426 {
427         struct typec_altmode *adev = to_typec_altmode(dev);
428
429         return sprintf(buf, "%04x\n", adev->svid);
430 }
431 static DEVICE_ATTR_RO(svid);
432
433 static struct attribute *typec_altmode_attrs[] = {
434         &dev_attr_active.attr,
435         &dev_attr_mode.attr,
436         &dev_attr_svid.attr,
437         &dev_attr_vdo.attr,
438         NULL
439 };
440 ATTRIBUTE_GROUPS(typec_altmode);
441
442 static int altmode_id_get(struct device *dev)
443 {
444         struct ida *ids;
445
446         if (is_typec_partner(dev))
447                 ids = &to_typec_partner(dev)->mode_ids;
448         else if (is_typec_plug(dev))
449                 ids = &to_typec_plug(dev)->mode_ids;
450         else
451                 ids = &to_typec_port(dev)->mode_ids;
452
453         return ida_simple_get(ids, 0, 0, GFP_KERNEL);
454 }
455
456 static void altmode_id_remove(struct device *dev, int id)
457 {
458         struct ida *ids;
459
460         if (is_typec_partner(dev))
461                 ids = &to_typec_partner(dev)->mode_ids;
462         else if (is_typec_plug(dev))
463                 ids = &to_typec_plug(dev)->mode_ids;
464         else
465                 ids = &to_typec_port(dev)->mode_ids;
466
467         ida_simple_remove(ids, id);
468 }
469
470 static void typec_altmode_release(struct device *dev)
471 {
472         struct altmode *alt = to_altmode(to_typec_altmode(dev));
473
474         typec_altmode_put_partner(alt);
475
476         altmode_id_remove(alt->adev.dev.parent, alt->id);
477         kfree(alt);
478 }
479
480 const struct device_type typec_altmode_dev_type = {
481         .name = "typec_alternate_mode",
482         .groups = typec_altmode_groups,
483         .release = typec_altmode_release,
484 };
485
486 static struct typec_altmode *
487 typec_register_altmode(struct device *parent,
488                        const struct typec_altmode_desc *desc)
489 {
490         unsigned int id = altmode_id_get(parent);
491         bool is_port = is_typec_port(parent);
492         struct altmode *alt;
493         int ret;
494
495         alt = kzalloc(sizeof(*alt), GFP_KERNEL);
496         if (!alt)
497                 return ERR_PTR(-ENOMEM);
498
499         alt->adev.svid = desc->svid;
500         alt->adev.mode = desc->mode;
501         alt->adev.vdo = desc->vdo;
502         alt->roles = desc->roles;
503         alt->id = id;
504
505         alt->attrs[0] = &dev_attr_vdo.attr;
506         alt->attrs[1] = &dev_attr_description.attr;
507         alt->attrs[2] = &dev_attr_active.attr;
508
509         if (is_port) {
510                 alt->attrs[3] = &dev_attr_supported_roles.attr;
511                 alt->adev.active = true; /* Enabled by default */
512         }
513
514         sprintf(alt->group_name, "mode%d", desc->mode);
515         alt->group.name = alt->group_name;
516         alt->group.attrs = alt->attrs;
517         alt->groups[0] = &alt->group;
518
519         alt->adev.dev.parent = parent;
520         alt->adev.dev.groups = alt->groups;
521         alt->adev.dev.type = &typec_altmode_dev_type;
522         dev_set_name(&alt->adev.dev, "%s.%u", dev_name(parent), id);
523
524         /* Link partners and plugs with the ports */
525         if (is_port)
526                 BLOCKING_INIT_NOTIFIER_HEAD(&alt->nh);
527         else
528                 typec_altmode_set_partner(alt);
529
530         /* The partners are bind to drivers */
531         if (is_typec_partner(parent))
532                 alt->adev.dev.bus = &typec_bus;
533
534         ret = device_register(&alt->adev.dev);
535         if (ret) {
536                 dev_err(parent, "failed to register alternate mode (%d)\n",
537                         ret);
538                 put_device(&alt->adev.dev);
539                 return ERR_PTR(ret);
540         }
541
542         return &alt->adev;
543 }
544
545 /**
546  * typec_unregister_altmode - Unregister Alternate Mode
547  * @adev: The alternate mode to be unregistered
548  *
549  * Unregister device created with typec_partner_register_altmode(),
550  * typec_plug_register_altmode() or typec_port_register_altmode().
551  */
552 void typec_unregister_altmode(struct typec_altmode *adev)
553 {
554         if (IS_ERR_OR_NULL(adev))
555                 return;
556         typec_mux_put(to_altmode(adev)->mux);
557         device_unregister(&adev->dev);
558 }
559 EXPORT_SYMBOL_GPL(typec_unregister_altmode);
560
561 /* ------------------------------------------------------------------------- */
562 /* Type-C Partners */
563
564 static ssize_t accessory_mode_show(struct device *dev,
565                                    struct device_attribute *attr,
566                                    char *buf)
567 {
568         struct typec_partner *p = to_typec_partner(dev);
569
570         return sprintf(buf, "%s\n", typec_accessory_modes[p->accessory]);
571 }
572 static DEVICE_ATTR_RO(accessory_mode);
573
574 static ssize_t supports_usb_power_delivery_show(struct device *dev,
575                                                 struct device_attribute *attr,
576                                                 char *buf)
577 {
578         struct typec_partner *p = to_typec_partner(dev);
579
580         return sprintf(buf, "%s\n", p->usb_pd ? "yes" : "no");
581 }
582 static DEVICE_ATTR_RO(supports_usb_power_delivery);
583
584 static struct attribute *typec_partner_attrs[] = {
585         &dev_attr_accessory_mode.attr,
586         &dev_attr_supports_usb_power_delivery.attr,
587         NULL
588 };
589 ATTRIBUTE_GROUPS(typec_partner);
590
591 static void typec_partner_release(struct device *dev)
592 {
593         struct typec_partner *partner = to_typec_partner(dev);
594
595         ida_destroy(&partner->mode_ids);
596         kfree(partner);
597 }
598
599 static const struct device_type typec_partner_dev_type = {
600         .name = "typec_partner",
601         .groups = typec_partner_groups,
602         .release = typec_partner_release,
603 };
604
605 /**
606  * typec_partner_set_identity - Report result from Discover Identity command
607  * @partner: The partner updated identity values
608  *
609  * This routine is used to report that the result of Discover Identity USB power
610  * delivery command has become available.
611  */
612 int typec_partner_set_identity(struct typec_partner *partner)
613 {
614         if (!partner->identity)
615                 return -EINVAL;
616
617         typec_report_identity(&partner->dev);
618         return 0;
619 }
620 EXPORT_SYMBOL_GPL(typec_partner_set_identity);
621
622 /**
623  * typec_partner_register_altmode - Register USB Type-C Partner Alternate Mode
624  * @partner: USB Type-C Partner that supports the alternate mode
625  * @desc: Description of the alternate mode
626  *
627  * This routine is used to register each alternate mode individually that
628  * @partner has listed in response to Discover SVIDs command. The modes for a
629  * SVID listed in response to Discover Modes command need to be listed in an
630  * array in @desc.
631  *
632  * Returns handle to the alternate mode on success or NULL on failure.
633  */
634 struct typec_altmode *
635 typec_partner_register_altmode(struct typec_partner *partner,
636                                const struct typec_altmode_desc *desc)
637 {
638         return typec_register_altmode(&partner->dev, desc);
639 }
640 EXPORT_SYMBOL_GPL(typec_partner_register_altmode);
641
642 /**
643  * typec_register_partner - Register a USB Type-C Partner
644  * @port: The USB Type-C Port the partner is connected to
645  * @desc: Description of the partner
646  *
647  * Registers a device for USB Type-C Partner described in @desc.
648  *
649  * Returns handle to the partner on success or ERR_PTR on failure.
650  */
651 struct typec_partner *typec_register_partner(struct typec_port *port,
652                                              struct typec_partner_desc *desc)
653 {
654         struct typec_partner *partner;
655         int ret;
656
657         partner = kzalloc(sizeof(*partner), GFP_KERNEL);
658         if (!partner)
659                 return ERR_PTR(-ENOMEM);
660
661         ida_init(&partner->mode_ids);
662         partner->usb_pd = desc->usb_pd;
663         partner->accessory = desc->accessory;
664
665         if (desc->identity) {
666                 /*
667                  * Creating directory for the identity only if the driver is
668                  * able to provide data to it.
669                  */
670                 partner->dev.groups = usb_pd_id_groups;
671                 partner->identity = desc->identity;
672         }
673
674         partner->dev.class = typec_class;
675         partner->dev.parent = &port->dev;
676         partner->dev.type = &typec_partner_dev_type;
677         dev_set_name(&partner->dev, "%s-partner", dev_name(&port->dev));
678
679         ret = device_register(&partner->dev);
680         if (ret) {
681                 dev_err(&port->dev, "failed to register partner (%d)\n", ret);
682                 put_device(&partner->dev);
683                 return ERR_PTR(ret);
684         }
685
686         return partner;
687 }
688 EXPORT_SYMBOL_GPL(typec_register_partner);
689
690 /**
691  * typec_unregister_partner - Unregister a USB Type-C Partner
692  * @partner: The partner to be unregistered
693  *
694  * Unregister device created with typec_register_partner().
695  */
696 void typec_unregister_partner(struct typec_partner *partner)
697 {
698         if (!IS_ERR_OR_NULL(partner))
699                 device_unregister(&partner->dev);
700 }
701 EXPORT_SYMBOL_GPL(typec_unregister_partner);
702
703 /* ------------------------------------------------------------------------- */
704 /* Type-C Cable Plugs */
705
706 static void typec_plug_release(struct device *dev)
707 {
708         struct typec_plug *plug = to_typec_plug(dev);
709
710         ida_destroy(&plug->mode_ids);
711         kfree(plug);
712 }
713
714 static const struct device_type typec_plug_dev_type = {
715         .name = "typec_plug",
716         .release = typec_plug_release,
717 };
718
719 /**
720  * typec_plug_register_altmode - Register USB Type-C Cable Plug Alternate Mode
721  * @plug: USB Type-C Cable Plug that supports the alternate mode
722  * @desc: Description of the alternate mode
723  *
724  * This routine is used to register each alternate mode individually that @plug
725  * has listed in response to Discover SVIDs command. The modes for a SVID that
726  * the plug lists in response to Discover Modes command need to be listed in an
727  * array in @desc.
728  *
729  * Returns handle to the alternate mode on success or ERR_PTR on failure.
730  */
731 struct typec_altmode *
732 typec_plug_register_altmode(struct typec_plug *plug,
733                             const struct typec_altmode_desc *desc)
734 {
735         return typec_register_altmode(&plug->dev, desc);
736 }
737 EXPORT_SYMBOL_GPL(typec_plug_register_altmode);
738
739 /**
740  * typec_register_plug - Register a USB Type-C Cable Plug
741  * @cable: USB Type-C Cable with the plug
742  * @desc: Description of the cable plug
743  *
744  * Registers a device for USB Type-C Cable Plug described in @desc. A USB Type-C
745  * Cable Plug represents a plug with electronics in it that can response to USB
746  * Power Delivery SOP Prime or SOP Double Prime packages.
747  *
748  * Returns handle to the cable plug on success or ERR_PTR on failure.
749  */
750 struct typec_plug *typec_register_plug(struct typec_cable *cable,
751                                        struct typec_plug_desc *desc)
752 {
753         struct typec_plug *plug;
754         char name[8];
755         int ret;
756
757         plug = kzalloc(sizeof(*plug), GFP_KERNEL);
758         if (!plug)
759                 return ERR_PTR(-ENOMEM);
760
761         sprintf(name, "plug%d", desc->index);
762
763         ida_init(&plug->mode_ids);
764         plug->index = desc->index;
765         plug->dev.class = typec_class;
766         plug->dev.parent = &cable->dev;
767         plug->dev.type = &typec_plug_dev_type;
768         dev_set_name(&plug->dev, "%s-%s", dev_name(cable->dev.parent), name);
769
770         ret = device_register(&plug->dev);
771         if (ret) {
772                 dev_err(&cable->dev, "failed to register plug (%d)\n", ret);
773                 put_device(&plug->dev);
774                 return ERR_PTR(ret);
775         }
776
777         return plug;
778 }
779 EXPORT_SYMBOL_GPL(typec_register_plug);
780
781 /**
782  * typec_unregister_plug - Unregister a USB Type-C Cable Plug
783  * @plug: The cable plug to be unregistered
784  *
785  * Unregister device created with typec_register_plug().
786  */
787 void typec_unregister_plug(struct typec_plug *plug)
788 {
789         if (!IS_ERR_OR_NULL(plug))
790                 device_unregister(&plug->dev);
791 }
792 EXPORT_SYMBOL_GPL(typec_unregister_plug);
793
794 /* Type-C Cables */
795
796 static ssize_t
797 type_show(struct device *dev, struct device_attribute *attr, char *buf)
798 {
799         struct typec_cable *cable = to_typec_cable(dev);
800
801         return sprintf(buf, "%s\n", cable->active ? "active" : "passive");
802 }
803 static DEVICE_ATTR_RO(type);
804
805 static const char * const typec_plug_types[] = {
806         [USB_PLUG_NONE]         = "unknown",
807         [USB_PLUG_TYPE_A]       = "type-a",
808         [USB_PLUG_TYPE_B]       = "type-b",
809         [USB_PLUG_TYPE_C]       = "type-c",
810         [USB_PLUG_CAPTIVE]      = "captive",
811 };
812
813 static ssize_t plug_type_show(struct device *dev,
814                               struct device_attribute *attr, char *buf)
815 {
816         struct typec_cable *cable = to_typec_cable(dev);
817
818         return sprintf(buf, "%s\n", typec_plug_types[cable->type]);
819 }
820 static DEVICE_ATTR_RO(plug_type);
821
822 static struct attribute *typec_cable_attrs[] = {
823         &dev_attr_type.attr,
824         &dev_attr_plug_type.attr,
825         NULL
826 };
827 ATTRIBUTE_GROUPS(typec_cable);
828
829 static void typec_cable_release(struct device *dev)
830 {
831         struct typec_cable *cable = to_typec_cable(dev);
832
833         kfree(cable);
834 }
835
836 static const struct device_type typec_cable_dev_type = {
837         .name = "typec_cable",
838         .groups = typec_cable_groups,
839         .release = typec_cable_release,
840 };
841
842 /**
843  * typec_cable_set_identity - Report result from Discover Identity command
844  * @cable: The cable updated identity values
845  *
846  * This routine is used to report that the result of Discover Identity USB power
847  * delivery command has become available.
848  */
849 int typec_cable_set_identity(struct typec_cable *cable)
850 {
851         if (!cable->identity)
852                 return -EINVAL;
853
854         typec_report_identity(&cable->dev);
855         return 0;
856 }
857 EXPORT_SYMBOL_GPL(typec_cable_set_identity);
858
859 /**
860  * typec_register_cable - Register a USB Type-C Cable
861  * @port: The USB Type-C Port the cable is connected to
862  * @desc: Description of the cable
863  *
864  * Registers a device for USB Type-C Cable described in @desc. The cable will be
865  * parent for the optional cable plug devises.
866  *
867  * Returns handle to the cable on success or ERR_PTR on failure.
868  */
869 struct typec_cable *typec_register_cable(struct typec_port *port,
870                                          struct typec_cable_desc *desc)
871 {
872         struct typec_cable *cable;
873         int ret;
874
875         cable = kzalloc(sizeof(*cable), GFP_KERNEL);
876         if (!cable)
877                 return ERR_PTR(-ENOMEM);
878
879         cable->type = desc->type;
880         cable->active = desc->active;
881
882         if (desc->identity) {
883                 /*
884                  * Creating directory for the identity only if the driver is
885                  * able to provide data to it.
886                  */
887                 cable->dev.groups = usb_pd_id_groups;
888                 cable->identity = desc->identity;
889         }
890
891         cable->dev.class = typec_class;
892         cable->dev.parent = &port->dev;
893         cable->dev.type = &typec_cable_dev_type;
894         dev_set_name(&cable->dev, "%s-cable", dev_name(&port->dev));
895
896         ret = device_register(&cable->dev);
897         if (ret) {
898                 dev_err(&port->dev, "failed to register cable (%d)\n", ret);
899                 put_device(&cable->dev);
900                 return ERR_PTR(ret);
901         }
902
903         return cable;
904 }
905 EXPORT_SYMBOL_GPL(typec_register_cable);
906
907 /**
908  * typec_unregister_cable - Unregister a USB Type-C Cable
909  * @cable: The cable to be unregistered
910  *
911  * Unregister device created with typec_register_cable().
912  */
913 void typec_unregister_cable(struct typec_cable *cable)
914 {
915         if (!IS_ERR_OR_NULL(cable))
916                 device_unregister(&cable->dev);
917 }
918 EXPORT_SYMBOL_GPL(typec_unregister_cable);
919
920 /* ------------------------------------------------------------------------- */
921 /* USB Type-C ports */
922
923 static const char * const typec_roles[] = {
924         [TYPEC_SINK]    = "sink",
925         [TYPEC_SOURCE]  = "source",
926 };
927
928 static const char * const typec_data_roles[] = {
929         [TYPEC_DEVICE]  = "device",
930         [TYPEC_HOST]    = "host",
931 };
932
933 static const char * const typec_port_power_roles[] = {
934         [TYPEC_PORT_SRC] = "source",
935         [TYPEC_PORT_SNK] = "sink",
936         [TYPEC_PORT_DRP] = "dual",
937 };
938
939 static const char * const typec_port_data_roles[] = {
940         [TYPEC_PORT_DFP] = "host",
941         [TYPEC_PORT_UFP] = "device",
942         [TYPEC_PORT_DRD] = "dual",
943 };
944
945 static const char * const typec_port_types_drp[] = {
946         [TYPEC_PORT_SRC] = "dual [source] sink",
947         [TYPEC_PORT_SNK] = "dual source [sink]",
948         [TYPEC_PORT_DRP] = "[dual] source sink",
949 };
950
951 static ssize_t
952 preferred_role_store(struct device *dev, struct device_attribute *attr,
953                      const char *buf, size_t size)
954 {
955         struct typec_port *port = to_typec_port(dev);
956         int role;
957         int ret;
958
959         if (port->cap->type != TYPEC_PORT_DRP) {
960                 dev_dbg(dev, "Preferred role only supported with DRP ports\n");
961                 return -EOPNOTSUPP;
962         }
963
964         if (!port->cap->try_role) {
965                 dev_dbg(dev, "Setting preferred role not supported\n");
966                 return -EOPNOTSUPP;
967         }
968
969         role = sysfs_match_string(typec_roles, buf);
970         if (role < 0) {
971                 if (sysfs_streq(buf, "none"))
972                         role = TYPEC_NO_PREFERRED_ROLE;
973                 else
974                         return -EINVAL;
975         }
976
977         ret = port->cap->try_role(port->cap, role);
978         if (ret)
979                 return ret;
980
981         port->prefer_role = role;
982         return size;
983 }
984
985 static ssize_t
986 preferred_role_show(struct device *dev, struct device_attribute *attr,
987                     char *buf)
988 {
989         struct typec_port *port = to_typec_port(dev);
990
991         if (port->cap->type != TYPEC_PORT_DRP)
992                 return 0;
993
994         if (port->prefer_role < 0)
995                 return 0;
996
997         return sprintf(buf, "%s\n", typec_roles[port->prefer_role]);
998 }
999 static DEVICE_ATTR_RW(preferred_role);
1000
1001 static ssize_t data_role_store(struct device *dev,
1002                                struct device_attribute *attr,
1003                                const char *buf, size_t size)
1004 {
1005         struct typec_port *port = to_typec_port(dev);
1006         int ret;
1007
1008         if (!port->cap->dr_set) {
1009                 dev_dbg(dev, "data role swapping not supported\n");
1010                 return -EOPNOTSUPP;
1011         }
1012
1013         ret = sysfs_match_string(typec_data_roles, buf);
1014         if (ret < 0)
1015                 return ret;
1016
1017         mutex_lock(&port->port_type_lock);
1018         if (port->cap->data != TYPEC_PORT_DRD) {
1019                 ret = -EOPNOTSUPP;
1020                 goto unlock_and_ret;
1021         }
1022
1023         ret = port->cap->dr_set(port->cap, ret);
1024         if (ret)
1025                 goto unlock_and_ret;
1026
1027         ret = size;
1028 unlock_and_ret:
1029         mutex_unlock(&port->port_type_lock);
1030         return ret;
1031 }
1032
1033 static ssize_t data_role_show(struct device *dev,
1034                               struct device_attribute *attr, char *buf)
1035 {
1036         struct typec_port *port = to_typec_port(dev);
1037
1038         if (port->cap->data == TYPEC_PORT_DRD)
1039                 return sprintf(buf, "%s\n", port->data_role == TYPEC_HOST ?
1040                                "[host] device" : "host [device]");
1041
1042         return sprintf(buf, "[%s]\n", typec_data_roles[port->data_role]);
1043 }
1044 static DEVICE_ATTR_RW(data_role);
1045
1046 static ssize_t power_role_store(struct device *dev,
1047                                 struct device_attribute *attr,
1048                                 const char *buf, size_t size)
1049 {
1050         struct typec_port *port = to_typec_port(dev);
1051         int ret;
1052
1053         if (!port->cap->pd_revision) {
1054                 dev_dbg(dev, "USB Power Delivery not supported\n");
1055                 return -EOPNOTSUPP;
1056         }
1057
1058         if (!port->cap->pr_set) {
1059                 dev_dbg(dev, "power role swapping not supported\n");
1060                 return -EOPNOTSUPP;
1061         }
1062
1063         if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
1064                 dev_dbg(dev, "partner unable to swap power role\n");
1065                 return -EIO;
1066         }
1067
1068         ret = sysfs_match_string(typec_roles, buf);
1069         if (ret < 0)
1070                 return ret;
1071
1072         mutex_lock(&port->port_type_lock);
1073         if (port->port_type != TYPEC_PORT_DRP) {
1074                 dev_dbg(dev, "port type fixed at \"%s\"",
1075                              typec_port_power_roles[port->port_type]);
1076                 ret = -EOPNOTSUPP;
1077                 goto unlock_and_ret;
1078         }
1079
1080         ret = port->cap->pr_set(port->cap, ret);
1081         if (ret)
1082                 goto unlock_and_ret;
1083
1084         ret = size;
1085 unlock_and_ret:
1086         mutex_unlock(&port->port_type_lock);
1087         return ret;
1088 }
1089
1090 static ssize_t power_role_show(struct device *dev,
1091                                struct device_attribute *attr, char *buf)
1092 {
1093         struct typec_port *port = to_typec_port(dev);
1094
1095         if (port->cap->type == TYPEC_PORT_DRP)
1096                 return sprintf(buf, "%s\n", port->pwr_role == TYPEC_SOURCE ?
1097                                "[source] sink" : "source [sink]");
1098
1099         return sprintf(buf, "[%s]\n", typec_roles[port->pwr_role]);
1100 }
1101 static DEVICE_ATTR_RW(power_role);
1102
1103 static ssize_t
1104 port_type_store(struct device *dev, struct device_attribute *attr,
1105                         const char *buf, size_t size)
1106 {
1107         struct typec_port *port = to_typec_port(dev);
1108         int ret;
1109         enum typec_port_type type;
1110
1111         if (!port->cap->port_type_set || port->cap->type != TYPEC_PORT_DRP) {
1112                 dev_dbg(dev, "changing port type not supported\n");
1113                 return -EOPNOTSUPP;
1114         }
1115
1116         ret = sysfs_match_string(typec_port_power_roles, buf);
1117         if (ret < 0)
1118                 return ret;
1119
1120         type = ret;
1121         mutex_lock(&port->port_type_lock);
1122
1123         if (port->port_type == type) {
1124                 ret = size;
1125                 goto unlock_and_ret;
1126         }
1127
1128         ret = port->cap->port_type_set(port->cap, type);
1129         if (ret)
1130                 goto unlock_and_ret;
1131
1132         port->port_type = type;
1133         ret = size;
1134
1135 unlock_and_ret:
1136         mutex_unlock(&port->port_type_lock);
1137         return ret;
1138 }
1139
1140 static ssize_t
1141 port_type_show(struct device *dev, struct device_attribute *attr,
1142                 char *buf)
1143 {
1144         struct typec_port *port = to_typec_port(dev);
1145
1146         if (port->cap->type == TYPEC_PORT_DRP)
1147                 return sprintf(buf, "%s\n",
1148                                typec_port_types_drp[port->port_type]);
1149
1150         return sprintf(buf, "[%s]\n", typec_port_power_roles[port->cap->type]);
1151 }
1152 static DEVICE_ATTR_RW(port_type);
1153
1154 static const char * const typec_pwr_opmodes[] = {
1155         [TYPEC_PWR_MODE_USB]    = "default",
1156         [TYPEC_PWR_MODE_1_5A]   = "1.5A",
1157         [TYPEC_PWR_MODE_3_0A]   = "3.0A",
1158         [TYPEC_PWR_MODE_PD]     = "usb_power_delivery",
1159 };
1160
1161 static ssize_t power_operation_mode_show(struct device *dev,
1162                                          struct device_attribute *attr,
1163                                          char *buf)
1164 {
1165         struct typec_port *port = to_typec_port(dev);
1166
1167         return sprintf(buf, "%s\n", typec_pwr_opmodes[port->pwr_opmode]);
1168 }
1169 static DEVICE_ATTR_RO(power_operation_mode);
1170
1171 static ssize_t vconn_source_store(struct device *dev,
1172                                   struct device_attribute *attr,
1173                                   const char *buf, size_t size)
1174 {
1175         struct typec_port *port = to_typec_port(dev);
1176         bool source;
1177         int ret;
1178
1179         if (!port->cap->pd_revision) {
1180                 dev_dbg(dev, "VCONN swap depends on USB Power Delivery\n");
1181                 return -EOPNOTSUPP;
1182         }
1183
1184         if (!port->cap->vconn_set) {
1185                 dev_dbg(dev, "VCONN swapping not supported\n");
1186                 return -EOPNOTSUPP;
1187         }
1188
1189         ret = kstrtobool(buf, &source);
1190         if (ret)
1191                 return ret;
1192
1193         ret = port->cap->vconn_set(port->cap, (enum typec_role)source);
1194         if (ret)
1195                 return ret;
1196
1197         return size;
1198 }
1199
1200 static ssize_t vconn_source_show(struct device *dev,
1201                                  struct device_attribute *attr, char *buf)
1202 {
1203         struct typec_port *port = to_typec_port(dev);
1204
1205         return sprintf(buf, "%s\n",
1206                        port->vconn_role == TYPEC_SOURCE ? "yes" : "no");
1207 }
1208 static DEVICE_ATTR_RW(vconn_source);
1209
1210 static ssize_t supported_accessory_modes_show(struct device *dev,
1211                                               struct device_attribute *attr,
1212                                               char *buf)
1213 {
1214         struct typec_port *port = to_typec_port(dev);
1215         ssize_t ret = 0;
1216         int i;
1217
1218         for (i = 0; i < ARRAY_SIZE(port->cap->accessory); i++) {
1219                 if (port->cap->accessory[i])
1220                         ret += sprintf(buf + ret, "%s ",
1221                                typec_accessory_modes[port->cap->accessory[i]]);
1222         }
1223
1224         if (!ret)
1225                 return sprintf(buf, "none\n");
1226
1227         buf[ret - 1] = '\n';
1228
1229         return ret;
1230 }
1231 static DEVICE_ATTR_RO(supported_accessory_modes);
1232
1233 static ssize_t usb_typec_revision_show(struct device *dev,
1234                                        struct device_attribute *attr,
1235                                        char *buf)
1236 {
1237         struct typec_port *port = to_typec_port(dev);
1238         u16 rev = port->cap->revision;
1239
1240         return sprintf(buf, "%d.%d\n", (rev >> 8) & 0xff, (rev >> 4) & 0xf);
1241 }
1242 static DEVICE_ATTR_RO(usb_typec_revision);
1243
1244 static ssize_t usb_power_delivery_revision_show(struct device *dev,
1245                                                 struct device_attribute *attr,
1246                                                 char *buf)
1247 {
1248         struct typec_port *p = to_typec_port(dev);
1249
1250         return sprintf(buf, "%d\n", (p->cap->pd_revision >> 8) & 0xff);
1251 }
1252 static DEVICE_ATTR_RO(usb_power_delivery_revision);
1253
1254 static struct attribute *typec_attrs[] = {
1255         &dev_attr_data_role.attr,
1256         &dev_attr_power_operation_mode.attr,
1257         &dev_attr_power_role.attr,
1258         &dev_attr_preferred_role.attr,
1259         &dev_attr_supported_accessory_modes.attr,
1260         &dev_attr_usb_power_delivery_revision.attr,
1261         &dev_attr_usb_typec_revision.attr,
1262         &dev_attr_vconn_source.attr,
1263         &dev_attr_port_type.attr,
1264         NULL,
1265 };
1266 ATTRIBUTE_GROUPS(typec);
1267
1268 static int typec_uevent(struct device *dev, struct kobj_uevent_env *env)
1269 {
1270         int ret;
1271
1272         ret = add_uevent_var(env, "TYPEC_PORT=%s", dev_name(dev));
1273         if (ret)
1274                 dev_err(dev, "failed to add uevent TYPEC_PORT\n");
1275
1276         return ret;
1277 }
1278
1279 static void typec_release(struct device *dev)
1280 {
1281         struct typec_port *port = to_typec_port(dev);
1282
1283         ida_simple_remove(&typec_index_ida, port->id);
1284         ida_destroy(&port->mode_ids);
1285         typec_switch_put(port->sw);
1286         typec_mux_put(port->mux);
1287         kfree(port);
1288 }
1289
1290 const struct device_type typec_port_dev_type = {
1291         .name = "typec_port",
1292         .groups = typec_groups,
1293         .uevent = typec_uevent,
1294         .release = typec_release,
1295 };
1296
1297 /* --------------------------------------- */
1298 /* Driver callbacks to report role updates */
1299
1300 /**
1301  * typec_set_data_role - Report data role change
1302  * @port: The USB Type-C Port where the role was changed
1303  * @role: The new data role
1304  *
1305  * This routine is used by the port drivers to report data role changes.
1306  */
1307 void typec_set_data_role(struct typec_port *port, enum typec_data_role role)
1308 {
1309         if (port->data_role == role)
1310                 return;
1311
1312         port->data_role = role;
1313         sysfs_notify(&port->dev.kobj, NULL, "data_role");
1314         kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
1315 }
1316 EXPORT_SYMBOL_GPL(typec_set_data_role);
1317
1318 /**
1319  * typec_set_pwr_role - Report power role change
1320  * @port: The USB Type-C Port where the role was changed
1321  * @role: The new data role
1322  *
1323  * This routine is used by the port drivers to report power role changes.
1324  */
1325 void typec_set_pwr_role(struct typec_port *port, enum typec_role role)
1326 {
1327         if (port->pwr_role == role)
1328                 return;
1329
1330         port->pwr_role = role;
1331         sysfs_notify(&port->dev.kobj, NULL, "power_role");
1332         kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
1333 }
1334 EXPORT_SYMBOL_GPL(typec_set_pwr_role);
1335
1336 /**
1337  * typec_set_vconn_role - Report VCONN source change
1338  * @port: The USB Type-C Port which VCONN role changed
1339  * @role: Source when @port is sourcing VCONN, or Sink when it's not
1340  *
1341  * This routine is used by the port drivers to report if the VCONN source is
1342  * changes.
1343  */
1344 void typec_set_vconn_role(struct typec_port *port, enum typec_role role)
1345 {
1346         if (port->vconn_role == role)
1347                 return;
1348
1349         port->vconn_role = role;
1350         sysfs_notify(&port->dev.kobj, NULL, "vconn_source");
1351         kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
1352 }
1353 EXPORT_SYMBOL_GPL(typec_set_vconn_role);
1354
1355 static int partner_match(struct device *dev, void *data)
1356 {
1357         return is_typec_partner(dev);
1358 }
1359
1360 /**
1361  * typec_set_pwr_opmode - Report changed power operation mode
1362  * @port: The USB Type-C Port where the mode was changed
1363  * @opmode: New power operation mode
1364  *
1365  * This routine is used by the port drivers to report changed power operation
1366  * mode in @port. The modes are USB (default), 1.5A, 3.0A as defined in USB
1367  * Type-C specification, and "USB Power Delivery" when the power levels are
1368  * negotiated with methods defined in USB Power Delivery specification.
1369  */
1370 void typec_set_pwr_opmode(struct typec_port *port,
1371                           enum typec_pwr_opmode opmode)
1372 {
1373         struct device *partner_dev;
1374
1375         if (port->pwr_opmode == opmode)
1376                 return;
1377
1378         port->pwr_opmode = opmode;
1379         sysfs_notify(&port->dev.kobj, NULL, "power_operation_mode");
1380         kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
1381
1382         partner_dev = device_find_child(&port->dev, NULL, partner_match);
1383         if (partner_dev) {
1384                 struct typec_partner *partner = to_typec_partner(partner_dev);
1385
1386                 if (opmode == TYPEC_PWR_MODE_PD && !partner->usb_pd) {
1387                         partner->usb_pd = 1;
1388                         sysfs_notify(&partner_dev->kobj, NULL,
1389                                      "supports_usb_power_delivery");
1390                 }
1391                 put_device(partner_dev);
1392         }
1393 }
1394 EXPORT_SYMBOL_GPL(typec_set_pwr_opmode);
1395
1396 /**
1397  * typec_find_port_power_role - Get the typec port power capability
1398  * @name: port power capability string
1399  *
1400  * This routine is used to find the typec_port_type by its string name.
1401  *
1402  * Returns typec_port_type if success, otherwise negative error code.
1403  */
1404 int typec_find_port_power_role(const char *name)
1405 {
1406         return match_string(typec_port_power_roles,
1407                             ARRAY_SIZE(typec_port_power_roles), name);
1408 }
1409 EXPORT_SYMBOL_GPL(typec_find_port_power_role);
1410
1411 /**
1412  * typec_find_power_role - Find the typec one specific power role
1413  * @name: power role string
1414  *
1415  * This routine is used to find the typec_role by its string name.
1416  *
1417  * Returns typec_role if success, otherwise negative error code.
1418  */
1419 int typec_find_power_role(const char *name)
1420 {
1421         return match_string(typec_roles, ARRAY_SIZE(typec_roles), name);
1422 }
1423 EXPORT_SYMBOL_GPL(typec_find_power_role);
1424
1425 /**
1426  * typec_find_port_data_role - Get the typec port data capability
1427  * @name: port data capability string
1428  *
1429  * This routine is used to find the typec_port_data by its string name.
1430  *
1431  * Returns typec_port_data if success, otherwise negative error code.
1432  */
1433 int typec_find_port_data_role(const char *name)
1434 {
1435         return match_string(typec_port_data_roles,
1436                             ARRAY_SIZE(typec_port_data_roles), name);
1437 }
1438 EXPORT_SYMBOL_GPL(typec_find_port_data_role);
1439
1440 /* ------------------------------------------ */
1441 /* API for Multiplexer/DeMultiplexer Switches */
1442
1443 /**
1444  * typec_set_orientation - Set USB Type-C cable plug orientation
1445  * @port: USB Type-C Port
1446  * @orientation: USB Type-C cable plug orientation
1447  *
1448  * Set cable plug orientation for @port.
1449  */
1450 int typec_set_orientation(struct typec_port *port,
1451                           enum typec_orientation orientation)
1452 {
1453         int ret;
1454
1455         if (port->sw) {
1456                 ret = port->sw->set(port->sw, orientation);
1457                 if (ret)
1458                         return ret;
1459         }
1460
1461         port->orientation = orientation;
1462
1463         return 0;
1464 }
1465 EXPORT_SYMBOL_GPL(typec_set_orientation);
1466
1467 /**
1468  * typec_get_orientation - Get USB Type-C cable plug orientation
1469  * @port: USB Type-C Port
1470  *
1471  * Get current cable plug orientation for @port.
1472  */
1473 enum typec_orientation typec_get_orientation(struct typec_port *port)
1474 {
1475         return port->orientation;
1476 }
1477 EXPORT_SYMBOL_GPL(typec_get_orientation);
1478
1479 /**
1480  * typec_set_mode - Set mode of operation for USB Type-C connector
1481  * @port: USB Type-C connector
1482  * @mode: Accessory Mode, USB Operation or Safe State
1483  *
1484  * Configure @port for Accessory Mode @mode. This function will configure the
1485  * muxes needed for @mode.
1486  */
1487 int typec_set_mode(struct typec_port *port, int mode)
1488 {
1489         return port->mux ? port->mux->set(port->mux, mode) : 0;
1490 }
1491 EXPORT_SYMBOL_GPL(typec_set_mode);
1492
1493 /* --------------------------------------- */
1494
1495 /**
1496  * typec_port_register_altmode - Register USB Type-C Port Alternate Mode
1497  * @port: USB Type-C Port that supports the alternate mode
1498  * @desc: Description of the alternate mode
1499  *
1500  * This routine is used to register an alternate mode that @port is capable of
1501  * supporting.
1502  *
1503  * Returns handle to the alternate mode on success or ERR_PTR on failure.
1504  */
1505 struct typec_altmode *
1506 typec_port_register_altmode(struct typec_port *port,
1507                             const struct typec_altmode_desc *desc)
1508 {
1509         struct typec_altmode *adev;
1510         struct typec_mux *mux;
1511
1512         mux = typec_mux_get(&port->dev, desc);
1513         if (IS_ERR(mux))
1514                 return ERR_CAST(mux);
1515
1516         adev = typec_register_altmode(&port->dev, desc);
1517         if (IS_ERR(adev))
1518                 typec_mux_put(mux);
1519         else
1520                 to_altmode(adev)->mux = mux;
1521
1522         return adev;
1523 }
1524 EXPORT_SYMBOL_GPL(typec_port_register_altmode);
1525
1526 /**
1527  * typec_register_port - Register a USB Type-C Port
1528  * @parent: Parent device
1529  * @cap: Description of the port
1530  *
1531  * Registers a device for USB Type-C Port described in @cap.
1532  *
1533  * Returns handle to the port on success or ERR_PTR on failure.
1534  */
1535 struct typec_port *typec_register_port(struct device *parent,
1536                                        const struct typec_capability *cap)
1537 {
1538         struct typec_port *port;
1539         int ret;
1540         int id;
1541
1542         port = kzalloc(sizeof(*port), GFP_KERNEL);
1543         if (!port)
1544                 return ERR_PTR(-ENOMEM);
1545
1546         id = ida_simple_get(&typec_index_ida, 0, 0, GFP_KERNEL);
1547         if (id < 0) {
1548                 kfree(port);
1549                 return ERR_PTR(id);
1550         }
1551
1552         switch (cap->type) {
1553         case TYPEC_PORT_SRC:
1554                 port->pwr_role = TYPEC_SOURCE;
1555                 port->vconn_role = TYPEC_SOURCE;
1556                 break;
1557         case TYPEC_PORT_SNK:
1558                 port->pwr_role = TYPEC_SINK;
1559                 port->vconn_role = TYPEC_SINK;
1560                 break;
1561         case TYPEC_PORT_DRP:
1562                 if (cap->prefer_role != TYPEC_NO_PREFERRED_ROLE)
1563                         port->pwr_role = cap->prefer_role;
1564                 else
1565                         port->pwr_role = TYPEC_SINK;
1566                 break;
1567         }
1568
1569         switch (cap->data) {
1570         case TYPEC_PORT_DFP:
1571                 port->data_role = TYPEC_HOST;
1572                 break;
1573         case TYPEC_PORT_UFP:
1574                 port->data_role = TYPEC_DEVICE;
1575                 break;
1576         case TYPEC_PORT_DRD:
1577                 if (cap->prefer_role == TYPEC_SOURCE)
1578                         port->data_role = TYPEC_HOST;
1579                 else
1580                         port->data_role = TYPEC_DEVICE;
1581                 break;
1582         }
1583
1584         ida_init(&port->mode_ids);
1585         mutex_init(&port->port_type_lock);
1586
1587         port->id = id;
1588         port->cap = cap;
1589         port->port_type = cap->type;
1590         port->prefer_role = cap->prefer_role;
1591
1592         device_initialize(&port->dev);
1593         port->dev.class = typec_class;
1594         port->dev.parent = parent;
1595         port->dev.fwnode = cap->fwnode;
1596         port->dev.type = &typec_port_dev_type;
1597         dev_set_name(&port->dev, "port%d", id);
1598
1599         port->sw = typec_switch_get(&port->dev);
1600         if (IS_ERR(port->sw)) {
1601                 put_device(&port->dev);
1602                 return ERR_CAST(port->sw);
1603         }
1604
1605         port->mux = typec_mux_get(&port->dev, NULL);
1606         if (IS_ERR(port->mux)) {
1607                 put_device(&port->dev);
1608                 return ERR_CAST(port->mux);
1609         }
1610
1611         ret = device_add(&port->dev);
1612         if (ret) {
1613                 dev_err(parent, "failed to register port (%d)\n", ret);
1614                 put_device(&port->dev);
1615                 return ERR_PTR(ret);
1616         }
1617
1618         return port;
1619 }
1620 EXPORT_SYMBOL_GPL(typec_register_port);
1621
1622 /**
1623  * typec_unregister_port - Unregister a USB Type-C Port
1624  * @port: The port to be unregistered
1625  *
1626  * Unregister device created with typec_register_port().
1627  */
1628 void typec_unregister_port(struct typec_port *port)
1629 {
1630         if (!IS_ERR_OR_NULL(port))
1631                 device_unregister(&port->dev);
1632 }
1633 EXPORT_SYMBOL_GPL(typec_unregister_port);
1634
1635 static int __init typec_init(void)
1636 {
1637         int ret;
1638
1639         ret = bus_register(&typec_bus);
1640         if (ret)
1641                 return ret;
1642
1643         ret = class_register(&typec_mux_class);
1644         if (ret)
1645                 goto err_unregister_bus;
1646
1647         typec_class = class_create(THIS_MODULE, "typec");
1648         if (IS_ERR(typec_class)) {
1649                 ret = PTR_ERR(typec_class);
1650                 goto err_unregister_mux_class;
1651         }
1652
1653         return 0;
1654
1655 err_unregister_mux_class:
1656         class_unregister(&typec_mux_class);
1657
1658 err_unregister_bus:
1659         bus_unregister(&typec_bus);
1660
1661         return ret;
1662 }
1663 subsys_initcall(typec_init);
1664
1665 static void __exit typec_exit(void)
1666 {
1667         class_destroy(typec_class);
1668         ida_destroy(&typec_index_ida);
1669         bus_unregister(&typec_bus);
1670         class_unregister(&typec_mux_class);
1671 }
1672 module_exit(typec_exit);
1673
1674 MODULE_AUTHOR("Heikki Krogerus <[email protected]>");
1675 MODULE_LICENSE("GPL v2");
1676 MODULE_DESCRIPTION("USB Type-C Connector Class");
This page took 0.128545 seconds and 4 git commands to generate.