blob: 4dbd91f5877f676dcede2d5081f54e70a1cfeabd [file] [log] [blame]
/* Copyright (c) 2016-2017, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __LINUX_USB_USBPD_H
#define __LINUX_USB_USBPD_H
#include <linux/list.h>
struct usbpd;
/* 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);
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);
#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;
}
#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 */