On 02/25/2018 07:25 AM, Hans de Goede wrote: > From: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> > > --- > Documentation/driver-api/usb/typec.rst | 73 +++++++++++-- > drivers/usb/typec/Makefile | 1 + > drivers/usb/typec/{typec.c => class.c} | 70 ++++++++++++ > drivers/usb/typec/mux.c | 188 +++++++++++++++++++++++++++++++++ > include/linux/usb/typec.h | 14 +++ > include/linux/usb/typec_mux.h | 55 ++++++++++ > 6 files changed, 390 insertions(+), 11 deletions(-) > rename drivers/usb/typec/{typec.c => class.c} (95%) > create mode 100644 drivers/usb/typec/mux.c > create mode 100644 include/linux/usb/typec_mux.h > > diff --git a/Documentation/driver-api/usb/typec.rst b/Documentation/driver-api/usb/typec.rst > index 8a7249f2ff04..091e4def3a39 100644 > --- a/Documentation/driver-api/usb/typec.rst > +++ b/Documentation/driver-api/usb/typec.rst > + > +Multiplexer/DeMultiplexer Switches > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + > +USB Type-C connectors may have one or more mux/demux switches behind them. Since > +the plugs can be inserted right-side-up or upside-down, a switch is needed to > +route the correct data pairs from the connector to the USB controllers. If > +Alternate or Accessory Modes are supported, an other switch is needed that can another > +route the pins on the connector to some other component besides USB. USB Type-C > +Connector Class supplies an API for registering those switches. > + > +.. kernel-doc:: drivers/usb/typec/mux.c > + :functions: typec_switch_register typec_switch_unregister typec_mux_register typec_mux_unregister > + > +In most cases the same physical mux will handle both the orientation and mode. > +However, as the port drivers will be responsible of the orientation, and the for the orientation, > +alternate mode drivers of the mode, the two are always separated into their own for the mode, > +logical components: "mux" for the mode and "switch" for the orientation. > + > +When a port is registered, USB Type-C Connector Class requests both the mux and > +the switch for the port. The drivers can then use the following API for > +controlling them: > + > +.. kernel-doc:: drivers/usb/typec/class.c > + :functions: typec_set_orientation typec_set_mode > + > +If the connector is dual-role capable, there may also be a switch for the data > +role. USB Type-C Connector Class does not supply separate API for them. The > +port drivers can use USB Role Class API with those. > + > +Illustration of the muxes behind a connector that supports an alternate mode: > + > + ------------------------ > + | Connector | > + ------------------------ > + | | > + ------------------------ > + \ Orientation / > + -------------------- > + | > + -------------------- > + / Mode \ > + ------------------------ > + / \ > + ------------------------ -------------------- > + | Alt Mode | / USB Role \ > + ------------------------ ------------------------ > + / \ > + ------------------------ ------------------------ > + | USB Host | | USB Device | > + ------------------------ ------------------------ > diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c > new file mode 100644 > index 000000000000..3102238366ed > --- /dev/null > +++ b/drivers/usb/typec/mux.c > @@ -0,0 +1,188 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/** > + * USB Type-C Multiplexer/DeMultiplexer Switch support > + * > + * Copyright (C) 2018 Intel Corporation > + * Author: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> > + * Hans de Goede <hdegoede@xxxxxxxxxx> > + */ > + > +#include <linux/device.h> > +#include <linux/connection.h> > +#include <linux/usb/typec_mux.h> Needs: <linux/mutex.h> <linux/list.h> ... > +static DEFINE_MUTEX(switch_lock); > +static DEFINE_MUTEX(mux_lock); > +static LIST_HEAD(switch_list); > +static LIST_HEAD(mux_list); > + > +static void *typec_switch_match(struct devcon *con, int ep, void *data) > +{ > + struct typec_switch *sw; > + > + list_for_each_entry(sw, &switch_list, entry) > + if (!strcmp(con->endpoint[ep], dev_name(sw->dev))) > + return sw; > + > + /* > + * We only get called if a connection was found, tell the caller to > + * wait for the switch to show-up. show up. > + */ > + return ERR_PTR(-EPROBE_DEFER); > +} > + > +static void *typec_mux_match(struct devcon *con, int ep, void *data) > +{ > + struct typec_mux *mux; > + > + list_for_each_entry(mux, &mux_list, entry) > + if (!strcmp(con->endpoint[ep], dev_name(mux->dev))) > + return mux; > + > + /* > + * We only get called if a connection was found, tell the caller to > + * wait for the switch to show-up. show up. > + */ > + return ERR_PTR(-EPROBE_DEFER); > +} > diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h > new file mode 100644 > index 000000000000..0ddaaa8b0ac1 > --- /dev/null > +++ b/include/linux/usb/typec_mux.h > @@ -0,0 +1,55 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#ifndef __USB_TYPEC_MUX > +#define __USB_TYPEC_MUX > + > +#include <linux/list.h> > +#include <linux/usb/typec.h> > + > +struct device; > + > +/** > + * typec_switch - USB Type-C cable orientation switch * struct typec_switch - USB Type-C cable orientation switch > + * @dev: Switch device > + * @entry: List entry > + * @set: Callback to the driver for setting the orientation > + * > + * USB Type-C pin flipper switch routing the correct data pairs from the > + * connector to the USB controller depending on the orientation of the cable > + * plug. > + */ > +struct typec_switch { > + struct device *dev; > + struct list_head entry; > + > + int (*set)(struct typec_switch *sw, enum typec_orientation orientation); > +}; > + > +/** > + * typec_switch - USB Type-C connector pin mux * struct typec_mux - USB Type-C connector pin mux > + * @dev: Mux device > + * @entry: List entry > + * @set: Callback to the driver for setting the state of the mux > + * > + * Pin Multiplexer/DeMultiplexer switch routing the USB Type-C connector pins to > + * different components depending on the requested mode of operation. Used with > + * Accessory/Alternate modes. > + */ > +struct typec_mux { > + struct device *dev; > + struct list_head entry; > + > + int (*set)(struct typec_mux *mux, int state); > +}; ta. -- ~Randy -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html