Files
Pratham Pratap 88731b2564 usb: pd: Add flag to notify peer_usb_comm support to dp
Some Type-C multi-port adapters which do not support usb connection
are advertising the multi-functionality in DP alt mode. If
multi-functionality is preferred, the DP driver assumes the adapter
supports usb connection and USB phy driver will program the PHY mode
to DP+USB.

In source mode, usb PD driver checks for the peer_usb_connection
of the adapter. If it does not support usb then it will stop usb stack
and update the PHY MODE to USB only mode from phy_suspend path.
The result is, usb may program the combo PHY to usb only mode when DP
is already connected. This is causing AUX read/write timeouts when DP
is trying to access the phy registers.

To fix this issue, a flag in SVID connect handler in usbpd driver to
notify peer_usb_comm support to the DP driver. DP driver will read this
flag and program the phy mode.

Change-Id: Iae6a9596000313ede51d8af3c4989c74ac2f0b10
Signed-off-by: Pratham Pratap <prathampratap@codeaurora.org>
2019-10-15 14:30:06 -07:00

163 lines
4.0 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*/
#ifndef __LINUX_USB_USBPD_H
#define __LINUX_USB_USBPD_H
#include <linux/list.h>
struct usbpd;
struct device;
/* Standard IDs */
#define USBPD_SID 0xff00
/* Structured VDM Command Type */
enum usbpd_svdm_cmd_type {
SVDM_CMD_TYPE_INITIATOR,
SVDM_CMD_TYPE_RESP_ACK,
SVDM_CMD_TYPE_RESP_NAK,
SVDM_CMD_TYPE_RESP_BUSY,
};
/* Structured VDM Commands */
#define USBPD_SVDM_DISCOVER_IDENTITY 0x1
#define USBPD_SVDM_DISCOVER_SVIDS 0x2
#define USBPD_SVDM_DISCOVER_MODES 0x3
#define USBPD_SVDM_ENTER_MODE 0x4
#define USBPD_SVDM_EXIT_MODE 0x5
#define USBPD_SVDM_ATTENTION 0x6
/*
* Implemented by client
*/
struct usbpd_svid_handler {
u16 svid;
/* Notified when VDM session established/reset; must be implemented */
void (*connect)(struct usbpd_svid_handler *hdlr,
bool supports_usb_comm);
void (*disconnect)(struct usbpd_svid_handler *hdlr);
/* DP driver -> PE driver for requesting USB SS lanes */
int (*request_usb_ss_lane)(struct usbpd *pd,
struct usbpd_svid_handler *hdlr);
/* Unstructured VDM */
void (*vdm_received)(struct usbpd_svid_handler *hdlr, u32 vdm_hdr,
const u32 *vdos, int num_vdos);
/* Structured VDM */
void (*svdm_received)(struct usbpd_svid_handler *hdlr, u8 cmd,
enum usbpd_svdm_cmd_type cmd_type, const u32 *vdos,
int num_vdos);
/* client should leave these blank; private members used by PD driver */
struct list_head entry;
bool discovered;
};
enum plug_orientation {
ORIENTATION_NONE,
ORIENTATION_CC1,
ORIENTATION_CC2,
};
#if IS_ENABLED(CONFIG_USB_PD_POLICY)
/*
* Obtains an instance of usbpd from a DT phandle
*/
struct usbpd *devm_usbpd_get_by_phandle(struct device *dev,
const char *phandle);
/*
* Called by client to handle specific SVID messages.
* Specify callback functions in the usbpd_svid_handler argument
*/
int usbpd_register_svid(struct usbpd *pd, struct usbpd_svid_handler *hdlr);
void usbpd_unregister_svid(struct usbpd *pd, struct usbpd_svid_handler *hdlr);
/*
* Transmit a VDM message.
*/
int usbpd_send_vdm(struct usbpd *pd, u32 vdm_hdr, const u32 *vdos,
int num_vdos);
/*
* Transmit a Structured VDM message.
*/
int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd,
enum usbpd_svdm_cmd_type cmd_type, int obj_pos,
const u32 *vdos, int num_vdos);
/*
* Get current status of CC pin orientation.
*
* Return: ORIENTATION_CC1 or ORIENTATION_CC2 if attached,
* otherwise ORIENTATION_NONE if not attached
*/
enum plug_orientation usbpd_get_plug_orientation(struct usbpd *pd);
void usbpd_vdm_in_suspend(struct usbpd *pd, bool in_suspend);
#else
static inline struct usbpd *devm_usbpd_get_by_phandle(struct device *dev,
const char *phandle)
{
return ERR_PTR(-ENODEV);
}
static inline int usbpd_register_svid(struct usbpd *pd,
struct usbpd_svid_handler *hdlr)
{
return -EINVAL;
}
static inline void usbpd_unregister_svid(struct usbpd *pd,
struct usbpd_svid_handler *hdlr)
{
}
static inline int usbpd_send_vdm(struct usbpd *pd, u32 vdm_hdr, const u32 *vdos,
int num_vdos)
{
return -EINVAL;
}
static inline int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd,
enum usbpd_svdm_cmd_type cmd_type, int obj_pos,
const u32 *vdos, int num_vdos)
{
return -EINVAL;
}
static inline enum plug_orientation usbpd_get_plug_orientation(struct usbpd *pd)
{
return ORIENTATION_NONE;
}
static inline void usbpd_vdm_in_suspend(struct usbpd *pd, bool in_suspend) { }
#endif /* IS_ENABLED(CONFIG_USB_PD_POLICY) */
/*
* Additional helpers for Enter/Exit Mode commands
*/
static inline int usbpd_enter_mode(struct usbpd *pd, u16 svid, int mode,
const u32 *vdo)
{
return usbpd_send_svdm(pd, svid, USBPD_SVDM_ENTER_MODE,
SVDM_CMD_TYPE_INITIATOR, mode, vdo, vdo ? 1 : 0);
}
static inline int usbpd_exit_mode(struct usbpd *pd, u16 svid, int mode,
const u32 *vdo)
{
return usbpd_send_svdm(pd, svid, USBPD_SVDM_EXIT_MODE,
SVDM_CMD_TYPE_INITIATOR, mode, vdo, vdo ? 1 : 0);
}
#endif /* __LINUX_USB_USBPD_H */