API for USB Type-C Alternate Mode drivers

Introduction

Alternate modes require communication with the partner using Vendor DefinedMessages (VDM) as defined in USB Type-C and USB Power Delivery Specifications.The communication is SVID (Standard or Vendor ID) specific, i.e. specific forevery alternate mode, so every alternate mode will need a custom driver.

USB Type-C bus allows binding a driver to the discovered partner alternatemodes by using the SVID and the mode number.

USB Type-C Connector Class provides a device for every alternatemode a port supports, and separate device for every alternate mode the partnersupports. The drivers for the alternate modes are bound to the partner alternatemode devices, and the port alternate mode devices must be handled by the portdrivers.

When a new partner alternate mode device is registered, it is linked to thealternate mode device of the port that the partner is attached to, that hasmatching SVID and mode. Communication between the port driver and alternate modedriver will happen using the same API.

The port alternate mode devices are used as a proxy between the partner and thealternate mode drivers, so the port drivers are only expected to pass the SVIDspecific commands from the alternate mode drivers to the partner, and from thepartners to the alternate mode drivers. No direct SVID specific communication isneeded from the port drivers, but the port drivers need to provide the operationcallbacks for the port alternate mode devices, just like the alternate modedrivers need to provide them for the partner alternate mode devices.

Usage:

General

By default, the alternate mode drivers are responsible for entering the mode.It is also possible to leave the decision about entering the mode to the userspace (See Documentation/ABI/testing/sysfs-class-typec). Port drivers should notenter any modes on their own.

->vdm is the most important callback in the operation callbacks vector. Itwill be used to deliver all the SVID specific commands from the partner to thealternate mode driver, and vice versa in case of port drivers. The drivers sendthe SVID specific commands to each other usingtypec_altmode_vdm().

If the communication with the partner using the SVID specific commands resultsin need to reconfigure the pins on the connector, the alternate mode driverneeds to notify the bus usingtypec_altmode_notify(). The driverpasses the negotiated SVID specific pin configuration value to the function asparameter. The bus driver will then configure the mux behind the connector usingthat value as the state value for the mux.

NOTE: The SVID specific pin configuration values must always start fromTYPEC_STATE_MODAL. USB Type-C specification defines two default states forthe connector:TYPEC_STATE_USB andTYPEC_STATE_SAFE. These values arereserved by the bus as the first possible values for the state. When thealternate mode is entered, the bus will put the connector intoTYPEC_STATE_SAFE before sending Enter or Exit Mode command as defined in USBType-C Specification, and also put the connector back toTYPEC_STATE_USBafter the mode has been exited.

An example of working definitions for SVID specific pin configurations wouldlook like this:

enum {    ALTMODEX_CONF_A = TYPEC_STATE_MODAL,    ALTMODEX_CONF_B,    ...};

Helper macroTYPEC_MODAL_STATE() can also be used:

#define ALTMODEX_CONF_A = TYPEC_MODAL_STATE(0);#define ALTMODEX_CONF_B = TYPEC_MODAL_STATE(1);

Cable plug alternate modes

The alternate mode drivers are not bound to cable plug alternate mode devices,only to the partner alternate mode devices. If the alternate mode supports, orrequires, a cable that responds to SOP Prime, and optionally SOP Double Primemessages, the driver for that alternate mode must request handle to the cableplug alternate modes usingtypec_altmode_get_plug(), and take overtheir control.

Driver API

Alternate mode driver registering/unregistering

Alternate mode driver operations

inttypec_altmode_notify(struct typec_altmode * adev, unsigned long conf, void * data)

Communication between the OS and alternate mode driver

Parameters

structtypec_altmode*adev
Handle to the alternate mode
unsignedlongconf
Alternate mode specific configuration value
void*data
Alternate mode specific data

Description

The primary purpose for this function is to allow the alternate mode driversto tell which pin configuration has been negotiated with the partner. Thatinformation will then be used for example to configure the muxes.Communication to the other direction is also possible, and low level devicedrivers can also send notifications to the alternate mode drivers. The actualcommunication will be specific for every SVID.

inttypec_altmode_enter(struct typec_altmode * adev, u32 * vdo)

Enter Mode

Parameters

structtypec_altmode*adev
The alternate mode
u32*vdo
VDO for the Enter Mode command

Description

The alternate mode drivers use this function to enter mode. The port driversuse this to inform the alternate mode drivers that the partner has initiatedEnter Mode command. If the alternate mode does not require VDO,vdo must beNULL.

inttypec_altmode_exit(struct typec_altmode * adev)

Exit Mode

Parameters

structtypec_altmode*adev
The alternate mode

Description

The partner ofadev has initiated Exit Mode command.

voidtypec_altmode_attention(struct typec_altmode * adev, u32 vdo)

Attention command

Parameters

structtypec_altmode*adev
The alternate mode
u32vdo
VDO for the Attention command

Description

Notifies the partner ofadev about Attention command.

inttypec_altmode_vdm(struct typec_altmode * adev, const u32 header, const u32 * vdo, int count)

Send Vendor Defined Messages (VDM) to the partner

Parameters

structtypec_altmode*adev
Alternate mode handle
constu32header
VDM Header
constu32*vdo
Array of Vendor Defined Data Objects
intcount
Number of Data Objects

Description

The alternate mode drivers use this function for SVID specific communicationwith the partner. The port drivers use it to deliver the Structured VDMsreceived from the partners to the alternate mode drivers.

API for the port drivers

struct typec_altmode *typec_match_altmode(struct typec_altmode ** altmodes, size_t n, u16 svid, u8 mode)

Match SVID and mode to an array of alternate modes

Parameters

structtypec_altmode**altmodes
Array of alternate modes
size_tn
Number of elements in the array, or -1 for NULL terminated arrays
u16svid
Standard or Vendor ID to match with
u8mode
Mode to match with

Description

Return pointer to an alternate mode with SVID matchingsvid, or NULL when nomatch is found.

Cable Plug operations

struct typec_altmode *typec_altmode_get_plug(struct typec_altmode * adev, enum typec_plug_index index)

Find cable plug alternate mode

Parameters

structtypec_altmode*adev
Handle to partner alternate mode
enumtypec_plug_indexindex
Cable plug index

Description

Increment reference count for cable plug alternate mode device. Returnshandle to the cable plug alternate mode, or NULL if none is found.

voidtypec_altmode_put_plug(struct typec_altmode * plug)

Decrement cable plug alternate mode reference count

Parameters

structtypec_altmode*plug
Handle to the cable plug alternate mode