1 // SPDX-License-Identifier: GPL-2.0
3 * USB Type-C Connector Class Port Mapping Utility
5 * Copyright (C) 2021, Intel Corporation
9 #include <linux/acpi.h>
10 #include <linux/component.h>
14 static int typec_aggregate_bind(struct device *dev)
16 return component_bind_all(dev, NULL);
19 static void typec_aggregate_unbind(struct device *dev)
21 component_unbind_all(dev, NULL);
24 static const struct component_master_ops typec_aggregate_ops = {
25 .bind = typec_aggregate_bind,
26 .unbind = typec_aggregate_unbind,
29 struct each_port_arg {
30 struct typec_port *port;
31 struct component_match *match;
34 static int typec_port_compare(struct device *dev, void *fwnode)
36 return device_match_fwnode(dev, fwnode);
39 static int typec_port_match(struct device *dev, void *data)
41 struct acpi_device *adev = to_acpi_device(dev);
42 struct each_port_arg *arg = data;
43 struct acpi_device *con_adev;
45 con_adev = ACPI_COMPANION(&arg->port->dev);
49 if (con_adev->pld_crc == adev->pld_crc)
50 component_match_add(&arg->port->dev, &arg->match, typec_port_compare,
51 acpi_fwnode_handle(adev));
55 int typec_link_ports(struct typec_port *con)
57 struct each_port_arg arg = { .port = con, .match = NULL };
59 if (!has_acpi_companion(&con->dev))
62 acpi_bus_for_each_dev(typec_port_match, &arg);
67 * REVISIT: Now each connector can have only a single component master.
68 * So far only the USB ports connected to the USB Type-C connector share
69 * the _PLD with it, but if there one day is something else (like maybe
70 * the DisplayPort ACPI device object) that also shares the _PLD with
71 * the connector, every one of those needs to have its own component
72 * master, because each different type of component needs to be bind to
73 * the connector independently of the other components. That requires
74 * improvements to the component framework. Right now you can only have
75 * one master per device.
77 return component_master_add_with_match(&con->dev, &typec_aggregate_ops, arg.match);
80 void typec_unlink_ports(struct typec_port *con)
82 if (has_acpi_companion(&con->dev))
83 component_master_del(&con->dev, &typec_aggregate_ops);