Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'devprop-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull device properties framework updates from Rafael Wysocki:
"These add helpers for counting items in a property array and extend
the "software nodes" support to be more convenient for representing
device properties supplied by drivers and make the intel_cht_int33fe
driver use that.

Specifics:

- Add helpers to count items in a property array (Andy Shevchenko).

- Extend "software nodes" support to be more convenient for
representing device properties supplied by drivers (Heikki
Krogerus).

- Add device_find_child_by_name() helper to the driver core (Heikki
Krogerus).

- Extend device connection code to also look for references provided
via fwnode pointers (Heikki Krogerus).

- Start to register proper struct device objects for USB Type-C muxes
and orientation switches (Heikki Krogerus).

- Update the intel_cht_int33fe driver to describe devices in a more
general way with the help of "software nodes" (Heikki Krogerus)"

* tag 'devprop-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
device property: Add helpers to count items in an array
platform/x86: intel_cht_int33fe: Replacing the old connections with references
platform/x86: intel_cht_int33fe: Supply fwnodes for the external dependencies
platform/x86: intel_cht_int33fe: Provide fwnode for the USB connector
platform/x86: intel_cht_int33fe: Provide software nodes for the devices
platform/x86: intel_cht_int33fe: Remove unused fusb302 device property
platform/x86: intel_cht_int33fe: Register max17047 in its own function
usb: typec: Registering real device entries for the muxes
device connection: Find connections also by checking the references
device property: Introduce fwnode_find_reference()
ACPI / property: Don't limit named child node matching to data nodes
driver core: Add helper device_find_child_by_name()
software node: Add software_node_get_reference_args()
software node: Use kobject name when finding child nodes by name
software node: Add support for static node descriptors
software node: Simplify software_node_release() function
software node: Allow node creation without properties

