Skip to content

Commit f0690a2

Browse files
Guenter Roeckgregkh
authored andcommitted
staging: typec: USB Type-C Port Manager (tcpm)
This driver implements the USB Type-C Power Delivery state machine for both source and sink ports. Alternate mode support is not fully implemented. The driver attaches to the USB Type-C class code implemented in the following patches. usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY usb: USB Type-C connector class This driver only implements the state machine. Lower level drivers are responsible for - Reporting VBUS status and activating VBUS - Setting CC lines and providing CC line status - Setting line polarity - Activating and deactivating VCONN - Setting the current limit - Activating and deactivating PD message transfers - Sending and receiving PD messages The driver provides both a functional API as well as callbacks for lower level drivers. Signed-off-by: Guenter Roeck <[email protected]> Signed-off-by: Guenter Roeck <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent d852ed9 commit f0690a2

File tree

10 files changed

+4203
-1
lines changed

10 files changed

+4203
-1
lines changed

drivers/staging/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,6 @@ source "drivers/staging/vc04_services/Kconfig"
104104

105105
source "drivers/staging/bcm2835-audio/Kconfig"
106106

107+
source "drivers/staging/typec/Kconfig"
108+
107109
endif # STAGING

drivers/staging/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Makefile for staging directory
22

33
obj-y += media/
4+
obj-y += typec/
45
obj-$(CONFIG_PRISM2_USB) += wlan-ng/
56
obj-$(CONFIG_COMEDI) += comedi/
67
obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
@@ -41,4 +42,3 @@ obj-$(CONFIG_KS7010) += ks7010/
4142
obj-$(CONFIG_GREYBUS) += greybus/
4243
obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/
4344
obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
44-

drivers/staging/typec/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
menu "USB Power Delivery and Type-C drivers"
2+
3+
config TYPEC_TCPM
4+
tristate "USB Type-C Port Controller Manager"
5+
depends on USB
6+
select TYPEC
7+
help
8+
The Type-C Port Controller Manager provides a USB PD and USB Type-C
9+
state machine for use with Type-C Port Controllers.
10+
11+
endmenu

drivers/staging/typec/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
obj-$(CONFIG_TYPEC_TCPM) += tcpm.o

drivers/staging/typec/TODO

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
tcpm:
2+
- Add documentation (at the very least for the API to low level drivers)
3+
- Split PD code into separate file
4+
- Check if it makes sense to use tracepoints instead of debugfs for debug logs
5+
- Implement Alternate Mode handling
6+
- Address "#if 0" code if not addressed with the above
7+
- Validate all comments marked with "XXX"; either address or remove comments
8+
- Add support for USB PD 3.0. While not mandatory, at least fast role swap
9+
as well as authentication support would be very desirable.
10+
11+
Please send patches to Guenter Roeck <[email protected]> and copy
12+
Heikki Krogerus <[email protected]>.

