at v4.16-rc1 1365 lines 35 kB view raw
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 <heikki.krogerus@linux.intel.com> 7 */ 8 9#include <linux/device.h> 10#include <linux/module.h> 11#include <linux/mutex.h> 12#include <linux/slab.h> 13#include <linux/usb/typec.h> 14 15struct typec_mode { 16 int index; 17 u32 vdo; 18 char *desc; 19 enum typec_port_type roles; 20 21 struct typec_altmode *alt_mode; 22 23 unsigned int active:1; 24 25 char group_name[6]; 26 struct attribute_group group; 27 struct attribute *attrs[5]; 28 struct device_attribute vdo_attr; 29 struct device_attribute desc_attr; 30 struct device_attribute active_attr; 31 struct device_attribute roles_attr; 32}; 33 34struct typec_altmode { 35 struct device dev; 36 u16 svid; 37 int n_modes; 38 struct typec_mode modes[ALTMODE_MAX_MODES]; 39 const struct attribute_group *mode_groups[ALTMODE_MAX_MODES]; 40}; 41 42struct typec_plug { 43 struct device dev; 44 enum typec_plug_index index; 45}; 46 47struct typec_cable { 48 struct device dev; 49 enum typec_plug_type type; 50 struct usb_pd_identity *identity; 51 unsigned int active:1; 52}; 53 54struct typec_partner { 55 struct device dev; 56 unsigned int usb_pd:1; 57 struct usb_pd_identity *identity; 58 enum typec_accessory accessory; 59}; 60 61struct typec_port { 62 unsigned int id; 63 struct device dev; 64 65 int prefer_role; 66 enum typec_data_role data_role; 67 enum typec_role pwr_role; 68 enum typec_role vconn_role; 69 enum typec_pwr_opmode pwr_opmode; 70 enum typec_port_type port_type; 71 struct mutex port_type_lock; 72 73 const struct typec_capability *cap; 74}; 75 76#define to_typec_port(_dev_) container_of(_dev_, struct typec_port, dev) 77#define to_typec_plug(_dev_) container_of(_dev_, struct typec_plug, dev) 78#define to_typec_cable(_dev_) container_of(_dev_, struct typec_cable, dev) 79#define to_typec_partner(_dev_) container_of(_dev_, struct typec_partner, dev) 80#define to_altmode(_dev_) container_of(_dev_, struct typec_altmode, dev) 81 82static const struct device_type typec_partner_dev_type; 83static const struct device_type typec_cable_dev_type; 84static const struct device_type typec_plug_dev_type; 85static const struct device_type typec_port_dev_type; 86 87#define is_typec_partner(_dev_) (_dev_->type == &typec_partner_dev_type) 88#define is_typec_cable(_dev_) (_dev_->type == &typec_cable_dev_type) 89#define is_typec_plug(_dev_) (_dev_->type == &typec_plug_dev_type) 90#define is_typec_port(_dev_) (_dev_->type == &typec_port_dev_type) 91 92static DEFINE_IDA(typec_index_ida); 93static struct class *typec_class; 94 95/* Common attributes */ 96 97static const char * const typec_accessory_modes[] = { 98 [TYPEC_ACCESSORY_NONE] = "none", 99 [TYPEC_ACCESSORY_AUDIO] = "analog_audio", 100 [TYPEC_ACCESSORY_DEBUG] = "debug", 101}; 102 103static struct usb_pd_identity *get_pd_identity(struct device *dev) 104{ 105 if (is_typec_partner(dev)) { 106 struct typec_partner *partner = to_typec_partner(dev); 107 108 return partner->identity; 109 } else if (is_typec_cable(dev)) { 110 struct typec_cable *cable = to_typec_cable(dev); 111 112 return cable->identity; 113 } 114 return NULL; 115} 116 117static ssize_t id_header_show(struct device *dev, struct device_attribute *attr, 118 char *buf) 119{ 120 struct usb_pd_identity *id = get_pd_identity(dev); 121 122 return sprintf(buf, "0x%08x\n", id->id_header); 123} 124static DEVICE_ATTR_RO(id_header); 125 126static ssize_t cert_stat_show(struct device *dev, struct device_attribute *attr, 127 char *buf) 128{ 129 struct usb_pd_identity *id = get_pd_identity(dev); 130 131 return sprintf(buf, "0x%08x\n", id->cert_stat); 132} 133static DEVICE_ATTR_RO(cert_stat); 134 135static ssize_t product_show(struct device *dev, struct device_attribute *attr, 136 char *buf) 137{ 138 struct usb_pd_identity *id = get_pd_identity(dev); 139 140 return sprintf(buf, "0x%08x\n", id->product); 141} 142static DEVICE_ATTR_RO(product); 143 144static struct attribute *usb_pd_id_attrs[] = { 145 &dev_attr_id_header.attr, 146 &dev_attr_cert_stat.attr, 147 &dev_attr_product.attr, 148 NULL 149}; 150 151static const struct attribute_group usb_pd_id_group = { 152 .name = "identity", 153 .attrs = usb_pd_id_attrs, 154}; 155 156static const struct attribute_group *usb_pd_id_groups[] = { 157 &usb_pd_id_group, 158 NULL, 159}; 160 161static void typec_report_identity(struct device *dev) 162{ 163 sysfs_notify(&dev->kobj, "identity", "id_header"); 164 sysfs_notify(&dev->kobj, "identity", "cert_stat"); 165 sysfs_notify(&dev->kobj, "identity", "product"); 166} 167 168/* ------------------------------------------------------------------------- */ 169/* Alternate Modes */ 170 171/** 172 * typec_altmode_update_active - Report Enter/Exit mode 173 * @alt: Handle to the alternate mode 174 * @mode: Mode index 175 * @active: True when the mode has been entered 176 * 177 * If a partner or cable plug executes Enter/Exit Mode command successfully, the 178 * drivers use this routine to report the updated state of the mode. 179 */ 180void typec_altmode_update_active(struct typec_altmode *alt, int mode, 181 bool active) 182{ 183 struct typec_mode *m = &alt->modes[mode]; 184 char dir[6]; 185 186 if (m->active == active) 187 return; 188 189 m->active = active; 190 snprintf(dir, sizeof(dir), "mode%d", mode); 191 sysfs_notify(&alt->dev.kobj, dir, "active"); 192 kobject_uevent(&alt->dev.kobj, KOBJ_CHANGE); 193} 194EXPORT_SYMBOL_GPL(typec_altmode_update_active); 195 196/** 197 * typec_altmode2port - Alternate Mode to USB Type-C port 198 * @alt: The Alternate Mode 199 * 200 * Returns handle to the port that a cable plug or partner with @alt is 201 * connected to. 202 */ 203struct typec_port *typec_altmode2port(struct typec_altmode *alt) 204{ 205 if (is_typec_plug(alt->dev.parent)) 206 return to_typec_port(alt->dev.parent->parent->parent); 207 if (is_typec_partner(alt->dev.parent)) 208 return to_typec_port(alt->dev.parent->parent); 209 if (is_typec_port(alt->dev.parent)) 210 return to_typec_port(alt->dev.parent); 211 212 return NULL; 213} 214EXPORT_SYMBOL_GPL(typec_altmode2port); 215 216static ssize_t 217typec_altmode_vdo_show(struct device *dev, struct device_attribute *attr, 218 char *buf) 219{ 220 struct typec_mode *mode = container_of(attr, struct typec_mode, 221 vdo_attr); 222 223 return sprintf(buf, "0x%08x\n", mode->vdo); 224} 225 226static ssize_t 227typec_altmode_desc_show(struct device *dev, struct device_attribute *attr, 228 char *buf) 229{ 230 struct typec_mode *mode = container_of(attr, struct typec_mode, 231 desc_attr); 232 233 return sprintf(buf, "%s\n", mode->desc ? mode->desc : ""); 234} 235 236static ssize_t 237typec_altmode_active_show(struct device *dev, struct device_attribute *attr, 238 char *buf) 239{ 240 struct typec_mode *mode = container_of(attr, struct typec_mode, 241 active_attr); 242 243 return sprintf(buf, "%s\n", mode->active ? "yes" : "no"); 244} 245 246static ssize_t 247typec_altmode_active_store(struct device *dev, struct device_attribute *attr, 248 const char *buf, size_t size) 249{ 250 struct typec_mode *mode = container_of(attr, struct typec_mode, 251 active_attr); 252 struct typec_port *port = typec_altmode2port(mode->alt_mode); 253 bool activate; 254 int ret; 255 256 if (!port->cap->activate_mode) 257 return -EOPNOTSUPP; 258 259 ret = kstrtobool(buf, &activate); 260 if (ret) 261 return ret; 262 263 ret = port->cap->activate_mode(port->cap, mode->index, activate); 264 if (ret) 265 return ret; 266 267 return size; 268} 269 270static ssize_t 271typec_altmode_roles_show(struct device *dev, struct device_attribute *attr, 272 char *buf) 273{ 274 struct typec_mode *mode = container_of(attr, struct typec_mode, 275 roles_attr); 276 ssize_t ret; 277 278 switch (mode->roles) { 279 case TYPEC_PORT_DFP: 280 ret = sprintf(buf, "source\n"); 281 break; 282 case TYPEC_PORT_UFP: 283 ret = sprintf(buf, "sink\n"); 284 break; 285 case TYPEC_PORT_DRP: 286 default: 287 ret = sprintf(buf, "source sink\n"); 288 break; 289 } 290 return ret; 291} 292 293static void typec_init_modes(struct typec_altmode *alt, 294 const struct typec_mode_desc *desc, bool is_port) 295{ 296 int i; 297 298 for (i = 0; i < alt->n_modes; i++, desc++) { 299 struct typec_mode *mode = &alt->modes[i]; 300 301 /* Not considering the human readable description critical */ 302 mode->desc = kstrdup(desc->desc, GFP_KERNEL); 303 if (desc->desc && !mode->desc) 304 dev_err(&alt->dev, "failed to copy mode%d desc\n", i); 305 306 mode->alt_mode = alt; 307 mode->vdo = desc->vdo; 308 mode->roles = desc->roles; 309 mode->index = desc->index; 310 sprintf(mode->group_name, "mode%d", desc->index); 311 312 sysfs_attr_init(&mode->vdo_attr.attr); 313 mode->vdo_attr.attr.name = "vdo"; 314 mode->vdo_attr.attr.mode = 0444; 315 mode->vdo_attr.show = typec_altmode_vdo_show; 316 317 sysfs_attr_init(&mode->desc_attr.attr); 318 mode->desc_attr.attr.name = "description"; 319 mode->desc_attr.attr.mode = 0444; 320 mode->desc_attr.show = typec_altmode_desc_show; 321 322 sysfs_attr_init(&mode->active_attr.attr); 323 mode->active_attr.attr.name = "active"; 324 mode->active_attr.attr.mode = 0644; 325 mode->active_attr.show = typec_altmode_active_show; 326 mode->active_attr.store = typec_altmode_active_store; 327 328 mode->attrs[0] = &mode->vdo_attr.attr; 329 mode->attrs[1] = &mode->desc_attr.attr; 330 mode->attrs[2] = &mode->active_attr.attr; 331 332 /* With ports, list the roles that the mode is supported with */ 333 if (is_port) { 334 sysfs_attr_init(&mode->roles_attr.attr); 335 mode->roles_attr.attr.name = "supported_roles"; 336 mode->roles_attr.attr.mode = 0444; 337 mode->roles_attr.show = typec_altmode_roles_show; 338 339 mode->attrs[3] = &mode->roles_attr.attr; 340 } 341 342 mode->group.attrs = mode->attrs; 343 mode->group.name = mode->group_name; 344 345 alt->mode_groups[i] = &mode->group; 346 } 347} 348 349static ssize_t svid_show(struct device *dev, struct device_attribute *attr, 350 char *buf) 351{ 352 struct typec_altmode *alt = to_altmode(dev); 353 354 return sprintf(buf, "%04x\n", alt->svid); 355} 356static DEVICE_ATTR_RO(svid); 357 358static struct attribute *typec_altmode_attrs[] = { 359 &dev_attr_svid.attr, 360 NULL 361}; 362ATTRIBUTE_GROUPS(typec_altmode); 363 364static void typec_altmode_release(struct device *dev) 365{ 366 struct typec_altmode *alt = to_altmode(dev); 367 int i; 368 369 for (i = 0; i < alt->n_modes; i++) 370 kfree(alt->modes[i].desc); 371 kfree(alt); 372} 373 374static const struct device_type typec_altmode_dev_type = { 375 .name = "typec_alternate_mode", 376 .groups = typec_altmode_groups, 377 .release = typec_altmode_release, 378}; 379 380static struct typec_altmode * 381typec_register_altmode(struct device *parent, 382 const struct typec_altmode_desc *desc) 383{ 384 struct typec_altmode *alt; 385 int ret; 386 387 alt = kzalloc(sizeof(*alt), GFP_KERNEL); 388 if (!alt) 389 return NULL; 390 391 alt->svid = desc->svid; 392 alt->n_modes = desc->n_modes; 393 typec_init_modes(alt, desc->modes, is_typec_port(parent)); 394 395 alt->dev.parent = parent; 396 alt->dev.groups = alt->mode_groups; 397 alt->dev.type = &typec_altmode_dev_type; 398 dev_set_name(&alt->dev, "svid-%04x", alt->svid); 399 400 ret = device_register(&alt->dev); 401 if (ret) { 402 dev_err(parent, "failed to register alternate mode (%d)\n", 403 ret); 404 put_device(&alt->dev); 405 return NULL; 406 } 407 408 return alt; 409} 410 411/** 412 * typec_unregister_altmode - Unregister Alternate Mode 413 * @alt: The alternate mode to be unregistered 414 * 415 * Unregister device created with typec_partner_register_altmode(), 416 * typec_plug_register_altmode() or typec_port_register_altmode(). 417 */ 418void typec_unregister_altmode(struct typec_altmode *alt) 419{ 420 if (alt) 421 device_unregister(&alt->dev); 422} 423EXPORT_SYMBOL_GPL(typec_unregister_altmode); 424 425/* ------------------------------------------------------------------------- */ 426/* Type-C Partners */ 427 428static ssize_t accessory_mode_show(struct device *dev, 429 struct device_attribute *attr, 430 char *buf) 431{ 432 struct typec_partner *p = to_typec_partner(dev); 433 434 return sprintf(buf, "%s\n", typec_accessory_modes[p->accessory]); 435} 436static DEVICE_ATTR_RO(accessory_mode); 437 438static ssize_t supports_usb_power_delivery_show(struct device *dev, 439 struct device_attribute *attr, 440 char *buf) 441{ 442 struct typec_partner *p = to_typec_partner(dev); 443 444 return sprintf(buf, "%s\n", p->usb_pd ? "yes" : "no"); 445} 446static DEVICE_ATTR_RO(supports_usb_power_delivery); 447 448static struct attribute *typec_partner_attrs[] = { 449 &dev_attr_accessory_mode.attr, 450 &dev_attr_supports_usb_power_delivery.attr, 451 NULL 452}; 453ATTRIBUTE_GROUPS(typec_partner); 454 455static void typec_partner_release(struct device *dev) 456{ 457 struct typec_partner *partner = to_typec_partner(dev); 458 459 kfree(partner); 460} 461 462static const struct device_type typec_partner_dev_type = { 463 .name = "typec_partner", 464 .groups = typec_partner_groups, 465 .release = typec_partner_release, 466}; 467 468/** 469 * typec_partner_set_identity - Report result from Discover Identity command 470 * @partner: The partner updated identity values 471 * 472 * This routine is used to report that the result of Discover Identity USB power 473 * delivery command has become available. 474 */ 475int typec_partner_set_identity(struct typec_partner *partner) 476{ 477 if (!partner->identity) 478 return -EINVAL; 479 480 typec_report_identity(&partner->dev); 481 return 0; 482} 483EXPORT_SYMBOL_GPL(typec_partner_set_identity); 484 485/** 486 * typec_partner_register_altmode - Register USB Type-C Partner Alternate Mode 487 * @partner: USB Type-C Partner that supports the alternate mode 488 * @desc: Description of the alternate mode 489 * 490 * This routine is used to register each alternate mode individually that 491 * @partner has listed in response to Discover SVIDs command. The modes for a 492 * SVID listed in response to Discover Modes command need to be listed in an 493 * array in @desc. 494 * 495 * Returns handle to the alternate mode on success or NULL on failure. 496 */ 497struct typec_altmode * 498typec_partner_register_altmode(struct typec_partner *partner, 499 const struct typec_altmode_desc *desc) 500{ 501 return typec_register_altmode(&partner->dev, desc); 502} 503EXPORT_SYMBOL_GPL(typec_partner_register_altmode); 504 505/** 506 * typec_register_partner - Register a USB Type-C Partner 507 * @port: The USB Type-C Port the partner is connected to 508 * @desc: Description of the partner 509 * 510 * Registers a device for USB Type-C Partner described in @desc. 511 * 512 * Returns handle to the partner on success or NULL on failure. 513 */ 514struct typec_partner *typec_register_partner(struct typec_port *port, 515 struct typec_partner_desc *desc) 516{ 517 struct typec_partner *partner; 518 int ret; 519 520 partner = kzalloc(sizeof(*partner), GFP_KERNEL); 521 if (!partner) 522 return NULL; 523 524 partner->usb_pd = desc->usb_pd; 525 partner->accessory = desc->accessory; 526 527 if (desc->identity) { 528 /* 529 * Creating directory for the identity only if the driver is 530 * able to provide data to it. 531 */ 532 partner->dev.groups = usb_pd_id_groups; 533 partner->identity = desc->identity; 534 } 535 536 partner->dev.class = typec_class; 537 partner->dev.parent = &port->dev; 538 partner->dev.type = &typec_partner_dev_type; 539 dev_set_name(&partner->dev, "%s-partner", dev_name(&port->dev)); 540 541 ret = device_register(&partner->dev); 542 if (ret) { 543 dev_err(&port->dev, "failed to register partner (%d)\n", ret); 544 put_device(&partner->dev); 545 return NULL; 546 } 547 548 return partner; 549} 550EXPORT_SYMBOL_GPL(typec_register_partner); 551 552/** 553 * typec_unregister_partner - Unregister a USB Type-C Partner 554 * @partner: The partner to be unregistered 555 * 556 * Unregister device created with typec_register_partner(). 557 */ 558void typec_unregister_partner(struct typec_partner *partner) 559{ 560 if (partner) 561 device_unregister(&partner->dev); 562} 563EXPORT_SYMBOL_GPL(typec_unregister_partner); 564 565/* ------------------------------------------------------------------------- */ 566/* Type-C Cable Plugs */ 567 568static void typec_plug_release(struct device *dev) 569{ 570 struct typec_plug *plug = to_typec_plug(dev); 571 572 kfree(plug); 573} 574 575static const struct device_type typec_plug_dev_type = { 576 .name = "typec_plug", 577 .release = typec_plug_release, 578}; 579 580/** 581 * typec_plug_register_altmode - Register USB Type-C Cable Plug Alternate Mode 582 * @plug: USB Type-C Cable Plug that supports the alternate mode 583 * @desc: Description of the alternate mode 584 * 585 * This routine is used to register each alternate mode individually that @plug 586 * has listed in response to Discover SVIDs command. The modes for a SVID that 587 * the plug lists in response to Discover Modes command need to be listed in an 588 * array in @desc. 589 * 590 * Returns handle to the alternate mode on success or NULL on failure. 591 */ 592struct typec_altmode * 593typec_plug_register_altmode(struct typec_plug *plug, 594 const struct typec_altmode_desc *desc) 595{ 596 return typec_register_altmode(&plug->dev, desc); 597} 598EXPORT_SYMBOL_GPL(typec_plug_register_altmode); 599 600/** 601 * typec_register_plug - Register a USB Type-C Cable Plug 602 * @cable: USB Type-C Cable with the plug 603 * @desc: Description of the cable plug 604 * 605 * Registers a device for USB Type-C Cable Plug described in @desc. A USB Type-C 606 * Cable Plug represents a plug with electronics in it that can response to USB 607 * Power Delivery SOP Prime or SOP Double Prime packages. 608 * 609 * Returns handle to the cable plug on success or NULL on failure. 610 */ 611struct typec_plug *typec_register_plug(struct typec_cable *cable, 612 struct typec_plug_desc *desc) 613{ 614 struct typec_plug *plug; 615 char name[8]; 616 int ret; 617 618 plug = kzalloc(sizeof(*plug), GFP_KERNEL); 619 if (!plug) 620 return NULL; 621 622 sprintf(name, "plug%d", desc->index); 623 624 plug->index = desc->index; 625 plug->dev.class = typec_class; 626 plug->dev.parent = &cable->dev; 627 plug->dev.type = &typec_plug_dev_type; 628 dev_set_name(&plug->dev, "%s-%s", dev_name(cable->dev.parent), name); 629 630 ret = device_register(&plug->dev); 631 if (ret) { 632 dev_err(&cable->dev, "failed to register plug (%d)\n", ret); 633 put_device(&plug->dev); 634 return NULL; 635 } 636 637 return plug; 638} 639EXPORT_SYMBOL_GPL(typec_register_plug); 640 641/** 642 * typec_unregister_plug - Unregister a USB Type-C Cable Plug 643 * @plug: The cable plug to be unregistered 644 * 645 * Unregister device created with typec_register_plug(). 646 */ 647void typec_unregister_plug(struct typec_plug *plug) 648{ 649 if (plug) 650 device_unregister(&plug->dev); 651} 652EXPORT_SYMBOL_GPL(typec_unregister_plug); 653 654/* Type-C Cables */ 655 656static ssize_t 657type_show(struct device *dev, struct device_attribute *attr, char *buf) 658{ 659 struct typec_cable *cable = to_typec_cable(dev); 660 661 return sprintf(buf, "%s\n", cable->active ? "active" : "passive"); 662} 663static DEVICE_ATTR_RO(type); 664 665static const char * const typec_plug_types[] = { 666 [USB_PLUG_NONE] = "unknown", 667 [USB_PLUG_TYPE_A] = "type-a", 668 [USB_PLUG_TYPE_B] = "type-b", 669 [USB_PLUG_TYPE_C] = "type-c", 670 [USB_PLUG_CAPTIVE] = "captive", 671}; 672 673static ssize_t plug_type_show(struct device *dev, 674 struct device_attribute *attr, char *buf) 675{ 676 struct typec_cable *cable = to_typec_cable(dev); 677 678 return sprintf(buf, "%s\n", typec_plug_types[cable->type]); 679} 680static DEVICE_ATTR_RO(plug_type); 681 682static struct attribute *typec_cable_attrs[] = { 683 &dev_attr_type.attr, 684 &dev_attr_plug_type.attr, 685 NULL 686}; 687ATTRIBUTE_GROUPS(typec_cable); 688 689static void typec_cable_release(struct device *dev) 690{ 691 struct typec_cable *cable = to_typec_cable(dev); 692 693 kfree(cable); 694} 695 696static const struct device_type typec_cable_dev_type = { 697 .name = "typec_cable", 698 .groups = typec_cable_groups, 699 .release = typec_cable_release, 700}; 701 702/** 703 * typec_cable_set_identity - Report result from Discover Identity command 704 * @cable: The cable updated identity values 705 * 706 * This routine is used to report that the result of Discover Identity USB power 707 * delivery command has become available. 708 */ 709int typec_cable_set_identity(struct typec_cable *cable) 710{ 711 if (!cable->identity) 712 return -EINVAL; 713 714 typec_report_identity(&cable->dev); 715 return 0; 716} 717EXPORT_SYMBOL_GPL(typec_cable_set_identity); 718 719/** 720 * typec_register_cable - Register a USB Type-C Cable 721 * @port: The USB Type-C Port the cable is connected to 722 * @desc: Description of the cable 723 * 724 * Registers a device for USB Type-C Cable described in @desc. The cable will be 725 * parent for the optional cable plug devises. 726 * 727 * Returns handle to the cable on success or NULL on failure. 728 */ 729struct typec_cable *typec_register_cable(struct typec_port *port, 730 struct typec_cable_desc *desc) 731{ 732 struct typec_cable *cable; 733 int ret; 734 735 cable = kzalloc(sizeof(*cable), GFP_KERNEL); 736 if (!cable) 737 return NULL; 738 739 cable->type = desc->type; 740 cable->active = desc->active; 741 742 if (desc->identity) { 743 /* 744 * Creating directory for the identity only if the driver is 745 * able to provide data to it. 746 */ 747 cable->dev.groups = usb_pd_id_groups; 748 cable->identity = desc->identity; 749 } 750 751 cable->dev.class = typec_class; 752 cable->dev.parent = &port->dev; 753 cable->dev.type = &typec_cable_dev_type; 754 dev_set_name(&cable->dev, "%s-cable", dev_name(&port->dev)); 755 756 ret = device_register(&cable->dev); 757 if (ret) { 758 dev_err(&port->dev, "failed to register cable (%d)\n", ret); 759 put_device(&cable->dev); 760 return NULL; 761 } 762 763 return cable; 764} 765EXPORT_SYMBOL_GPL(typec_register_cable); 766 767/** 768 * typec_unregister_cable - Unregister a USB Type-C Cable 769 * @cable: The cable to be unregistered 770 * 771 * Unregister device created with typec_register_cable(). 772 */ 773void typec_unregister_cable(struct typec_cable *cable) 774{ 775 if (cable) 776 device_unregister(&cable->dev); 777} 778EXPORT_SYMBOL_GPL(typec_unregister_cable); 779 780/* ------------------------------------------------------------------------- */ 781/* USB Type-C ports */ 782 783static const char * const typec_roles[] = { 784 [TYPEC_SINK] = "sink", 785 [TYPEC_SOURCE] = "source", 786}; 787 788static const char * const typec_data_roles[] = { 789 [TYPEC_DEVICE] = "device", 790 [TYPEC_HOST] = "host", 791}; 792 793static const char * const typec_port_types[] = { 794 [TYPEC_PORT_DFP] = "source", 795 [TYPEC_PORT_UFP] = "sink", 796 [TYPEC_PORT_DRP] = "dual", 797}; 798 799static const char * const typec_port_types_drp[] = { 800 [TYPEC_PORT_DFP] = "dual [source] sink", 801 [TYPEC_PORT_UFP] = "dual source [sink]", 802 [TYPEC_PORT_DRP] = "[dual] source sink", 803}; 804 805static ssize_t 806preferred_role_store(struct device *dev, struct device_attribute *attr, 807 const char *buf, size_t size) 808{ 809 struct typec_port *port = to_typec_port(dev); 810 int role; 811 int ret; 812 813 if (port->cap->type != TYPEC_PORT_DRP) { 814 dev_dbg(dev, "Preferred role only supported with DRP ports\n"); 815 return -EOPNOTSUPP; 816 } 817 818 if (!port->cap->try_role) { 819 dev_dbg(dev, "Setting preferred role not supported\n"); 820 return -EOPNOTSUPP; 821 } 822 823 role = sysfs_match_string(typec_roles, buf); 824 if (role < 0) { 825 if (sysfs_streq(buf, "none")) 826 role = TYPEC_NO_PREFERRED_ROLE; 827 else 828 return -EINVAL; 829 } 830 831 ret = port->cap->try_role(port->cap, role); 832 if (ret) 833 return ret; 834 835 port->prefer_role = role; 836 return size; 837} 838 839static ssize_t 840preferred_role_show(struct device *dev, struct device_attribute *attr, 841 char *buf) 842{ 843 struct typec_port *port = to_typec_port(dev); 844 845 if (port->cap->type != TYPEC_PORT_DRP) 846 return 0; 847 848 if (port->prefer_role < 0) 849 return 0; 850 851 return sprintf(buf, "%s\n", typec_roles[port->prefer_role]); 852} 853static DEVICE_ATTR_RW(preferred_role); 854 855static ssize_t data_role_store(struct device *dev, 856 struct device_attribute *attr, 857 const char *buf, size_t size) 858{ 859 struct typec_port *port = to_typec_port(dev); 860 int ret; 861 862 if (!port->cap->dr_set) { 863 dev_dbg(dev, "data role swapping not supported\n"); 864 return -EOPNOTSUPP; 865 } 866 867 ret = sysfs_match_string(typec_data_roles, buf); 868 if (ret < 0) 869 return ret; 870 871 mutex_lock(&port->port_type_lock); 872 if (port->port_type != TYPEC_PORT_DRP) { 873 dev_dbg(dev, "port type fixed at \"%s\"", 874 typec_port_types[port->port_type]); 875 ret = -EOPNOTSUPP; 876 goto unlock_and_ret; 877 } 878 879 ret = port->cap->dr_set(port->cap, ret); 880 if (ret) 881 goto unlock_and_ret; 882 883 ret = size; 884unlock_and_ret: 885 mutex_unlock(&port->port_type_lock); 886 return ret; 887} 888 889static ssize_t data_role_show(struct device *dev, 890 struct device_attribute *attr, char *buf) 891{ 892 struct typec_port *port = to_typec_port(dev); 893 894 if (port->cap->type == TYPEC_PORT_DRP) 895 return sprintf(buf, "%s\n", port->data_role == TYPEC_HOST ? 896 "[host] device" : "host [device]"); 897 898 return sprintf(buf, "[%s]\n", typec_data_roles[port->data_role]); 899} 900static DEVICE_ATTR_RW(data_role); 901 902static ssize_t power_role_store(struct device *dev, 903 struct device_attribute *attr, 904 const char *buf, size_t size) 905{ 906 struct typec_port *port = to_typec_port(dev); 907 int ret; 908 909 if (!port->cap->pd_revision) { 910 dev_dbg(dev, "USB Power Delivery not supported\n"); 911 return -EOPNOTSUPP; 912 } 913 914 if (!port->cap->pr_set) { 915 dev_dbg(dev, "power role swapping not supported\n"); 916 return -EOPNOTSUPP; 917 } 918 919 if (port->pwr_opmode != TYPEC_PWR_MODE_PD) { 920 dev_dbg(dev, "partner unable to swap power role\n"); 921 return -EIO; 922 } 923 924 ret = sysfs_match_string(typec_roles, buf); 925 if (ret < 0) 926 return ret; 927 928 mutex_lock(&port->port_type_lock); 929 if (port->port_type != TYPEC_PORT_DRP) { 930 dev_dbg(dev, "port type fixed at \"%s\"", 931 typec_port_types[port->port_type]); 932 ret = -EOPNOTSUPP; 933 goto unlock_and_ret; 934 } 935 936 ret = port->cap->pr_set(port->cap, ret); 937 if (ret) 938 goto unlock_and_ret; 939 940 ret = size; 941unlock_and_ret: 942 mutex_unlock(&port->port_type_lock); 943 return ret; 944} 945 946static ssize_t power_role_show(struct device *dev, 947 struct device_attribute *attr, char *buf) 948{ 949 struct typec_port *port = to_typec_port(dev); 950 951 if (port->cap->type == TYPEC_PORT_DRP) 952 return sprintf(buf, "%s\n", port->pwr_role == TYPEC_SOURCE ? 953 "[source] sink" : "source [sink]"); 954 955 return sprintf(buf, "[%s]\n", typec_roles[port->pwr_role]); 956} 957static DEVICE_ATTR_RW(power_role); 958 959static ssize_t 960port_type_store(struct device *dev, struct device_attribute *attr, 961 const char *buf, size_t size) 962{ 963 struct typec_port *port = to_typec_port(dev); 964 int ret; 965 enum typec_port_type type; 966 967 if (!port->cap->port_type_set || port->cap->type != TYPEC_PORT_DRP) { 968 dev_dbg(dev, "changing port type not supported\n"); 969 return -EOPNOTSUPP; 970 } 971 972 ret = sysfs_match_string(typec_port_types, buf); 973 if (ret < 0) 974 return ret; 975 976 type = ret; 977 mutex_lock(&port->port_type_lock); 978 979 if (port->port_type == type) { 980 ret = size; 981 goto unlock_and_ret; 982 } 983 984 ret = port->cap->port_type_set(port->cap, type); 985 if (ret) 986 goto unlock_and_ret; 987 988 port->port_type = type; 989 ret = size; 990 991unlock_and_ret: 992 mutex_unlock(&port->port_type_lock); 993 return ret; 994} 995 996static ssize_t 997port_type_show(struct device *dev, struct device_attribute *attr, 998 char *buf) 999{ 1000 struct typec_port *port = to_typec_port(dev); 1001 1002 if (port->cap->type == TYPEC_PORT_DRP) 1003 return sprintf(buf, "%s\n", 1004 typec_port_types_drp[port->port_type]); 1005 1006 return sprintf(buf, "[%s]\n", typec_port_types[port->cap->type]); 1007} 1008static DEVICE_ATTR_RW(port_type); 1009 1010static const char * const typec_pwr_opmodes[] = { 1011 [TYPEC_PWR_MODE_USB] = "default", 1012 [TYPEC_PWR_MODE_1_5A] = "1.5A", 1013 [TYPEC_PWR_MODE_3_0A] = "3.0A", 1014 [TYPEC_PWR_MODE_PD] = "usb_power_delivery", 1015}; 1016 1017static ssize_t power_operation_mode_show(struct device *dev, 1018 struct device_attribute *attr, 1019 char *buf) 1020{ 1021 struct typec_port *port = to_typec_port(dev); 1022 1023 return sprintf(buf, "%s\n", typec_pwr_opmodes[port->pwr_opmode]); 1024} 1025static DEVICE_ATTR_RO(power_operation_mode); 1026 1027static ssize_t vconn_source_store(struct device *dev, 1028 struct device_attribute *attr, 1029 const char *buf, size_t size) 1030{ 1031 struct typec_port *port = to_typec_port(dev); 1032 bool source; 1033 int ret; 1034 1035 if (!port->cap->pd_revision) { 1036 dev_dbg(dev, "VCONN swap depends on USB Power Delivery\n"); 1037 return -EOPNOTSUPP; 1038 } 1039 1040 if (!port->cap->vconn_set) { 1041 dev_dbg(dev, "VCONN swapping not supported\n"); 1042 return -EOPNOTSUPP; 1043 } 1044 1045 ret = kstrtobool(buf, &source); 1046 if (ret) 1047 return ret; 1048 1049 ret = port->cap->vconn_set(port->cap, (enum typec_role)source); 1050 if (ret) 1051 return ret; 1052 1053 return size; 1054} 1055 1056static ssize_t vconn_source_show(struct device *dev, 1057 struct device_attribute *attr, char *buf) 1058{ 1059 struct typec_port *port = to_typec_port(dev); 1060 1061 return sprintf(buf, "%s\n", 1062 port->vconn_role == TYPEC_SOURCE ? "yes" : "no"); 1063} 1064static DEVICE_ATTR_RW(vconn_source); 1065 1066static ssize_t supported_accessory_modes_show(struct device *dev, 1067 struct device_attribute *attr, 1068 char *buf) 1069{ 1070 struct typec_port *port = to_typec_port(dev); 1071 ssize_t ret = 0; 1072 int i; 1073 1074 for (i = 0; i < ARRAY_SIZE(port->cap->accessory); i++) { 1075 if (port->cap->accessory[i]) 1076 ret += sprintf(buf + ret, "%s ", 1077 typec_accessory_modes[port->cap->accessory[i]]); 1078 } 1079 1080 if (!ret) 1081 return sprintf(buf, "none\n"); 1082 1083 buf[ret - 1] = '\n'; 1084 1085 return ret; 1086} 1087static DEVICE_ATTR_RO(supported_accessory_modes); 1088 1089static ssize_t usb_typec_revision_show(struct device *dev, 1090 struct device_attribute *attr, 1091 char *buf) 1092{ 1093 struct typec_port *port = to_typec_port(dev); 1094 u16 rev = port->cap->revision; 1095 1096 return sprintf(buf, "%d.%d\n", (rev >> 8) & 0xff, (rev >> 4) & 0xf); 1097} 1098static DEVICE_ATTR_RO(usb_typec_revision); 1099 1100static ssize_t usb_power_delivery_revision_show(struct device *dev, 1101 struct device_attribute *attr, 1102 char *buf) 1103{ 1104 struct typec_port *p = to_typec_port(dev); 1105 1106 return sprintf(buf, "%d\n", (p->cap->pd_revision >> 8) & 0xff); 1107} 1108static DEVICE_ATTR_RO(usb_power_delivery_revision); 1109 1110static struct attribute *typec_attrs[] = { 1111 &dev_attr_data_role.attr, 1112 &dev_attr_power_operation_mode.attr, 1113 &dev_attr_power_role.attr, 1114 &dev_attr_preferred_role.attr, 1115 &dev_attr_supported_accessory_modes.attr, 1116 &dev_attr_usb_power_delivery_revision.attr, 1117 &dev_attr_usb_typec_revision.attr, 1118 &dev_attr_vconn_source.attr, 1119 &dev_attr_port_type.attr, 1120 NULL, 1121}; 1122ATTRIBUTE_GROUPS(typec); 1123 1124static int typec_uevent(struct device *dev, struct kobj_uevent_env *env) 1125{ 1126 int ret; 1127 1128 ret = add_uevent_var(env, "TYPEC_PORT=%s", dev_name(dev)); 1129 if (ret) 1130 dev_err(dev, "failed to add uevent TYPEC_PORT\n"); 1131 1132 return ret; 1133} 1134 1135static void typec_release(struct device *dev) 1136{ 1137 struct typec_port *port = to_typec_port(dev); 1138 1139 ida_simple_remove(&typec_index_ida, port->id); 1140 kfree(port); 1141} 1142 1143static const struct device_type typec_port_dev_type = { 1144 .name = "typec_port", 1145 .groups = typec_groups, 1146 .uevent = typec_uevent, 1147 .release = typec_release, 1148}; 1149 1150/* --------------------------------------- */ 1151/* Driver callbacks to report role updates */ 1152 1153/** 1154 * typec_set_data_role - Report data role change 1155 * @port: The USB Type-C Port where the role was changed 1156 * @role: The new data role 1157 * 1158 * This routine is used by the port drivers to report data role changes. 1159 */ 1160void typec_set_data_role(struct typec_port *port, enum typec_data_role role) 1161{ 1162 if (port->data_role == role) 1163 return; 1164 1165 port->data_role = role; 1166 sysfs_notify(&port->dev.kobj, NULL, "data_role"); 1167 kobject_uevent(&port->dev.kobj, KOBJ_CHANGE); 1168} 1169EXPORT_SYMBOL_GPL(typec_set_data_role); 1170 1171/** 1172 * typec_set_pwr_role - Report power role change 1173 * @port: The USB Type-C Port where the role was changed 1174 * @role: The new data role 1175 * 1176 * This routine is used by the port drivers to report power role changes. 1177 */ 1178void typec_set_pwr_role(struct typec_port *port, enum typec_role role) 1179{ 1180 if (port->pwr_role == role) 1181 return; 1182 1183 port->pwr_role = role; 1184 sysfs_notify(&port->dev.kobj, NULL, "power_role"); 1185 kobject_uevent(&port->dev.kobj, KOBJ_CHANGE); 1186} 1187EXPORT_SYMBOL_GPL(typec_set_pwr_role); 1188 1189/** 1190 * typec_set_pwr_role - Report VCONN source change 1191 * @port: The USB Type-C Port which VCONN role changed 1192 * @role: Source when @port is sourcing VCONN, or Sink when it's not 1193 * 1194 * This routine is used by the port drivers to report if the VCONN source is 1195 * changes. 1196 */ 1197void typec_set_vconn_role(struct typec_port *port, enum typec_role role) 1198{ 1199 if (port->vconn_role == role) 1200 return; 1201 1202 port->vconn_role = role; 1203 sysfs_notify(&port->dev.kobj, NULL, "vconn_source"); 1204 kobject_uevent(&port->dev.kobj, KOBJ_CHANGE); 1205} 1206EXPORT_SYMBOL_GPL(typec_set_vconn_role); 1207 1208static int partner_match(struct device *dev, void *data) 1209{ 1210 return is_typec_partner(dev); 1211} 1212 1213/** 1214 * typec_set_pwr_opmode - Report changed power operation mode 1215 * @port: The USB Type-C Port where the mode was changed 1216 * @opmode: New power operation mode 1217 * 1218 * This routine is used by the port drivers to report changed power operation 1219 * mode in @port. The modes are USB (default), 1.5A, 3.0A as defined in USB 1220 * Type-C specification, and "USB Power Delivery" when the power levels are 1221 * negotiated with methods defined in USB Power Delivery specification. 1222 */ 1223void typec_set_pwr_opmode(struct typec_port *port, 1224 enum typec_pwr_opmode opmode) 1225{ 1226 struct device *partner_dev; 1227 1228 if (port->pwr_opmode == opmode) 1229 return; 1230 1231 port->pwr_opmode = opmode; 1232 sysfs_notify(&port->dev.kobj, NULL, "power_operation_mode"); 1233 kobject_uevent(&port->dev.kobj, KOBJ_CHANGE); 1234 1235 partner_dev = device_find_child(&port->dev, NULL, partner_match); 1236 if (partner_dev) { 1237 struct typec_partner *partner = to_typec_partner(partner_dev); 1238 1239 if (opmode == TYPEC_PWR_MODE_PD && !partner->usb_pd) { 1240 partner->usb_pd = 1; 1241 sysfs_notify(&partner_dev->kobj, NULL, 1242 "supports_usb_power_delivery"); 1243 } 1244 put_device(partner_dev); 1245 } 1246} 1247EXPORT_SYMBOL_GPL(typec_set_pwr_opmode); 1248 1249/* --------------------------------------- */ 1250 1251/** 1252 * typec_port_register_altmode - Register USB Type-C Port Alternate Mode 1253 * @port: USB Type-C Port that supports the alternate mode 1254 * @desc: Description of the alternate mode 1255 * 1256 * This routine is used to register an alternate mode that @port is capable of 1257 * supporting. 1258 * 1259 * Returns handle to the alternate mode on success or NULL on failure. 1260 */ 1261struct typec_altmode * 1262typec_port_register_altmode(struct typec_port *port, 1263 const struct typec_altmode_desc *desc) 1264{ 1265 return typec_register_altmode(&port->dev, desc); 1266} 1267EXPORT_SYMBOL_GPL(typec_port_register_altmode); 1268 1269/** 1270 * typec_register_port - Register a USB Type-C Port 1271 * @parent: Parent device 1272 * @cap: Description of the port 1273 * 1274 * Registers a device for USB Type-C Port described in @cap. 1275 * 1276 * Returns handle to the port on success or NULL on failure. 1277 */ 1278struct typec_port *typec_register_port(struct device *parent, 1279 const struct typec_capability *cap) 1280{ 1281 struct typec_port *port; 1282 int role; 1283 int ret; 1284 int id; 1285 1286 port = kzalloc(sizeof(*port), GFP_KERNEL); 1287 if (!port) 1288 return NULL; 1289 1290 id = ida_simple_get(&typec_index_ida, 0, 0, GFP_KERNEL); 1291 if (id < 0) { 1292 kfree(port); 1293 return NULL; 1294 } 1295 1296 if (cap->type == TYPEC_PORT_DFP) 1297 role = TYPEC_SOURCE; 1298 else if (cap->type == TYPEC_PORT_UFP) 1299 role = TYPEC_SINK; 1300 else 1301 role = cap->prefer_role; 1302 1303 if (role == TYPEC_SOURCE) { 1304 port->data_role = TYPEC_HOST; 1305 port->pwr_role = TYPEC_SOURCE; 1306 port->vconn_role = TYPEC_SOURCE; 1307 } else { 1308 port->data_role = TYPEC_DEVICE; 1309 port->pwr_role = TYPEC_SINK; 1310 port->vconn_role = TYPEC_SINK; 1311 } 1312 1313 port->id = id; 1314 port->cap = cap; 1315 port->port_type = cap->type; 1316 mutex_init(&port->port_type_lock); 1317 port->prefer_role = cap->prefer_role; 1318 1319 port->dev.class = typec_class; 1320 port->dev.parent = parent; 1321 port->dev.fwnode = cap->fwnode; 1322 port->dev.type = &typec_port_dev_type; 1323 dev_set_name(&port->dev, "port%d", id); 1324 1325 ret = device_register(&port->dev); 1326 if (ret) { 1327 dev_err(parent, "failed to register port (%d)\n", ret); 1328 put_device(&port->dev); 1329 return NULL; 1330 } 1331 1332 return port; 1333} 1334EXPORT_SYMBOL_GPL(typec_register_port); 1335 1336/** 1337 * typec_unregister_port - Unregister a USB Type-C Port 1338 * @port: The port to be unregistered 1339 * 1340 * Unregister device created with typec_register_port(). 1341 */ 1342void typec_unregister_port(struct typec_port *port) 1343{ 1344 if (port) 1345 device_unregister(&port->dev); 1346} 1347EXPORT_SYMBOL_GPL(typec_unregister_port); 1348 1349static int __init typec_init(void) 1350{ 1351 typec_class = class_create(THIS_MODULE, "typec"); 1352 return PTR_ERR_OR_ZERO(typec_class); 1353} 1354subsys_initcall(typec_init); 1355 1356static void __exit typec_exit(void) 1357{ 1358 class_destroy(typec_class); 1359 ida_destroy(&typec_index_ida); 1360} 1361module_exit(typec_exit); 1362 1363MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>"); 1364MODULE_LICENSE("GPL v2"); 1365MODULE_DESCRIPTION("USB Type-C Connector Class");