+954 -256
+20 -6
drivers/acpi/property.c
··· 600 600 acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode, 601 601 const char *childname) 602 602 { 603 + char name[ACPI_PATH_SEGMENT_LENGTH]; 603 604 struct fwnode_handle *child; 605 + struct acpi_buffer path; 606 + acpi_status status; 604 607 605 - /* 606 - * Find first matching named child node of this fwnode. 607 - * For ACPI this will be a data only sub-node. 608 - */ 609 - fwnode_for_each_child_node(fwnode, child) 610 - if (acpi_data_node_match(child, childname)) 608 + path.length = sizeof(name); 609 + path.pointer = name; 610 + 611 + fwnode_for_each_child_node(fwnode, child) { 612 + if (is_acpi_data_node(child)) { 613 + if (acpi_data_node_match(child, childname)) 614 + return child; 615 + continue; 616 + } 617 + 618 + status = acpi_get_name(ACPI_HANDLE_FWNODE(child), 619 + ACPI_SINGLE_NAME, &path); 620 + if (ACPI_FAILURE(status)) 621 + break; 622 + 623 + if (!strncmp(name, childname, ACPI_NAMESEG_SIZE)) 611 624 return child; 625 + } 612 626 613 627 return NULL; 614 628 }
+28
drivers/base/core.c
··· 2474 2474 } 2475 2475 EXPORT_SYMBOL_GPL(device_find_child); 2476 2476 2477 + /** 2478 + * device_find_child_by_name - device iterator for locating a child device. 2479 + * @parent: parent struct device 2480 + * @name: name of the child device 2481 + * 2482 + * This is similar to the device_find_child() function above, but it 2483 + * returns a reference to a device that has the name @name. 2484 + * 2485 + * NOTE: you will need to drop the reference with put_device() after use. 2486 + */ 2487 + struct device *device_find_child_by_name(struct device *parent, 2488 + const char *name) 2489 + { 2490 + struct klist_iter i; 2491 + struct device *child; 2492 + 2493 + if (!parent) 2494 + return NULL; 2495 + 2496 + klist_iter_init(&parent->p->klist_children, &i); 2497 + while ((child = next_device(&i))) 2498 + if (!strcmp(dev_name(child), name) && get_device(child)) 2499 + break; 2500 + klist_iter_exit(&i); 2501 + return child; 2502 + } 2503 + EXPORT_SYMBOL_GPL(device_find_child_by_name); 2504 + 2477 2505 int __init devices_init(void) 2478 2506 { 2479 2507 devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
+26
drivers/base/devcon.c
··· 38 38 return NULL; 39 39 } 40 40 41 + static void * 42 + fwnode_devcon_match(struct fwnode_handle *fwnode, const char *con_id, 43 + void *data, devcon_match_fn_t match) 44 + { 45 + struct device_connection con = { }; 46 + void *ret; 47 + int i; 48 + 49 + for (i = 0; ; i++) { 50 + con.fwnode = fwnode_find_reference(fwnode, con_id, i); 51 + if (IS_ERR(con.fwnode)) 52 + break; 53 + 54 + ret = match(&con, -1, data); 55 + fwnode_handle_put(con.fwnode); 56 + if (ret) 57 + return ret; 58 + } 59 + 60 + return NULL; 61 + } 62 + 41 63 /** 42 64 * device_connection_find_match - Find physical connection to a device 43 65 * @dev: Device with the connection ··· 85 63 86 64 if (fwnode) { 87 65 ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); 66 + if (ret) 67 + return ret; 68 + 69 + ret = fwnode_devcon_match(fwnode, con_id, data, match); 88 70 if (ret) 89 71 return ret; 90 72 }
+24
drivers/base/property.c
··· 485 485 EXPORT_SYMBOL_GPL(fwnode_property_get_reference_args); 486 486 487 487 /** 488 + * fwnode_find_reference - Find named reference to a fwnode_handle 489 + * @fwnode: Firmware node where to look for the reference 490 + * @name: The name of the reference 491 + * @index: Index of the reference 492 + * 493 + * @index can be used when the named reference holds a table of references. 494 + * 495 + * Returns pointer to the reference fwnode, or ERR_PTR. Caller is responsible to 496 + * call fwnode_handle_put() on the returned fwnode pointer. 497 + */ 498 + struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode, 499 + const char *name, 500 + unsigned int index) 501 + { 502 + struct fwnode_reference_args args; 503 + int ret; 504 + 505 + ret = fwnode_property_get_reference_args(fwnode, name, NULL, 0, index, 506 + &args); 507 + return ret ? ERR_PTR(ret) : args.fwnode; 508 + } 509 + EXPORT_SYMBOL_GPL(fwnode_find_reference); 510 + 511 + /** 488 512 * device_remove_properties - Remove properties from a device object. 489 513 * @dev: Device whose properties to remove. 490 514 *
+256 -80
drivers/base/swnode.c
··· 11 11 #include <linux/property.h> 12 12 #include <linux/slab.h> 13 13 14 - struct software_node { 14 + struct swnode { 15 15 int id; 16 16 struct kobject kobj; 17 17 struct fwnode_handle fwnode; 18 + const struct software_node *node; 18 19 19 20 /* hierarchy */ 20 21 struct ida child_ids; 21 22 struct list_head entry; 22 23 struct list_head children; 23 - struct software_node *parent; 24 + struct swnode *parent; 24 25 25 - /* properties */ 26 - const struct property_entry *properties; 26 + unsigned int allocated:1; 27 27 }; 28 28 29 29 static DEFINE_IDA(swnode_root_ids); 30 30 static struct kset *swnode_kset; 31 31 32 - #define kobj_to_swnode(_kobj_) container_of(_kobj_, struct software_node, kobj) 32 + #define kobj_to_swnode(_kobj_) container_of(_kobj_, struct swnode, kobj) 33 33 34 34 static const struct fwnode_operations software_node_ops; 35 35 ··· 37 37 { 38 38 return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &software_node_ops; 39 39 } 40 + EXPORT_SYMBOL_GPL(is_software_node); 40 41 41 - #define to_software_node(__fwnode) \ 42 + #define to_swnode(__fwnode) \ 42 43 ({ \ 43 - typeof(__fwnode) __to_software_node_fwnode = __fwnode; \ 44 + typeof(__fwnode) __to_swnode_fwnode = __fwnode; \ 44 45 \ 45 - is_software_node(__to_software_node_fwnode) ? \ 46 - container_of(__to_software_node_fwnode, \ 47 - struct software_node, fwnode) : \ 48 - NULL; \ 46 + is_software_node(__to_swnode_fwnode) ? \ 47 + container_of(__to_swnode_fwnode, \ 48 + struct swnode, fwnode) : NULL; \ 49 49 }) 50 + 51 + static struct swnode * 52 + software_node_to_swnode(const struct software_node *node) 53 + { 54 + struct swnode *swnode; 55 + struct kobject *k; 56 + 57 + if (!node) 58 + return NULL; 59 + 60 + spin_lock(&swnode_kset->list_lock); 61 + 62 + list_for_each_entry(k, &swnode_kset->list, entry) { 63 + swnode = kobj_to_swnode(k); 64 + if (swnode->node == node) 65 + break; 66 + swnode = NULL; 67 + } 68 + 69 + spin_unlock(&swnode_kset->list_lock); 70 + 71 + return swnode; 72 + } 73 + 74 + const struct software_node *to_software_node(struct fwnode_handle *fwnode) 75 + { 76 + struct swnode *swnode = to_swnode(fwnode); 77 + 78 + return swnode ? swnode->node : NULL; 79 + } 80 + EXPORT_SYMBOL_GPL(to_software_node); 81 + 82 + struct fwnode_handle *software_node_fwnode(const struct software_node *node) 83 + { 84 + struct swnode *swnode = software_node_to_swnode(node); 85 + 86 + return swnode ? &swnode->fwnode : NULL; 87 + } 88 + EXPORT_SYMBOL_GPL(software_node_fwnode); 50 89 51 90 /* -------------------------------------------------------------------------- */ 52 91 /* property_entry processing */ ··· 422 383 int i, n = 0; 423 384 int ret; 424 385 386 + if (!properties) 387 + return NULL; 388 + 425 389 while (properties[n].name) 426 390 n++; 427 391 ··· 472 430 473 431 static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode) 474 432 { 475 - struct software_node *swnode = to_software_node(fwnode); 433 + struct swnode *swnode = to_swnode(fwnode); 476 434 477 435 kobject_get(&swnode->kobj); 478 436 ··· 481 439 482 440 static void software_node_put(struct fwnode_handle *fwnode) 483 441 { 484 - struct software_node *swnode = to_software_node(fwnode); 442 + struct swnode *swnode = to_swnode(fwnode); 485 443 486 444 kobject_put(&swnode->kobj); 487 445 } ··· 489 447 static bool software_node_property_present(const struct fwnode_handle *fwnode, 490 448 const char *propname) 491 449 { 492 - return !!property_entry_get(to_software_node(fwnode)->properties, 493 - propname); 450 + struct swnode *swnode = to_swnode(fwnode); 451 + 452 + return !!property_entry_get(swnode->node->properties, propname); 494 453 } 495 454 496 455 static int software_node_read_int_array(const struct fwnode_handle *fwnode, ··· 499 456 unsigned int elem_size, void *val, 500 457 size_t nval) 501 458 { 502 - struct software_node *swnode = to_software_node(fwnode); 459 + struct swnode *swnode = to_swnode(fwnode); 503 460 504 - return property_entry_read_int_array(swnode->properties, propname, 461 + return property_entry_read_int_array(swnode->node->properties, propname, 505 462 elem_size, val, nval); 506 463 } 507 464 ··· 509 466 const char *propname, 510 467 const char **val, size_t nval) 511 468 { 512 - struct software_node *swnode = to_software_node(fwnode); 469 + struct swnode *swnode = to_swnode(fwnode); 513 470 514 - return property_entry_read_string_array(swnode->properties, propname, 515 - val, nval); 471 + return property_entry_read_string_array(swnode->node->properties, 472 + propname, val, nval); 516 473 } 517 474 518 475 static struct fwnode_handle * 519 476 software_node_get_parent(const struct fwnode_handle *fwnode) 520 477 { 521 - struct software_node *swnode = to_software_node(fwnode); 478 + struct swnode *swnode = to_swnode(fwnode); 522 479 523 - return swnode ? (swnode->parent ? &swnode->parent->fwnode : NULL) : 524 - NULL; 480 + return swnode ? (swnode->parent ? &swnode->parent->fwnode : NULL) : NULL; 525 481 } 526 482 527 483 static struct fwnode_handle * 528 484 software_node_get_next_child(const struct fwnode_handle *fwnode, 529 485 struct fwnode_handle *child) 530 486 { 531 - struct software_node *p = to_software_node(fwnode); 532 - struct software_node *c = to_software_node(child); 487 + struct swnode *p = to_swnode(fwnode); 488 + struct swnode *c = to_swnode(child); 533 489 534 490 if (!p || list_empty(&p->children) || 535 491 (c && list_is_last(&c->entry, &p->children))) ··· 537 495 if (c) 538 496 c = list_next_entry(c, entry); 539 497 else 540 - c = list_first_entry(&p->children, struct software_node, entry); 498 + c = list_first_entry(&p->children, struct swnode, entry); 541 499 return &c->fwnode; 542 500 } 543 501 ··· 545 503 software_node_get_named_child_node(const struct fwnode_handle *fwnode, 546 504 const char *childname) 547 505 { 548 - struct software_node *swnode = to_software_node(fwnode); 549 - const struct property_entry *prop; 550 - struct software_node *child; 506 + struct swnode *swnode = to_swnode(fwnode); 507 + struct swnode *child; 551 508 552 509 if (!swnode || list_empty(&swnode->children)) 553 510 return NULL; 554 511 555 512 list_for_each_entry(child, &swnode->children, entry) { 556 - prop = property_entry_get(child->properties, "name"); 557 - if (!prop) 558 - continue; 559 - if (!strcmp(childname, prop->value.str)) { 513 + if (!strcmp(childname, kobject_name(&child->kobj))) { 560 514 kobject_get(&child->kobj); 561 515 return &child->fwnode; 562 516 } 563 517 } 564 518 return NULL; 519 + } 520 + 521 + static int 522 + software_node_get_reference_args(const struct fwnode_handle *fwnode, 523 + const char *propname, const char *nargs_prop, 524 + unsigned int nargs, unsigned int index, 525 + struct fwnode_reference_args *args) 526 + { 527 + struct swnode *swnode = to_swnode(fwnode); 528 + const struct software_node_reference *ref; 529 + const struct property_entry *prop; 530 + struct fwnode_handle *refnode; 531 + int i; 532 + 533 + if (!swnode || !swnode->node->references) 534 + return -ENOENT; 535 + 536 + for (ref = swnode->node->references; ref->name; ref++) 537 + if (!strcmp(ref->name, propname)) 538 + break; 539 + 540 + if (!ref->name || index > (ref->nrefs - 1)) 541 + return -ENOENT; 542 + 543 + refnode = software_node_fwnode(ref->refs[index].node); 544 + if (!refnode) 545 + return -ENOENT; 546 + 547 + if (nargs_prop) { 548 + prop = property_entry_get(swnode->node->properties, nargs_prop); 549 + if (!prop) 550 + return -EINVAL; 551 + 552 + nargs = prop->value.u32_data; 553 + } 554 + 555 + if (nargs > NR_FWNODE_REFERENCE_ARGS) 556 + return -EINVAL; 557 + 558 + args->fwnode = software_node_get(refnode); 559 + args->nargs = nargs; 560 + 561 + for (i = 0; i < nargs; i++) 562 + args->args[i] = ref->refs[index].args[i]; 563 + 564 + return 0; 565 565 } 566 566 567 567 static const struct fwnode_operations software_node_ops = { ··· 615 531 .get_parent = software_node_get_parent, 616 532 .get_next_child_node = software_node_get_next_child, 617 533 .get_named_child_node = software_node_get_named_child_node, 534 + .get_reference_args = software_node_get_reference_args 618 535 }; 619 536 620 537 /* -------------------------------------------------------------------------- */ 621 538 622 539 static int 623 - software_node_register_properties(struct software_node *swnode, 540 + software_node_register_properties(struct software_node *node, 624 541 const struct property_entry *properties) 625 542 { 626 543 struct property_entry *props; ··· 630 545 if (IS_ERR(props)) 631 546 return PTR_ERR(props); 632 547 633 - swnode->properties = props; 548 + node->properties = props; 634 549 635 550 return 0; 636 551 } 637 552 638 553 static void software_node_release(struct kobject *kobj) 639 554 { 640 - struct software_node *swnode = kobj_to_swnode(kobj); 555 + struct swnode *swnode = kobj_to_swnode(kobj); 641 556 642 - if (swnode->parent) { 643 - ida_simple_remove(&swnode->parent->child_ids, swnode->id); 644 - list_del(&swnode->entry); 645 - } else { 646 - ida_simple_remove(&swnode_root_ids, swnode->id); 557 + if (swnode->allocated) { 558 + property_entries_free(swnode->node->properties); 559 + kfree(swnode->node); 647 560 } 648 - 649 561 ida_destroy(&swnode->child_ids); 650 - property_entries_free(swnode->properties); 651 562 kfree(swnode); 652 563 } 653 564 ··· 652 571 .sysfs_ops = &kobj_sysfs_ops, 653 572 }; 654 573 574 + static struct fwnode_handle * 575 + swnode_register(const struct software_node *node, struct swnode *parent, 576 + unsigned int allocated) 577 + { 578 + struct swnode *swnode; 579 + int ret; 580 + 581 + swnode = kzalloc(sizeof(*swnode), GFP_KERNEL); 582 + if (!swnode) { 583 + ret = -ENOMEM; 584 + goto out_err; 585 + } 586 + 587 + ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids, 588 + 0, 0, GFP_KERNEL); 589 + if (ret < 0) { 590 + kfree(swnode); 591 + goto out_err; 592 + } 593 + 594 + swnode->id = ret; 595 + swnode->node = node; 596 + swnode->parent = parent; 597 + swnode->allocated = allocated; 598 + swnode->kobj.kset = swnode_kset; 599 + swnode->fwnode.ops = &software_node_ops; 600 + 601 + ida_init(&swnode->child_ids); 602 + INIT_LIST_HEAD(&swnode->entry); 603 + INIT_LIST_HEAD(&swnode->children); 604 + 605 + if (node->name) 606 + ret = kobject_init_and_add(&swnode->kobj, &software_node_type, 607 + parent ? &parent->kobj : NULL, 608 + "%s", node->name); 609 + else 610 + ret = kobject_init_and_add(&swnode->kobj, &software_node_type, 611 + parent ? &parent->kobj : NULL, 612 + "node%d", swnode->id); 613 + if (ret) { 614 + kobject_put(&swnode->kobj); 615 + return ERR_PTR(ret); 616 + } 617 + 618 + if (parent) 619 + list_add_tail(&swnode->entry, &parent->children); 620 + 621 + kobject_uevent(&swnode->kobj, KOBJ_ADD); 622 + return &swnode->fwnode; 623 + 624 + out_err: 625 + if (allocated) 626 + property_entries_free(node->properties); 627 + return ERR_PTR(ret); 628 + } 629 + 630 + /** 631 + * software_node_register_nodes - Register an array of software nodes 632 + * @nodes: Zero terminated array of software nodes to be registered 633 + * 634 + * Register multiple software nodes at once. 635 + */ 636 + int software_node_register_nodes(const struct software_node *nodes) 637 + { 638 + int ret; 639 + int i; 640 + 641 + for (i = 0; nodes[i].name; i++) { 642 + ret = software_node_register(&nodes[i]); 643 + if (ret) { 644 + software_node_unregister_nodes(nodes); 645 + return ret; 646 + } 647 + } 648 + 649 + return 0; 650 + } 651 + EXPORT_SYMBOL_GPL(software_node_register_nodes); 652 + 653 + /** 654 + * software_node_unregister_nodes - Unregister an array of software nodes 655 + * @nodes: Zero terminated array of software nodes to be unregistered 656 + * 657 + * Unregister multiple software nodes at once. 658 + */ 659 + void software_node_unregister_nodes(const struct software_node *nodes) 660 + { 661 + struct swnode *swnode; 662 + int i; 663 + 664 + for (i = 0; nodes[i].name; i++) { 665 + swnode = software_node_to_swnode(&nodes[i]); 666 + if (swnode) 667 + fwnode_remove_software_node(&swnode->fwnode); 668 + } 669 + } 670 + EXPORT_SYMBOL_GPL(software_node_unregister_nodes); 671 + 672 + /** 673 + * software_node_register - Register static software node 674 + * @node: The software node to be registered 675 + */ 676 + int software_node_register(const struct software_node *node) 677 + { 678 + struct swnode *parent = software_node_to_swnode(node->parent); 679 + 680 + if (software_node_to_swnode(node)) 681 + return -EEXIST; 682 + 683 + return PTR_ERR_OR_ZERO(swnode_register(node, parent, 0)); 684 + } 685 + EXPORT_SYMBOL_GPL(software_node_register); 686 + 655 687 struct fwnode_handle * 656 688 fwnode_create_software_node(const struct property_entry *properties, 657 689 const struct fwnode_handle *parent) 658 690 { 659 - struct software_node *p = NULL; 660 - struct software_node *swnode; 691 + struct software_node *node; 692 + struct swnode *p = NULL; 661 693 int ret; 662 694 663 695 if (parent) { ··· 778 584 return ERR_CAST(parent); 779 585 if (!is_software_node(parent)) 780 586 return ERR_PTR(-EINVAL); 781 - p = to_software_node(parent); 587 + p = to_swnode(parent); 782 588 } 783 589 784 - swnode = kzalloc(sizeof(*swnode), GFP_KERNEL); 785 - if (!swnode) 590 + node = kzalloc(sizeof(*node), GFP_KERNEL); 591 + if (!node) 786 592 return ERR_PTR(-ENOMEM); 787 593 788 - ret = ida_simple_get(p ? &p->child_ids : &swnode_root_ids, 0, 0, 789 - GFP_KERNEL); 790 - if (ret < 0) { 791 - kfree(swnode); 792 - return ERR_PTR(ret); 793 - } 794 - 795 - swnode->id = ret; 796 - swnode->kobj.kset = swnode_kset; 797 - swnode->fwnode.ops = &software_node_ops; 798 - 799 - ida_init(&swnode->child_ids); 800 - INIT_LIST_HEAD(&swnode->entry); 801 - INIT_LIST_HEAD(&swnode->children); 802 - swnode->parent = p; 803 - 804 - if (p) 805 - list_add_tail(&swnode->entry, &p->children); 806 - 807 - ret = kobject_init_and_add(&swnode->kobj, &software_node_type, 808 - p ? &p->kobj : NULL, "node%d", swnode->id); 594 + ret = software_node_register_properties(node, properties); 809 595 if (ret) { 810 - kobject_put(&swnode->kobj); 596 + kfree(node); 811 597 return ERR_PTR(ret); 812 598 } 813 599 814 - ret = software_node_register_properties(swnode, properties); 815 - if (ret) { 816 - kobject_put(&swnode->kobj); 817 - return ERR_PTR(ret); 818 - } 600 + node->parent = p ? p->node : NULL; 819 601 820 - kobject_uevent(&swnode->kobj, KOBJ_ADD); 821 - return &swnode->fwnode; 602 + return swnode_register(node, p, 1); 822 603 } 823 604 EXPORT_SYMBOL_GPL(fwnode_create_software_node); 824 605 825 606 void fwnode_remove_software_node(struct fwnode_handle *fwnode) 826 607 { 827 - struct software_node *swnode = to_software_node(fwnode); 608 + struct swnode *swnode = to_swnode(fwnode); 828 609 829 610 if (!swnode) 830 611 return; 612 + 613 + if (swnode->parent) { 614 + ida_simple_remove(&swnode->parent->child_ids, swnode->id); 615 + list_del(&swnode->entry); 616 + } else { 617 + ida_simple_remove(&swnode_root_ids, swnode->id); 618 + } 831 619 832 620 kobject_put(&swnode->kobj); 833 621 } ··· 818 642 int software_node_notify(struct device *dev, unsigned long action) 819 643 { 820 644 struct fwnode_handle *fwnode = dev_fwnode(dev); 821 - struct software_node *swnode; 645 + struct swnode *swnode; 822 646 int ret; 823 647 824 648 if (!fwnode) ··· 829 653 if (!is_software_node(fwnode)) 830 654 return 0; 831 655 832 - swnode = to_software_node(fwnode); 656 + swnode = to_swnode(fwnode); 833 657 834 658 switch (action) { 835 659 case KOBJ_ADD:
+245 -48
drivers/platform/x86/intel_cht_int33fe.c
··· 21 21 #include <linux/i2c.h> 22 22 #include <linux/interrupt.h> 23 23 #include <linux/module.h> 24 + #include <linux/pci.h> 24 25 #include <linux/platform_device.h> 25 26 #include <linux/regulator/consumer.h> 26 27 #include <linux/slab.h> 28 + #include <linux/usb/pd.h> 27 29 28 30 #define EXPECTED_PTYPE 4 31 + 32 + enum { 33 + INT33FE_NODE_FUSB302, 34 + INT33FE_NODE_MAX17047, 35 + INT33FE_NODE_PI3USB30532, 36 + INT33FE_NODE_DISPLAYPORT, 37 + INT33FE_NODE_ROLE_SWITCH, 38 + INT33FE_NODE_USB_CONNECTOR, 39 + INT33FE_NODE_MAX, 40 + }; 29 41 30 42 struct cht_int33fe_data { 31 43 struct i2c_client *max17047; 32 44 struct i2c_client *fusb302; 33 45 struct i2c_client *pi3usb30532; 34 - /* Contain a list-head must be per device */ 35 - struct device_connection connections[4]; 46 + 47 + struct fwnode_handle *dp; 48 + struct fwnode_handle *mux; 49 + }; 50 + 51 + static const struct software_node nodes[]; 52 + 53 + static const struct software_node_ref_args pi3usb30532_ref = { 54 + &nodes[INT33FE_NODE_PI3USB30532] 55 + }; 56 + 57 + static const struct software_node_ref_args dp_ref = { 58 + &nodes[INT33FE_NODE_DISPLAYPORT] 59 + }; 60 + 61 + static struct software_node_ref_args mux_ref; 62 + 63 + static const struct software_node_reference usb_connector_refs[] = { 64 + { "orientation-switch", 1, &pi3usb30532_ref}, 65 + { "mode-switch", 1, &pi3usb30532_ref}, 66 + { "displayport", 1, &dp_ref}, 67 + { } 68 + }; 69 + 70 + static const struct software_node_reference fusb302_refs[] = { 71 + { "usb-role-switch", 1, &mux_ref}, 72 + { } 36 73 }; 37 74 38 75 /* ··· 100 63 return 1; 101 64 } 102 65 103 - static struct i2c_client *cht_int33fe_find_max17047(void) 104 - { 105 - struct i2c_client *max17047 = NULL; 106 - 107 - i2c_for_each_dev(&max17047, cht_int33fe_check_for_max17047); 108 - return max17047; 109 - } 110 - 111 66 static const char * const max17047_suppliers[] = { "bq24190-charger" }; 112 67 113 68 static const struct property_entry max17047_props[] = { ··· 109 80 110 81 static const struct property_entry fusb302_props[] = { 111 82 PROPERTY_ENTRY_STRING("linux,extcon-name", "cht_wcove_pwrsrc"), 112 - PROPERTY_ENTRY_U32("fcs,max-sink-microvolt", 12000000), 113 - PROPERTY_ENTRY_U32("fcs,max-sink-microamp", 3000000), 114 - PROPERTY_ENTRY_U32("fcs,max-sink-microwatt", 36000000), 115 83 { } 116 84 }; 85 + 86 + #define PDO_FIXED_FLAGS \ 87 + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM) 88 + 89 + static const u32 src_pdo[] = { 90 + PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), 91 + }; 92 + 93 + static const u32 snk_pdo[] = { 94 + PDO_FIXED(5000, 400, PDO_FIXED_FLAGS), 95 + PDO_VAR(5000, 12000, 3000), 96 + }; 97 + 98 + static const struct property_entry usb_connector_props[] = { 99 + PROPERTY_ENTRY_STRING("data-role", "dual"), 100 + PROPERTY_ENTRY_STRING("power-role", "dual"), 101 + PROPERTY_ENTRY_STRING("try-power-role", "sink"), 102 + PROPERTY_ENTRY_U32_ARRAY("source-pdos", src_pdo), 103 + PROPERTY_ENTRY_U32_ARRAY("sink-pdos", snk_pdo), 104 + PROPERTY_ENTRY_U32("op-sink-microwatt", 2500000), 105 + { } 106 + }; 107 + 108 + static const struct software_node nodes[] = { 109 + { "fusb302", NULL, fusb302_props, fusb302_refs }, 110 + { "max17047", NULL, max17047_props }, 111 + { "pi3usb30532" }, 112 + { "displayport" }, 113 + { "usb-role-switch" }, 114 + { "connector", &nodes[0], usb_connector_props, usb_connector_refs }, 115 + { } 116 + }; 117 + 118 + static int cht_int33fe_setup_mux(struct cht_int33fe_data *data) 119 + { 120 + struct fwnode_handle *fwnode; 121 + struct device *dev; 122 + struct device *p; 123 + 124 + fwnode = software_node_fwnode(&nodes[INT33FE_NODE_ROLE_SWITCH]); 125 + if (!fwnode) 126 + return -ENODEV; 127 + 128 + /* First finding the platform device */ 129 + p = bus_find_device_by_name(&platform_bus_type, NULL, 130 + "intel_xhci_usb_sw"); 131 + if (!p) 132 + return -EPROBE_DEFER; 133 + 134 + /* Then the mux child device */ 135 + dev = device_find_child_by_name(p, "intel_xhci_usb_sw-role-switch"); 136 + put_device(p); 137 + if (!dev) 138 + return -EPROBE_DEFER; 139 + 140 + /* If there already is a node for the mux, using that one. */ 141 + if (dev->fwnode) 142 + fwnode_remove_software_node(fwnode); 143 + else 144 + dev->fwnode = fwnode; 145 + 146 + data->mux = fwnode_handle_get(dev->fwnode); 147 + put_device(dev); 148 + mux_ref.node = to_software_node(data->mux); 149 + 150 + return 0; 151 + } 152 + 153 + static int cht_int33fe_setup_dp(struct cht_int33fe_data *data) 154 + { 155 + struct fwnode_handle *fwnode; 156 + struct pci_dev *pdev; 157 + 158 + fwnode = software_node_fwnode(&nodes[INT33FE_NODE_DISPLAYPORT]); 159 + if (!fwnode) 160 + return -ENODEV; 161 + 162 + /* First let's find the GPU PCI device */ 163 + pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL); 164 + if (!pdev || pdev->vendor != PCI_VENDOR_ID_INTEL) { 165 + pci_dev_put(pdev); 166 + return -ENODEV; 167 + } 168 + 169 + /* Then the DP child device node */ 170 + data->dp = device_get_named_child_node(&pdev->dev, "DD02"); 171 + pci_dev_put(pdev); 172 + if (!data->dp) 173 + return -ENODEV; 174 + 175 + fwnode->secondary = ERR_PTR(-ENODEV); 176 + data->dp->secondary = fwnode; 177 + 178 + return 0; 179 + } 180 + 181 + static void cht_int33fe_remove_nodes(struct cht_int33fe_data *data) 182 + { 183 + software_node_unregister_nodes(nodes); 184 + 185 + if (data->mux) { 186 + fwnode_handle_put(data->mux); 187 + mux_ref.node = NULL; 188 + data->mux = NULL; 189 + } 190 + 191 + if (data->dp) { 192 + data->dp->secondary = NULL; 193 + fwnode_handle_put(data->dp); 194 + data->dp = NULL; 195 + } 196 + } 197 + 198 + static int cht_int33fe_add_nodes(struct cht_int33fe_data *data) 199 + { 200 + int ret; 201 + 202 + ret = software_node_register_nodes(nodes); 203 + if (ret) 204 + return ret; 205 + 206 + /* The devices that are not created in this driver need extra steps. */ 207 + 208 + /* 209 + * There is no ACPI device node for the USB role mux, so we need to find 210 + * the mux device and assign our node directly to it. That means we 211 + * depend on the mux driver. This function will return -PROBE_DEFER 212 + * until the mux device is registered. 213 + */ 214 + ret = cht_int33fe_setup_mux(data); 215 + if (ret) 216 + goto err_remove_nodes; 217 + 218 + /* 219 + * The DP connector does have ACPI device node. In this case we can just 220 + * find that ACPI node and assign our node as the secondary node to it. 221 + */ 222 + ret = cht_int33fe_setup_dp(data); 223 + if (ret) 224 + goto err_remove_nodes; 225 + 226 + return 0; 227 + 228 + err_remove_nodes: 229 + cht_int33fe_remove_nodes(data); 230 + 231 + return ret; 232 + } 233 + 234 + static int 235 + cht_int33fe_register_max17047(struct device *dev, struct cht_int33fe_data *data) 236 + { 237 + struct i2c_client *max17047 = NULL; 238 + struct i2c_board_info board_info; 239 + struct fwnode_handle *fwnode; 240 + int ret; 241 + 242 + fwnode = software_node_fwnode(&nodes[INT33FE_NODE_MAX17047]); 243 + if (!fwnode) 244 + return -ENODEV; 245 + 246 + i2c_for_each_dev(&max17047, cht_int33fe_check_for_max17047); 247 + if (max17047) { 248 + /* Pre-existing i2c-client for the max17047, add device-props */ 249 + fwnode->secondary = ERR_PTR(-ENODEV); 250 + max17047->dev.fwnode->secondary = fwnode; 251 + /* And re-probe to get the new device-props applied. */ 252 + ret = device_reprobe(&max17047->dev); 253 + if (ret) 254 + dev_warn(dev, "Reprobing max17047 error: %d\n", ret); 255 + return 0; 256 + } 257 + 258 + memset(&board_info, 0, sizeof(board_info)); 259 + strlcpy(board_info.type, "max17047", I2C_NAME_SIZE); 260 + board_info.dev_name = "max17047"; 261 + board_info.fwnode = fwnode; 262 + data->max17047 = i2c_acpi_new_device(dev, 1, &board_info); 263 + 264 + return PTR_ERR_OR_ZERO(data->max17047); 265 + } 117 266 118 267 static int cht_int33fe_probe(struct platform_device *pdev) 119 268 { 120 269 struct device *dev = &pdev->dev; 121 270 struct i2c_board_info board_info; 122 271 struct cht_int33fe_data *data; 123 - struct i2c_client *max17047; 272 + struct fwnode_handle *fwnode; 124 273 struct regulator *regulator; 125 274 unsigned long long ptyp; 126 275 acpi_status status; ··· 358 151 if (!data) 359 152 return -ENOMEM; 360 153 361 - /* Work around BIOS bug, see comment on cht_int33fe_find_max17047 */ 362 - max17047 = cht_int33fe_find_max17047(); 363 - if (max17047) { 364 - /* Pre-existing i2c-client for the max17047, add device-props */ 365 - ret = device_add_properties(&max17047->dev, max17047_props); 366 - if (ret) 367 - return ret; 368 - /* And re-probe to get the new device-props applied. */ 369 - ret = device_reprobe(&max17047->dev); 370 - if (ret) 371 - dev_warn(dev, "Reprobing max17047 error: %d\n", ret); 372 - } else { 373 - memset(&board_info, 0, sizeof(board_info)); 374 - strlcpy(board_info.type, "max17047", I2C_NAME_SIZE); 375 - board_info.dev_name = "max17047"; 376 - board_info.properties = max17047_props; 377 - data->max17047 = i2c_acpi_new_device(dev, 1, &board_info); 378 - if (IS_ERR(data->max17047)) 379 - return PTR_ERR(data->max17047); 154 + ret = cht_int33fe_add_nodes(data); 155 + if (ret) 156 + return ret; 157 + 158 + /* Work around BIOS bug, see comment on cht_int33fe_check_for_max17047 */ 159 + ret = cht_int33fe_register_max17047(dev, data); 160 + if (ret) 161 + goto out_remove_nodes; 162 + 163 + fwnode = software_node_fwnode(&nodes[INT33FE_NODE_FUSB302]); 164 + if (!fwnode) { 165 + ret = -ENODEV; 166 + goto out_unregister_max17047; 380 167 } 381 - 382 - data->connections[0].endpoint[0] = "port0"; 383 - data->connections[0].endpoint[1] = "i2c-pi3usb30532"; 384 - data->connections[0].id = "orientation-switch"; 385 - data->connections[1].endpoint[0] = "port0"; 386 - data->connections[1].endpoint[1] = "i2c-pi3usb30532"; 387 - data->connections[1].id = "mode-switch"; 388 - data->connections[2].endpoint[0] = "i2c-fusb302"; 389 - data->connections[2].endpoint[1] = "intel_xhci_usb_sw-role-switch"; 390 - data->connections[2].id = "usb-role-switch"; 391 - 392 - device_connections_add(data->connections); 393 168 394 169 memset(&board_info, 0, sizeof(board_info)); 395 170 strlcpy(board_info.type, "typec_fusb302", I2C_NAME_SIZE); 396 171 board_info.dev_name = "fusb302"; 397 - board_info.properties = fusb302_props; 172 + board_info.fwnode = fwnode; 398 173 board_info.irq = fusb302_irq; 399 174 400 175 data->fusb302 = i2c_acpi_new_device(dev, 2, &board_info); ··· 385 196 goto out_unregister_max17047; 386 197 } 387 198 199 + fwnode = software_node_fwnode(&nodes[INT33FE_NODE_PI3USB30532]); 200 + if (!fwnode) { 201 + ret = -ENODEV; 202 + goto out_unregister_fusb302; 203 + } 204 + 388 205 memset(&board_info, 0, sizeof(board_info)); 389 206 board_info.dev_name = "pi3usb30532"; 207 + board_info.fwnode = fwnode; 390 208 strlcpy(board_info.type, "pi3usb30532", I2C_NAME_SIZE); 391 209 392 210 data->pi3usb30532 = i2c_acpi_new_device(dev, 3, &board_info); ··· 412 216 out_unregister_max17047: 413 217 i2c_unregister_device(data->max17047); 414 218 415 - device_connections_remove(data->connections); 219 + out_remove_nodes: 220 + cht_int33fe_remove_nodes(data); 416 221 417 222 return ret; 418 223 } ··· 426 229 i2c_unregister_device(data->fusb302); 427 230 i2c_unregister_device(data->max17047); 428 231 429 - device_connections_remove(data->connections); 232 + cht_int33fe_remove_nodes(data); 430 233 431 234 return 0; 432 235 }
+1 -1
drivers/usb/roles/class.c
··· 101 101 struct device *dev; 102 102 103 103 if (con->fwnode) { 104 - if (!fwnode_property_present(con->fwnode, con->id)) 104 + if (con->id && !fwnode_property_present(con->fwnode, con->id)) 105 105 return NULL; 106 106 107 107 dev = class_find_device(role_class, NULL, con->fwnode,
+15
drivers/usb/typec/bus.h
··· 35 35 #define is_typec_altmode(_dev_) (_dev_->type == &typec_altmode_dev_type) 36 36 #define is_typec_port(_dev_) (_dev_->type == &typec_port_dev_type) 37 37 38 + extern struct class typec_mux_class; 39 + 40 + struct typec_switch { 41 + struct device dev; 42 + typec_switch_set_fn_t set; 43 + }; 44 + 45 + struct typec_mux { 46 + struct device dev; 47 + typec_mux_set_fn_t set; 48 + }; 49 + 50 + #define to_typec_switch(_dev_) container_of(_dev_, struct typec_switch, dev) 51 + #define to_typec_mux(_dev_) container_of(_dev_, struct typec_mux, dev) 52 + 38 53 #endif /* __USB_TYPEC_ALTMODE_H__ */
+15 -2
drivers/usb/typec/class.c
··· 1646 1646 if (ret) 1647 1647 return ret; 1648 1648 1649 + ret = class_register(&typec_mux_class); 1650 + if (ret) 1651 + goto err_unregister_bus; 1652 + 1649 1653 typec_class = class_create(THIS_MODULE, "typec"); 1650 1654 if (IS_ERR(typec_class)) { 1651 - bus_unregister(&typec_bus); 1652 - return PTR_ERR(typec_class); 1655 + ret = PTR_ERR(typec_class); 1656 + goto err_unregister_mux_class; 1653 1657 } 1654 1658 1655 1659 return 0; 1660 + 1661 + err_unregister_mux_class: 1662 + class_unregister(&typec_mux_class); 1663 + 1664 + err_unregister_bus: 1665 + bus_unregister(&typec_bus); 1666 + 1667 + return ret; 1656 1668 } 1657 1669 subsys_initcall(typec_init); 1658 1670 ··· 1673 1661 class_destroy(typec_class); 1674 1662 ida_destroy(&typec_index_ida); 1675 1663 bus_unregister(&typec_bus); 1664 + class_unregister(&typec_mux_class); 1676 1665 } 1677 1666 module_exit(typec_exit); 1678 1667
+172 -66
drivers/usb/typec/mux.c
··· 15 15 #include <linux/slab.h> 16 16 #include <linux/usb/typec_mux.h> 17 17 18 - static DEFINE_MUTEX(switch_lock); 19 - static DEFINE_MUTEX(mux_lock); 20 - static LIST_HEAD(switch_list); 21 - static LIST_HEAD(mux_list); 18 + #include "bus.h" 19 + 20 + static int name_match(struct device *dev, const void *name) 21 + { 22 + return !strcmp((const char *)name, dev_name(dev)); 23 + } 24 + 25 + static bool dev_name_ends_with(struct device *dev, const char *suffix) 26 + { 27 + const char *name = dev_name(dev); 28 + const int name_len = strlen(name); 29 + const int suffix_len = strlen(suffix); 30 + 31 + if (suffix_len > name_len) 32 + return false; 33 + 34 + return strcmp(name + (name_len - suffix_len), suffix) == 0; 35 + } 36 + 37 + static int switch_fwnode_match(struct device *dev, const void *fwnode) 38 + { 39 + return dev_fwnode(dev) == fwnode && dev_name_ends_with(dev, "-switch"); 40 + } 22 41 23 42 static void *typec_switch_match(struct device_connection *con, int ep, 24 43 void *data) 25 44 { 26 - struct typec_switch *sw; 45 + struct device *dev; 27 46 28 - if (!con->fwnode) { 29 - list_for_each_entry(sw, &switch_list, entry) 30 - if (!strcmp(con->endpoint[ep], dev_name(sw->dev))) 31 - return sw; 32 - return ERR_PTR(-EPROBE_DEFER); 47 + if (con->fwnode) { 48 + if (con->id && !fwnode_property_present(con->fwnode, con->id)) 49 + return NULL; 50 + 51 + dev = class_find_device(&typec_mux_class, NULL, con->fwnode, 52 + switch_fwnode_match); 53 + } else { 54 + dev = class_find_device(&typec_mux_class, NULL, 55 + con->endpoint[ep], name_match); 33 56 } 34 57 35 - /* 36 - * With OF graph the mux node must have a boolean device property named 37 - * "orientation-switch". 38 - */ 39 - if (con->id && !fwnode_property_present(con->fwnode, con->id)) 40 - return NULL; 41 - 42 - list_for_each_entry(sw, &switch_list, entry) 43 - if (dev_fwnode(sw->dev) == con->fwnode) 44 - return sw; 45 - 46 - return con->id ? ERR_PTR(-EPROBE_DEFER) : NULL; 58 + return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER); 47 59 } 48 60 49 61 /** ··· 71 59 { 72 60 struct typec_switch *sw; 73 61 74 - mutex_lock(&switch_lock); 75 62 sw = device_connection_find_match(dev, "orientation-switch", NULL, 76 63 typec_switch_match); 77 - if (!IS_ERR_OR_NULL(sw)) { 78 - WARN_ON(!try_module_get(sw->dev->driver->owner)); 79 - get_device(sw->dev); 80 - } 81 - mutex_unlock(&switch_lock); 64 + if (!IS_ERR_OR_NULL(sw)) 65 + WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); 82 66 83 67 return sw; 84 68 } ··· 89 81 void typec_switch_put(struct typec_switch *sw) 90 82 { 91 83 if (!IS_ERR_OR_NULL(sw)) { 92 - module_put(sw->dev->driver->owner); 93 - put_device(sw->dev); 84 + module_put(sw->dev.parent->driver->owner); 85 + put_device(&sw->dev); 94 86 } 95 87 } 96 88 EXPORT_SYMBOL_GPL(typec_switch_put); 97 89 90 + static void typec_switch_release(struct device *dev) 91 + { 92 + kfree(to_typec_switch(dev)); 93 + } 94 + 95 + static const struct device_type typec_switch_dev_type = { 96 + .name = "orientation_switch", 97 + .release = typec_switch_release, 98 + }; 99 + 98 100 /** 99 101 * typec_switch_register - Register USB Type-C orientation switch 100 - * @sw: USB Type-C orientation switch 102 + * @parent: Parent device 103 + * @desc: Orientation switch description 101 104 * 102 105 * This function registers a switch that can be used for routing the correct 103 106 * data pairs depending on the cable plug orientation from the USB Type-C 104 107 * connector to the USB controllers. USB Type-C plugs can be inserted 105 108 * right-side-up or upside-down. 106 109 */ 107 - int typec_switch_register(struct typec_switch *sw) 110 + struct typec_switch * 111 + typec_switch_register(struct device *parent, 112 + const struct typec_switch_desc *desc) 108 113 { 109 - mutex_lock(&switch_lock); 110 - list_add_tail(&sw->entry, &switch_list); 111 - mutex_unlock(&switch_lock); 114 + struct typec_switch *sw; 115 + int ret; 112 116 113 - return 0; 117 + if (!desc || !desc->set) 118 + return ERR_PTR(-EINVAL); 119 + 120 + sw = kzalloc(sizeof(*sw), GFP_KERNEL); 121 + if (!sw) 122 + return ERR_PTR(-ENOMEM); 123 + 124 + sw->set = desc->set; 125 + 126 + device_initialize(&sw->dev); 127 + sw->dev.parent = parent; 128 + sw->dev.fwnode = desc->fwnode; 129 + sw->dev.class = &typec_mux_class; 130 + sw->dev.type = &typec_switch_dev_type; 131 + sw->dev.driver_data = desc->drvdata; 132 + dev_set_name(&sw->dev, "%s-switch", dev_name(parent)); 133 + 134 + ret = device_add(&sw->dev); 135 + if (ret) { 136 + dev_err(parent, "failed to register switch (%d)\n", ret); 137 + put_device(&sw->dev); 138 + return ERR_PTR(ret); 139 + } 140 + 141 + return sw; 114 142 } 115 143 EXPORT_SYMBOL_GPL(typec_switch_register); 116 144 ··· 158 114 */ 159 115 void typec_switch_unregister(struct typec_switch *sw) 160 116 { 161 - mutex_lock(&switch_lock); 162 - list_del(&sw->entry); 163 - mutex_unlock(&switch_lock); 117 + if (!IS_ERR_OR_NULL(sw)) 118 + device_unregister(&sw->dev); 164 119 } 165 120 EXPORT_SYMBOL_GPL(typec_switch_unregister); 166 121 122 + void typec_switch_set_drvdata(struct typec_switch *sw, void *data) 123 + { 124 + dev_set_drvdata(&sw->dev, data); 125 + } 126 + EXPORT_SYMBOL_GPL(typec_switch_set_drvdata); 127 + 128 + void *typec_switch_get_drvdata(struct typec_switch *sw) 129 + { 130 + return dev_get_drvdata(&sw->dev); 131 + } 132 + EXPORT_SYMBOL_GPL(typec_switch_get_drvdata); 133 + 167 134 /* ------------------------------------------------------------------------- */ 135 + 136 + static int mux_fwnode_match(struct device *dev, const void *fwnode) 137 + { 138 + return dev_fwnode(dev) == fwnode && dev_name_ends_with(dev, "-mux"); 139 + } 168 140 169 141 static void *typec_mux_match(struct device_connection *con, int ep, void *data) 170 142 { 171 143 const struct typec_altmode_desc *desc = data; 172 - struct typec_mux *mux; 173 - int nval; 144 + struct device *dev; 174 145 bool match; 146 + int nval; 175 147 u16 *val; 176 148 int i; 177 149 178 150 if (!con->fwnode) { 179 - list_for_each_entry(mux, &mux_list, entry) 180 - if (!strcmp(con->endpoint[ep], dev_name(mux->dev))) 181 - return mux; 182 - return ERR_PTR(-EPROBE_DEFER); 151 + dev = class_find_device(&typec_mux_class, NULL, 152 + con->endpoint[ep], name_match); 153 + 154 + return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER); 183 155 } 184 156 185 157 /* ··· 240 180 return NULL; 241 181 242 182 find_mux: 243 - list_for_each_entry(mux, &mux_list, entry) 244 - if (dev_fwnode(mux->dev) == con->fwnode) 245 - return mux; 183 + dev = class_find_device(&typec_mux_class, NULL, con->fwnode, 184 + mux_fwnode_match); 246 185 247 - return ERR_PTR(-EPROBE_DEFER); 186 + return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER); 248 187 } 249 188 250 189 /** ··· 261 202 { 262 203 struct typec_mux *mux; 263 204 264 - mutex_lock(&mux_lock); 265 205 mux = device_connection_find_match(dev, "mode-switch", (void *)desc, 266 206 typec_mux_match); 267 - if (!IS_ERR_OR_NULL(mux)) { 268 - WARN_ON(!try_module_get(mux->dev->driver->owner)); 269 - get_device(mux->dev); 270 - } 271 - mutex_unlock(&mux_lock); 207 + if (!IS_ERR_OR_NULL(mux)) 208 + WARN_ON(!try_module_get(mux->dev.parent->driver->owner)); 272 209 273 210 return mux; 274 211 } ··· 279 224 void typec_mux_put(struct typec_mux *mux) 280 225 { 281 226 if (!IS_ERR_OR_NULL(mux)) { 282 - module_put(mux->dev->driver->owner); 283 - put_device(mux->dev); 227 + module_put(mux->dev.parent->driver->owner); 228 + put_device(&mux->dev); 284 229 } 285 230 } 286 231 EXPORT_SYMBOL_GPL(typec_mux_put); 287 232 233 + static void typec_mux_release(struct device *dev) 234 + { 235 + kfree(to_typec_mux(dev)); 236 + } 237 + 238 + static const struct device_type typec_mux_dev_type = { 239 + .name = "mode_switch", 240 + .release = typec_mux_release, 241 + }; 242 + 288 243 /** 289 244 * typec_mux_register - Register Multiplexer routing USB Type-C pins 290 - * @mux: USB Type-C Connector Multiplexer/DeMultiplexer 245 + * @parent: Parent device 246 + * @desc: Multiplexer description 291 247 * 292 248 * USB Type-C connectors can be used for alternate modes of operation besides 293 249 * USB when Accessory/Alternate Modes are supported. With some of those modes, 294 250 * the pins on the connector need to be reconfigured. This function registers 295 251 * multiplexer switches routing the pins on the connector. 296 252 */ 297 - int typec_mux_register(struct typec_mux *mux) 253 + struct typec_mux * 254 + typec_mux_register(struct device *parent, const struct typec_mux_desc *desc) 298 255 { 299 - mutex_lock(&mux_lock); 300 - list_add_tail(&mux->entry, &mux_list); 301 - mutex_unlock(&mux_lock); 256 + struct typec_mux *mux; 257 + int ret; 302 258 303 - return 0; 259 + if (!desc || !desc->set) 260 + return ERR_PTR(-EINVAL); 261 + 262 + mux = kzalloc(sizeof(*mux), GFP_KERNEL); 263 + if (!mux) 264 + return ERR_PTR(-ENOMEM); 265 + 266 + mux->set = desc->set; 267 + 268 + device_initialize(&mux->dev); 269 + mux->dev.parent = parent; 270 + mux->dev.fwnode = desc->fwnode; 271 + mux->dev.class = &typec_mux_class; 272 + mux->dev.type = &typec_mux_dev_type; 273 + mux->dev.driver_data = desc->drvdata; 274 + dev_set_name(&mux->dev, "%s-mux", dev_name(parent)); 275 + 276 + ret = device_add(&mux->dev); 277 + if (ret) { 278 + dev_err(parent, "failed to register mux (%d)\n", ret); 279 + put_device(&mux->dev); 280 + return ERR_PTR(ret); 281 + } 282 + 283 + return mux; 304 284 } 305 285 EXPORT_SYMBOL_GPL(typec_mux_register); 306 286 ··· 347 257 */ 348 258 void typec_mux_unregister(struct typec_mux *mux) 349 259 { 350 - mutex_lock(&mux_lock); 351 - list_del(&mux->entry); 352 - mutex_unlock(&mux_lock); 260 + if (!IS_ERR_OR_NULL(mux)) 261 + device_unregister(&mux->dev); 353 262 } 354 263 EXPORT_SYMBOL_GPL(typec_mux_unregister); 264 + 265 + void typec_mux_set_drvdata(struct typec_mux *mux, void *data) 266 + { 267 + dev_set_drvdata(&mux->dev, data); 268 + } 269 + EXPORT_SYMBOL_GPL(typec_mux_set_drvdata); 270 + 271 + void *typec_mux_get_drvdata(struct typec_mux *mux) 272 + { 273 + return dev_get_drvdata(&mux->dev); 274 + } 275 + EXPORT_SYMBOL_GPL(typec_mux_get_drvdata); 276 + 277 + struct class typec_mux_class = { 278 + .name = "typec_mux", 279 + .owner = THIS_MODULE, 280 + };
+27 -19
drivers/usb/typec/mux/pi3usb30532.c
··· 23 23 struct pi3usb30532 { 24 24 struct i2c_client *client; 25 25 struct mutex lock; /* protects the cached conf register */ 26 - struct typec_switch sw; 27 - struct typec_mux mux; 26 + struct typec_switch *sw; 27 + struct typec_mux *mux; 28 28 u8 conf; 29 29 }; 30 30 ··· 48 48 static int pi3usb30532_sw_set(struct typec_switch *sw, 49 49 enum typec_orientation orientation) 50 50 { 51 - struct pi3usb30532 *pi = container_of(sw, struct pi3usb30532, sw); 51 + struct pi3usb30532 *pi = typec_switch_get_drvdata(sw); 52 52 u8 new_conf; 53 53 int ret; 54 54 ··· 75 75 76 76 static int pi3usb30532_mux_set(struct typec_mux *mux, int state) 77 77 { 78 - struct pi3usb30532 *pi = container_of(mux, struct pi3usb30532, mux); 78 + struct pi3usb30532 *pi = typec_mux_get_drvdata(mux); 79 79 u8 new_conf; 80 80 int ret; 81 81 ··· 113 113 static int pi3usb30532_probe(struct i2c_client *client) 114 114 { 115 115 struct device *dev = &client->dev; 116 + struct typec_switch_desc sw_desc; 117 + struct typec_mux_desc mux_desc; 116 118 struct pi3usb30532 *pi; 117 119 int ret; 118 120 ··· 123 121 return -ENOMEM; 124 122 125 123 pi->client = client; 126 - pi->sw.dev = dev; 127 - pi->sw.set = pi3usb30532_sw_set; 128 - pi->mux.dev = dev; 129 - pi->mux.set = pi3usb30532_mux_set; 130 124 mutex_init(&pi->lock); 131 125 132 126 ret = i2c_smbus_read_byte_data(client, PI3USB30532_CONF); ··· 132 134 } 133 135 pi->conf = ret; 134 136 135 - ret = typec_switch_register(&pi->sw); 136 - if (ret) { 137 - dev_err(dev, "Error registering typec switch: %d\n", ret); 138 - return ret; 137 + sw_desc.drvdata = pi; 138 + sw_desc.fwnode = dev->fwnode; 139 + sw_desc.set = pi3usb30532_sw_set; 140 + 141 + pi->sw = typec_switch_register(dev, &sw_desc); 142 + if (IS_ERR(pi->sw)) { 143 + dev_err(dev, "Error registering typec switch: %ld\n", 144 + PTR_ERR(pi->sw)); 145 + return PTR_ERR(pi->sw); 139 146 } 140 147 141 - ret = typec_mux_register(&pi->mux); 142 - if (ret) { 143 - typec_switch_unregister(&pi->sw); 144 - dev_err(dev, "Error registering typec mux: %d\n", ret); 145 - return ret; 148 + mux_desc.drvdata = pi; 149 + mux_desc.fwnode = dev->fwnode; 150 + mux_desc.set = pi3usb30532_mux_set; 151 + 152 + pi->mux = typec_mux_register(dev, &mux_desc); 153 + if (IS_ERR(pi->mux)) { 154 + typec_switch_unregister(pi->sw); 155 + dev_err(dev, "Error registering typec mux: %ld\n", 156 + PTR_ERR(pi->mux)); 157 + return PTR_ERR(pi->mux); 146 158 } 147 159 148 160 i2c_set_clientdata(client, pi); ··· 163 155 { 164 156 struct pi3usb30532 *pi = i2c_get_clientdata(client); 165 157 166 - typec_mux_unregister(&pi->mux); 167 - typec_switch_unregister(&pi->sw); 158 + typec_mux_unregister(pi->mux); 159 + typec_switch_unregister(pi->sw); 168 160 return 0; 169 161 } 170 162
+2
include/linux/device.h
··· 1255 1255 int (*fn)(struct device *dev, void *data)); 1256 1256 extern struct device *device_find_child(struct device *dev, void *data, 1257 1257 int (*match)(struct device *dev, void *data)); 1258 + extern struct device *device_find_child_by_name(struct device *parent, 1259 + const char *name); 1258 1260 extern int device_rename(struct device *dev, const char *new_name); 1259 1261 extern int device_move(struct device *dev, struct device *new_parent, 1260 1262 enum dpm_order dpm_order);
+95
include/linux/property.h
··· 76 76 unsigned int nargs, unsigned int index, 77 77 struct fwnode_reference_args *args); 78 78 79 + struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode, 80 + const char *name, 81 + unsigned int index); 82 + 79 83 struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode); 80 84 struct fwnode_handle *fwnode_get_next_parent( 81 85 struct fwnode_handle *fwnode); ··· 145 141 return device_property_read_u64_array(dev, propname, val, 1); 146 142 } 147 143 144 + static inline int device_property_count_u8(struct device *dev, const char *propname) 145 + { 146 + return device_property_read_u8_array(dev, propname, NULL, 0); 147 + } 148 + 149 + static inline int device_property_count_u16(struct device *dev, const char *propname) 150 + { 151 + return device_property_read_u16_array(dev, propname, NULL, 0); 152 + } 153 + 154 + static inline int device_property_count_u32(struct device *dev, const char *propname) 155 + { 156 + return device_property_read_u32_array(dev, propname, NULL, 0); 157 + } 158 + 159 + static inline int device_property_count_u64(struct device *dev, const char *propname) 160 + { 161 + return device_property_read_u64_array(dev, propname, NULL, 0); 162 + } 163 + 148 164 static inline bool fwnode_property_read_bool(const struct fwnode_handle *fwnode, 149 165 const char *propname) 150 166 { ··· 193 169 const char *propname, u64 *val) 194 170 { 195 171 return fwnode_property_read_u64_array(fwnode, propname, val, 1); 172 + } 173 + 174 + static inline int fwnode_property_count_u8(const struct fwnode_handle *fwnode, 175 + const char *propname) 176 + { 177 + return fwnode_property_read_u8_array(fwnode, propname, NULL, 0); 178 + } 179 + 180 + static inline int fwnode_property_count_u16(const struct fwnode_handle *fwnode, 181 + const char *propname) 182 + { 183 + return fwnode_property_read_u16_array(fwnode, propname, NULL, 0); 184 + } 185 + 186 + static inline int fwnode_property_count_u32(const struct fwnode_handle *fwnode, 187 + const char *propname) 188 + { 189 + return fwnode_property_read_u32_array(fwnode, propname, NULL, 0); 190 + } 191 + 192 + static inline int fwnode_property_count_u64(const struct fwnode_handle *fwnode, 193 + const char *propname) 194 + { 195 + return fwnode_property_read_u64_array(fwnode, propname, NULL, 0); 196 196 } 197 197 198 198 /** ··· 377 329 /* -------------------------------------------------------------------------- */ 378 330 /* Software fwnode support - when HW description is incomplete or missing */ 379 331 332 + struct software_node; 333 + 334 + /** 335 + * struct software_node_ref_args - Reference with additional arguments 336 + * @node: Reference to a software node 337 + * @nargs: Number of elements in @args array 338 + * @args: Integer arguments 339 + */ 340 + struct software_node_ref_args { 341 + const struct software_node *node; 342 + unsigned int nargs; 343 + u64 args[NR_FWNODE_REFERENCE_ARGS]; 344 + }; 345 + 346 + /** 347 + * struct software_node_reference - Named software node reference property 348 + * @name: Name of the property 349 + * @nrefs: Number of elements in @refs array 350 + * @refs: Array of references with optional arguments 351 + */ 352 + struct software_node_reference { 353 + const char *name; 354 + unsigned int nrefs; 355 + const struct software_node_ref_args *refs; 356 + }; 357 + 358 + /** 359 + * struct software_node - Software node description 360 + * @name: Name of the software node 361 + * @parent: Parent of the software node 362 + * @properties: Array of device properties 363 + * @references: Array of software node reference properties 364 + */ 365 + struct software_node { 366 + const char *name; 367 + const struct software_node *parent; 368 + const struct property_entry *properties; 369 + const struct software_node_reference *references; 370 + }; 371 + 380 372 bool is_software_node(const struct fwnode_handle *fwnode); 373 + const struct software_node *to_software_node(struct fwnode_handle *fwnode); 374 + struct fwnode_handle *software_node_fwnode(const struct software_node *node); 375 + 376 + int software_node_register_nodes(const struct software_node *nodes); 377 + void software_node_unregister_nodes(const struct software_node *nodes); 378 + 379 + int software_node_register(const struct software_node *node); 381 380 382 381 int software_node_notify(struct device *dev, unsigned long action); 383 382
+28 -34
include/linux/usb/typec_mux.h
··· 3 3 #ifndef __USB_TYPEC_MUX 4 4 #define __USB_TYPEC_MUX 5 5 6 - #include <linux/list.h> 7 6 #include <linux/usb/typec.h> 8 7 9 8 struct device; 9 + struct typec_mux; 10 + struct typec_switch; 11 + struct fwnode_handle; 10 12 11 - /** 12 - * struct typec_switch - USB Type-C cable orientation switch 13 - * @dev: Switch device 14 - * @entry: List entry 15 - * @set: Callback to the driver for setting the orientation 16 - * 17 - * USB Type-C pin flipper switch routing the correct data pairs from the 18 - * connector to the USB controller depending on the orientation of the cable 19 - * plug. 20 - */ 21 - struct typec_switch { 22 - struct device *dev; 23 - struct list_head entry; 13 + typedef int (*typec_switch_set_fn_t)(struct typec_switch *sw, 14 + enum typec_orientation orientation); 24 15 25 - int (*set)(struct typec_switch *sw, enum typec_orientation orientation); 26 - }; 27 - 28 - /** 29 - * struct typec_switch - USB Type-C connector pin mux 30 - * @dev: Mux device 31 - * @entry: List entry 32 - * @set: Callback to the driver for setting the state of the mux 33 - * 34 - * Pin Multiplexer/DeMultiplexer switch routing the USB Type-C connector pins to 35 - * different components depending on the requested mode of operation. Used with 36 - * Accessory/Alternate modes. 37 - */ 38 - struct typec_mux { 39 - struct device *dev; 40 - struct list_head entry; 41 - 42 - int (*set)(struct typec_mux *mux, int state); 16 + struct typec_switch_desc { 17 + struct fwnode_handle *fwnode; 18 + typec_switch_set_fn_t set; 19 + void *drvdata; 43 20 }; 44 21 45 22 struct typec_switch *typec_switch_get(struct device *dev); 46 23 void typec_switch_put(struct typec_switch *sw); 47 - int typec_switch_register(struct typec_switch *sw); 24 + struct typec_switch * 25 + typec_switch_register(struct device *parent, 26 + const struct typec_switch_desc *desc); 48 27 void typec_switch_unregister(struct typec_switch *sw); 28 + 29 + void typec_switch_set_drvdata(struct typec_switch *sw, void *data); 30 + void *typec_switch_get_drvdata(struct typec_switch *sw); 31 + 32 + typedef int (*typec_mux_set_fn_t)(struct typec_mux *mux, int state); 33 + 34 + struct typec_mux_desc { 35 + struct fwnode_handle *fwnode; 36 + typec_mux_set_fn_t set; 37 + void *drvdata; 38 + }; 49 39 50 40 struct typec_mux * 51 41 typec_mux_get(struct device *dev, const struct typec_altmode_desc *desc); 52 42 void typec_mux_put(struct typec_mux *mux); 53 - int typec_mux_register(struct typec_mux *mux); 43 + struct typec_mux * 44 + typec_mux_register(struct device *parent, const struct typec_mux_desc *desc); 54 45 void typec_mux_unregister(struct typec_mux *mux); 46 + 47 + void typec_mux_set_drvdata(struct typec_mux *mux, void *data); 48 + void *typec_mux_get_drvdata(struct typec_mux *mux); 55 49 56 50 #endif /* __USB_TYPEC_MUX */