drivers/staging/typec/pd.h

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
/*
2+
* Copyright 2015-2017 Google, Inc
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*/
14+
15+
#ifndef __LINUX_USB_PD_H
16+
#define __LINUX_USB_PD_H
17+
18+
#include <linux/types.h>
19+
#include <linux/usb/typec.h>
20+
21+
/* USB PD Messages */
22+
enum pd_ctrl_msg_type {
23+
/* 0 Reserved */
24+
PD_CTRL_GOOD_CRC = 1,
25+
PD_CTRL_GOTO_MIN = 2,
26+
PD_CTRL_ACCEPT = 3,
27+
PD_CTRL_REJECT = 4,
28+
PD_CTRL_PING = 5,
29+
PD_CTRL_PS_RDY = 6,
30+
PD_CTRL_GET_SOURCE_CAP = 7,
31+
PD_CTRL_GET_SINK_CAP = 8,
32+
PD_CTRL_DR_SWAP = 9,
33+
PD_CTRL_PR_SWAP = 10,
34+
PD_CTRL_VCONN_SWAP = 11,
35+
PD_CTRL_WAIT = 12,
36+
PD_CTRL_SOFT_RESET = 13,
37+
/* 14-15 Reserved */
38+
};
39+
40+
enum pd_data_msg_type {
41+
/* 0 Reserved */
42+
PD_DATA_SOURCE_CAP = 1,
43+
PD_DATA_REQUEST = 2,
44+
PD_DATA_BIST = 3,
45+
PD_DATA_SINK_CAP = 4,
46+
/* 5-14 Reserved */
47+
PD_DATA_VENDOR_DEF = 15,
48+
};
49+
50+
#define PD_REV10 0x0
51+
#define PD_REV20 0x1
52+
53+
#define PD_HEADER_CNT_SHIFT 12
54+
#define PD_HEADER_CNT_MASK 0x7
55+
#define PD_HEADER_ID_SHIFT 9
56+
#define PD_HEADER_ID_MASK 0x7
57+
#define PD_HEADER_PWR_ROLE BIT(8)
58+
#define PD_HEADER_REV_SHIFT 6
59+
#define PD_HEADER_REV_MASK 0x3
60+
#define PD_HEADER_DATA_ROLE BIT(5)
61+
#define PD_HEADER_TYPE_SHIFT 0
62+
#define PD_HEADER_TYPE_MASK 0xf
63+
64+
#define PD_HEADER(type, pwr, data, id, cnt) \
65+
((((type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) | \
66+
((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) | \
67+
((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) | \
68+
(PD_REV20 << PD_HEADER_REV_SHIFT) | \
69+
(((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) | \
70+
(((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT))
71+
72+
#define PD_HEADER_LE(type, pwr, data, id, cnt) \
73+
cpu_to_le16(PD_HEADER((type), (pwr), (data), (id), (cnt)))
74+
75+
static inline unsigned int pd_header_cnt(u16 header)
76+
{
77+
return (header >> PD_HEADER_CNT_SHIFT) & PD_HEADER_CNT_MASK;
78+
}
79+
80+
static inline unsigned int pd_header_cnt_le(__le16 header)
81+
{
82+
return pd_header_cnt(le16_to_cpu(header));
83+
}
84+
85+
static inline unsigned int pd_header_type(u16 header)
86+
{
87+
return (header >> PD_HEADER_TYPE_SHIFT) & PD_HEADER_TYPE_MASK;
88+
}
89+
90+
static inline unsigned int pd_header_type_le(__le16 header)
91+
{
92+
return pd_header_type(le16_to_cpu(header));
93+
}
94+
95+
#define PD_MAX_PAYLOAD 7
96+
97+
struct pd_message {
98+
__le16 header;
99+
__le32 payload[PD_MAX_PAYLOAD];
100+
} __packed;
101+
102+
/* PDO: Power Data Object */
103+
#define PDO_MAX_OBJECTS 7
104+
105+
enum pd_pdo_type {
106+
PDO_TYPE_FIXED = 0,
107+
PDO_TYPE_BATT = 1,
108+
PDO_TYPE_VAR = 2,
109+
};
110+
111+
#define PDO_TYPE_SHIFT 30
112+
#define PDO_TYPE_MASK 0x3
113+
114+
#define PDO_TYPE(t) ((t) << PDO_TYPE_SHIFT)
115+
116+
#define PDO_VOLT_MASK 0x3ff
117+
#define PDO_CURR_MASK 0x3ff
118+
#define PDO_PWR_MASK 0x3ff
119+
120+
#define PDO_FIXED_DUAL_ROLE BIT(29) /* Power role swap supported */
121+
#define PDO_FIXED_SUSPEND BIT(28) /* USB Suspend supported (Source) */
122+
#define PDO_FIXED_HIGHER_CAP BIT(28) /* Requires more than vSafe5V (Sink) */
123+
#define PDO_FIXED_EXTPOWER BIT(27) /* Externally powered */
124+
#define PDO_FIXED_USB_COMM BIT(26) /* USB communications capable */
125+
#define PDO_FIXED_DATA_SWAP BIT(25) /* Data role swap supported */
126+
#define PDO_FIXED_VOLT_SHIFT 10 /* 50mV units */
127+
#define PDO_FIXED_CURR_SHIFT 0 /* 10mA units */
128+
129+
#define PDO_FIXED_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_FIXED_VOLT_SHIFT)
130+
#define PDO_FIXED_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_FIXED_CURR_SHIFT)
131+
132+
#define PDO_FIXED(mv, ma, flags) \
133+
(PDO_TYPE(PDO_TYPE_FIXED) | (flags) | \
134+
PDO_FIXED_VOLT(mv) | PDO_FIXED_CURR(ma))
135+
136+
#define PDO_BATT_MAX_VOLT_SHIFT 20 /* 50mV units */
137+
#define PDO_BATT_MIN_VOLT_SHIFT 10 /* 50mV units */
138+
#define PDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */
139+
140+
#define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MIN_VOLT_SHIFT)
141+
#define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MAX_VOLT_SHIFT)
142+
#define PDO_BATT_MAX_POWER(mw) ((((mw) / 250) & PDO_PWR_MASK) << PDO_BATT_MAX_PWR_SHIFT)
143+
144+
#define PDO_BATT(min_mv, max_mv, max_mw) \
145+
(PDO_TYPE(PDO_TYPE_BATT) | PDO_BATT_MIN_VOLT(min_mv) | \
146+
PDO_BATT_MAX_VOLT(max_mv) | PDO_BATT_MAX_POWER(max_mw))
147+
148+
#define PDO_VAR_MAX_VOLT_SHIFT 20 /* 50mV units */
149+
#define PDO_VAR_MIN_VOLT_SHIFT 10 /* 50mV units */
150+
#define PDO_VAR_MAX_CURR_SHIFT 0 /* 10mA units */
151+
152+
#define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MIN_VOLT_SHIFT)
153+
#define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MAX_VOLT_SHIFT)
154+
#define PDO_VAR_MAX_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_VAR_MAX_CURR_SHIFT)
155+
156+
#define PDO_VAR(min_mv, max_mv, max_ma) \
157+
(PDO_TYPE(PDO_TYPE_VAR) | PDO_VAR_MIN_VOLT(min_mv) | \
158+
PDO_VAR_MAX_VOLT(max_mv) | PDO_VAR_MAX_CURR(max_ma))
159+
160+
static inline enum pd_pdo_type pdo_type(u32 pdo)
161+
{
162+
return (pdo >> PDO_TYPE_SHIFT) & PDO_TYPE_MASK;
163+
}
164+
165+
static inline unsigned int pdo_fixed_voltage(u32 pdo)
166+
{
167+
return ((pdo >> PDO_FIXED_VOLT_SHIFT) & PDO_VOLT_MASK) * 50;
168+
}
169+
170+
static inline unsigned int pdo_min_voltage(u32 pdo)
171+
{
172+
return ((pdo >> PDO_VAR_MIN_VOLT_SHIFT) & PDO_VOLT_MASK) * 50;
173+
}
174+
175+
static inline unsigned int pdo_max_voltage(u32 pdo)
176+
{
177+
return ((pdo >> PDO_VAR_MAX_VOLT_SHIFT) & PDO_VOLT_MASK) * 50;
178+
}
179+
180+
static inline unsigned int pdo_max_current(u32 pdo)
181+
{
182+
return ((pdo >> PDO_VAR_MAX_CURR_SHIFT) & PDO_CURR_MASK) * 10;
183+
}
184+
185+
static inline unsigned int pdo_max_power(u32 pdo)
186+
{
187+
return ((pdo >> PDO_BATT_MAX_PWR_SHIFT) & PDO_PWR_MASK) * 250;
188+
}
189+
190+
/* RDO: Request Data Object */
191+
#define RDO_OBJ_POS_SHIFT 28
192+
#define RDO_OBJ_POS_MASK 0x7
193+
#define RDO_GIVE_BACK BIT(27) /* Supports reduced operating current */
194+
#define RDO_CAP_MISMATCH BIT(26) /* Not satisfied by source caps */
195+
#define RDO_USB_COMM BIT(25) /* USB communications capable */
196+
#define RDO_NO_SUSPEND BIT(24) /* USB Suspend not supported */
197+
198+
#define RDO_PWR_MASK 0x3ff
199+
#define RDO_CURR_MASK 0x3ff
200+
201+
#define RDO_FIXED_OP_CURR_SHIFT 10
202+
#define RDO_FIXED_MAX_CURR_SHIFT 0
203+
204+
#define RDO_OBJ(idx) (((idx) & RDO_OBJ_POS_MASK) << RDO_OBJ_POS_SHIFT)
205+
206+
#define PDO_FIXED_OP_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_OP_CURR_SHIFT)
207+
#define PDO_FIXED_MAX_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_MAX_CURR_SHIFT)
208+
209+
#define RDO_FIXED(idx, op_ma, max_ma, flags) \
210+
(RDO_OBJ(idx) | (flags) | \
211+
PDO_FIXED_OP_CURR(op_ma) | PDO_FIXED_MAX_CURR(max_ma))
212+
213+
#define RDO_BATT_OP_PWR_SHIFT 10 /* 250mW units */
214+
#define RDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */
215+
216+
#define RDO_BATT_OP_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_OP_PWR_SHIFT)
217+
#define RDO_BATT_MAX_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_MAX_PWR_SHIFT)
218+
219+
#define RDO_BATT(idx, op_mw, max_mw, flags) \
220+
(RDO_OBJ(idx) | (flags) | \
221+
RDO_BATT_OP_PWR(op_mw) | RDO_BATT_MAX_PWR(max_mw))
222+
223+
static inline unsigned int rdo_index(u32 rdo)
224+
{
225+
return (rdo >> RDO_OBJ_POS_SHIFT) & RDO_OBJ_POS_MASK;
226+
}
227+
228+
static inline unsigned int rdo_op_current(u32 rdo)
229+
{
230+
return ((rdo >> RDO_FIXED_OP_CURR_SHIFT) & RDO_CURR_MASK) * 10;
231+
}
232+
233+
static inline unsigned int rdo_max_current(u32 rdo)
234+
{
235+
return ((rdo >> RDO_FIXED_MAX_CURR_SHIFT) &
236+
RDO_CURR_MASK) * 10;
237+
}
238+
239+
static inline unsigned int rdo_op_power(u32 rdo)
240+
{
241+
return ((rdo >> RDO_BATT_OP_PWR_SHIFT) & RDO_PWR_MASK) * 250;
242+
}
243+
244+
static inline unsigned int rdo_max_power(u32 rdo)
245+
{
246+
return ((rdo >> RDO_BATT_MAX_PWR_SHIFT) & RDO_PWR_MASK) * 250;
247+
}
248+
249+
/* USB PD timers and counters */
250+
#define PD_T_NO_RESPONSE 5000 /* 4.5 - 5.5 seconds */
251+
#define PD_T_DB_DETECT 10000 /* 10 - 15 seconds */
252+
#define PD_T_SEND_SOURCE_CAP 150 /* 100 - 200 ms */
253+
#define PD_T_SENDER_RESPONSE 60 /* 24 - 30 ms, relaxed */
254+
#define PD_T_SOURCE_ACTIVITY 45
255+
#define PD_T_SINK_ACTIVITY 135
256+
#define PD_T_SINK_WAIT_CAP 240
257+
#define PD_T_PS_TRANSITION 500
258+
#define PD_T_SRC_TRANSITION 35
259+
#define PD_T_DRP_SNK 40
260+
#define PD_T_DRP_SRC 30
261+
#define PD_T_PS_SOURCE_OFF 920
262+
#define PD_T_PS_SOURCE_ON 480
263+
#define PD_T_PS_HARD_RESET 30
264+
#define PD_T_SRC_RECOVER 760
265+
#define PD_T_SRC_RECOVER_MAX 1000
266+
#define PD_T_SRC_TURN_ON 275
267+
#define PD_T_SAFE_0V 650
268+
#define PD_T_VCONN_SOURCE_ON 100
269+
#define PD_T_SINK_REQUEST 100 /* 100 ms minimum */
270+
#define PD_T_ERROR_RECOVERY 100 /* minimum 25 is insufficient */
271+
272+
#define PD_T_DRP_TRY 100 /* 75 - 150 ms */
273+
#define PD_T_DRP_TRYWAIT 600 /* 400 - 800 ms */
274+
275+
#define PD_T_CC_DEBOUNCE 200 /* 100 - 200 ms */
276+
#define PD_T_PD_DEBOUNCE 20 /* 10 - 20 ms */
277+
278+
#define PD_N_CAPS_COUNT (PD_T_NO_RESPONSE / PD_T_SEND_SOURCE_CAP)
279+
#define PD_N_HARD_RESET_COUNT 2
280+
281+
#endif /* __LINUX_USB_PD_H */

drivers/staging/typec/pd_bdo.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2015-2017 Google, Inc
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*/
14+
15+
#ifndef __LINUX_USB_PD_BDO_H
16+
#define __LINUX_USB_PD_BDO_H
17+
18+
/* BDO : BIST Data Object */
19+
#define BDO_MODE_RECV (0 << 28)
20+
#define BDO_MODE_TRANSMIT (1 << 28)
21+
#define BDO_MODE_COUNTERS (2 << 28)
22+
#define BDO_MODE_CARRIER0 (3 << 28)
23+
#define BDO_MODE_CARRIER1 (4 << 28)
24+
#define BDO_MODE_CARRIER2 (5 << 28)
25+
#define BDO_MODE_CARRIER3 (6 << 28)
26+
#define BDO_MODE_EYE (7 << 28)
27+
#define BDO_MODE_TESTDATA (8 << 28)
28+
29+
#define BDO_MODE_MASK(mode) ((mode) & 0xf0000000)
30+
31+
#endif

0 commit comments

Comments
 (0)