cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

port-mapper.c (2299B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * USB Type-C Connector Class Port Mapping Utility
      4 *
      5 * Copyright (C) 2021, Intel Corporation
      6 * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
      7 */
      8
      9#include <linux/acpi.h>
     10#include <linux/component.h>
     11
     12#include "class.h"
     13
     14static int typec_aggregate_bind(struct device *dev)
     15{
     16	return component_bind_all(dev, NULL);
     17}
     18
     19static void typec_aggregate_unbind(struct device *dev)
     20{
     21	component_unbind_all(dev, NULL);
     22}
     23
     24static const struct component_master_ops typec_aggregate_ops = {
     25	.bind = typec_aggregate_bind,
     26	.unbind = typec_aggregate_unbind,
     27};
     28
     29struct each_port_arg {
     30	struct typec_port *port;
     31	struct component_match *match;
     32};
     33
     34static int typec_port_compare(struct device *dev, void *fwnode)
     35{
     36	return device_match_fwnode(dev, fwnode);
     37}
     38
     39static int typec_port_match(struct device *dev, void *data)
     40{
     41	struct acpi_device *adev = to_acpi_device(dev);
     42	struct each_port_arg *arg = data;
     43	struct acpi_device *con_adev;
     44
     45	con_adev = ACPI_COMPANION(&arg->port->dev);
     46	if (con_adev == adev)
     47		return 0;
     48
     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));
     52	return 0;
     53}
     54
     55int typec_link_ports(struct typec_port *con)
     56{
     57	struct each_port_arg arg = { .port = con, .match = NULL };
     58
     59	if (!has_acpi_companion(&con->dev))
     60		return 0;
     61
     62	acpi_bus_for_each_dev(typec_port_match, &arg);
     63	if (!arg.match)
     64		return 0;
     65
     66	/*
     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.
     76	 */
     77	return component_master_add_with_match(&con->dev, &typec_aggregate_ops, arg.match);
     78}
     79
     80void typec_unlink_ports(struct typec_port *con)
     81{
     82	if (has_acpi_companion(&con->dev))
     83		component_master_del(&con->dev, &typec_aggregate_ops);
     84}