/* Copyright (c) 2016, 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 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; void (*connect)(struct usbpd_svid_handler *hdlr); void (*disconnect)(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); struct list_head entry; }; 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 */