summaryrefslogtreecommitdiff
path: root/include/linux/usb/usbpd.h
blob: c2c1025feb8eb436148b59d978e631875ae2d5bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* 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 <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;

	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 */