1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for Intel PMC USB mux control
5 * Copyright (C) 2020 Intel Corporation
6 * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
9 #include <linux/acpi.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/property.h>
13 #include <linux/usb/role.h>
14 #include <linux/usb/typec_mux.h>
15 #include <linux/usb/typec_dp.h>
16 #include <linux/usb/typec_tbt.h>
18 #include <asm/intel_pmc_ipc.h>
20 #define PMC_USBC_CMD 0xa7
22 /* "Usage" OOB Message field values */
31 #define PMC_USB_MSG_USB2_PORT_SHIFT 0
32 #define PMC_USB_MSG_USB3_PORT_SHIFT 4
33 #define PMC_USB_MSG_UFP_SHIFT 4
34 #define PMC_USB_MSG_ORI_HSL_SHIFT 5
35 #define PMC_USB_MSG_ORI_AUX_SHIFT 6
37 /* Alt Mode Request */
46 #define PMC_USB_MODE_TYPE_SHIFT 4
49 PMC_USB_MODE_TYPE_USB
,
51 PMC_USB_MODE_TYPE_TBT
,
54 /* Common Mode Data bits */
55 #define PMC_USB_ALTMODE_ACTIVE_CABLE BIT(2)
57 #define PMC_USB_ALTMODE_ORI_SHIFT 1
58 #define PMC_USB_ALTMODE_UFP_SHIFT 3
59 #define PMC_USB_ALTMODE_ORI_AUX_SHIFT 4
60 #define PMC_USB_ALTMODE_ORI_HSL_SHIFT 5
62 /* DP specific Mode Data bits */
63 #define PMC_USB_ALTMODE_DP_MODE_SHIFT 8
65 /* TBT specific Mode Data bits */
66 #define PMC_USB_ALTMODE_TBT_TYPE BIT(17)
67 #define PMC_USB_ALTMODE_CABLE_TYPE BIT(18)
68 #define PMC_USB_ALTMODE_ACTIVE_LINK BIT(20)
69 #define PMC_USB_ALTMODE_FORCE_LSR BIT(23)
70 #define PMC_USB_ALTMODE_CABLE_SPD(_s_) (((_s_) & GENMASK(2, 0)) << 25)
71 #define PMC_USB_ALTMODE_CABLE_USB31 1
72 #define PMC_USB_ALTMODE_CABLE_10GPS 2
73 #define PMC_USB_ALTMODE_CABLE_20GPS 3
74 #define PMC_USB_ALTMODE_TBT_GEN(_g_) (((_g_) & GENMASK(1, 0)) << 28)
76 /* Display HPD Request bits */
77 #define PMC_USB_DP_HPD_IRQ BIT(5)
78 #define PMC_USB_DP_HPD_LVL BIT(6)
85 struct typec_mux
*typec_mux
;
86 struct typec_switch
*typec_sw
;
87 struct usb_role_switch
*usb_sw
;
89 enum typec_orientation orientation
;
99 struct pmc_usb_port
*port
;
102 static int pmc_usb_command(struct pmc_usb_port
*port
, u8
*msg
, u32 len
)
107 * Error bit will always be 0 with the USBC command.
108 * Status can be checked from the response message.
110 intel_pmc_ipc_command(PMC_USBC_CMD
, 0, msg
, len
,
111 (void *)response
, 1);
114 if (response
[2] & BIT(1))
123 pmc_usb_mux_dp_hpd(struct pmc_usb_port
*port
, struct typec_mux_state
*state
)
125 struct typec_displayport_data
*data
= state
->data
;
128 msg
[0] = PMC_USB_DP_HPD
;
129 msg
[0] |= port
->usb3_port
<< PMC_USB_MSG_USB3_PORT_SHIFT
;
131 msg
[1] = PMC_USB_DP_HPD_IRQ
;
133 if (data
->status
& DP_STATUS_HPD_STATE
)
134 msg
[1] |= PMC_USB_DP_HPD_LVL
;
136 return pmc_usb_command(port
, msg
, sizeof(msg
));
140 pmc_usb_mux_dp(struct pmc_usb_port
*port
, struct typec_mux_state
*state
)
142 struct typec_displayport_data
*data
= state
->data
;
143 struct altmode_req req
= { };
145 if (data
->status
& DP_STATUS_IRQ_HPD
)
146 return pmc_usb_mux_dp_hpd(port
, state
);
148 req
.usage
= PMC_USB_ALT_MODE
;
149 req
.usage
|= port
->usb3_port
<< PMC_USB_MSG_USB3_PORT_SHIFT
;
150 req
.mode_type
= PMC_USB_MODE_TYPE_DP
<< PMC_USB_MODE_TYPE_SHIFT
;
152 req
.mode_data
= (port
->orientation
- 1) << PMC_USB_ALTMODE_ORI_SHIFT
;
153 req
.mode_data
|= (port
->role
- 1) << PMC_USB_ALTMODE_UFP_SHIFT
;
154 req
.mode_data
|= (port
->orientation
- 1) << PMC_USB_ALTMODE_ORI_AUX_SHIFT
;
155 req
.mode_data
|= (port
->orientation
- 1) << PMC_USB_ALTMODE_ORI_HSL_SHIFT
;
157 req
.mode_data
|= (state
->mode
- TYPEC_STATE_MODAL
) <<
158 PMC_USB_ALTMODE_DP_MODE_SHIFT
;
160 return pmc_usb_command(port
, (void *)&req
, sizeof(req
));
164 pmc_usb_mux_tbt(struct pmc_usb_port
*port
, struct typec_mux_state
*state
)
166 struct typec_thunderbolt_data
*data
= state
->data
;
167 u8 cable_speed
= TBT_CABLE_SPEED(data
->cable_mode
);
168 struct altmode_req req
= { };
170 req
.usage
= PMC_USB_ALT_MODE
;
171 req
.usage
|= port
->usb3_port
<< PMC_USB_MSG_USB3_PORT_SHIFT
;
172 req
.mode_type
= PMC_USB_MODE_TYPE_TBT
<< PMC_USB_MODE_TYPE_SHIFT
;
174 req
.mode_data
= (port
->orientation
- 1) << PMC_USB_ALTMODE_ORI_SHIFT
;
175 req
.mode_data
|= (port
->role
- 1) << PMC_USB_ALTMODE_UFP_SHIFT
;
176 req
.mode_data
|= (port
->orientation
- 1) << PMC_USB_ALTMODE_ORI_AUX_SHIFT
;
177 req
.mode_data
|= (port
->orientation
- 1) << PMC_USB_ALTMODE_ORI_HSL_SHIFT
;
179 if (TBT_ADAPTER(data
->device_mode
) == TBT_ADAPTER_TBT3
)
180 req
.mode_data
|= PMC_USB_ALTMODE_TBT_TYPE
;
182 if (data
->cable_mode
& TBT_CABLE_OPTICAL
)
183 req
.mode_data
|= PMC_USB_ALTMODE_CABLE_TYPE
;
185 if (data
->cable_mode
& TBT_CABLE_LINK_TRAINING
)
186 req
.mode_data
|= PMC_USB_ALTMODE_ACTIVE_LINK
;
188 if (data
->enter_vdo
& TBT_ENTER_MODE_ACTIVE_CABLE
)
189 req
.mode_data
|= PMC_USB_ALTMODE_ACTIVE_CABLE
;
191 req
.mode_data
|= PMC_USB_ALTMODE_CABLE_SPD(cable_speed
);
193 return pmc_usb_command(port
, (void *)&req
, sizeof(req
));
196 static int pmc_usb_mux_safe_state(struct pmc_usb_port
*port
)
200 msg
= PMC_USB_SAFE_MODE
;
201 msg
|= port
->usb3_port
<< PMC_USB_MSG_USB3_PORT_SHIFT
;
203 return pmc_usb_command(port
, &msg
, sizeof(msg
));
206 static int pmc_usb_connect(struct pmc_usb_port
*port
)
210 msg
[0] = PMC_USB_CONNECT
;
211 msg
[0] |= port
->usb3_port
<< PMC_USB_MSG_USB3_PORT_SHIFT
;
213 msg
[1] = port
->usb2_port
<< PMC_USB_MSG_USB2_PORT_SHIFT
;
214 msg
[1] |= (port
->orientation
- 1) << PMC_USB_MSG_ORI_HSL_SHIFT
;
215 msg
[1] |= (port
->orientation
- 1) << PMC_USB_MSG_ORI_AUX_SHIFT
;
217 return pmc_usb_command(port
, msg
, sizeof(msg
));
220 static int pmc_usb_disconnect(struct pmc_usb_port
*port
)
224 msg
[0] = PMC_USB_DISCONNECT
;
225 msg
[0] |= port
->usb3_port
<< PMC_USB_MSG_USB3_PORT_SHIFT
;
227 msg
[1] = port
->usb2_port
<< PMC_USB_MSG_USB2_PORT_SHIFT
;
229 return pmc_usb_command(port
, msg
, sizeof(msg
));
233 pmc_usb_mux_set(struct typec_mux
*mux
, struct typec_mux_state
*state
)
235 struct pmc_usb_port
*port
= typec_mux_get_drvdata(mux
);
240 if (state
->mode
== TYPEC_STATE_SAFE
)
241 return pmc_usb_mux_safe_state(port
);
243 switch (state
->alt
->svid
) {
244 case USB_TYPEC_TBT_SID
:
245 return pmc_usb_mux_tbt(port
, state
);
246 case USB_TYPEC_DP_SID
:
247 return pmc_usb_mux_dp(port
, state
);
253 static int pmc_usb_set_orientation(struct typec_switch
*sw
,
254 enum typec_orientation orientation
)
256 struct pmc_usb_port
*port
= typec_switch_get_drvdata(sw
);
258 if (port
->orientation
== orientation
)
261 port
->orientation
= orientation
;
264 if (orientation
== TYPEC_ORIENTATION_NONE
)
265 return pmc_usb_disconnect(port
);
267 return pmc_usb_connect(port
);
273 static int pmc_usb_set_role(struct usb_role_switch
*sw
, enum usb_role role
)
275 struct pmc_usb_port
*port
= usb_role_switch_get_drvdata(sw
);
277 if (port
->role
== role
)
282 if (port
->orientation
) {
283 if (role
== USB_ROLE_NONE
)
284 return pmc_usb_disconnect(port
);
286 return pmc_usb_connect(port
);
292 static int pmc_usb_register_port(struct pmc_usb
*pmc
, int index
,
293 struct fwnode_handle
*fwnode
)
295 struct pmc_usb_port
*port
= &pmc
->port
[index
];
296 struct usb_role_switch_desc desc
= { };
297 struct typec_switch_desc sw_desc
= { };
298 struct typec_mux_desc mux_desc
= { };
301 ret
= fwnode_property_read_u8(fwnode
, "usb2-port", &port
->usb2_port
);
305 ret
= fwnode_property_read_u8(fwnode
, "usb3-port", &port
->usb3_port
);
312 sw_desc
.fwnode
= fwnode
;
313 sw_desc
.drvdata
= port
;
314 sw_desc
.name
= fwnode_get_name(fwnode
);
315 sw_desc
.set
= pmc_usb_set_orientation
;
317 port
->typec_sw
= typec_switch_register(pmc
->dev
, &sw_desc
);
318 if (IS_ERR(port
->typec_sw
))
319 return PTR_ERR(port
->typec_sw
);
321 mux_desc
.fwnode
= fwnode
;
322 mux_desc
.drvdata
= port
;
323 mux_desc
.name
= fwnode_get_name(fwnode
);
324 mux_desc
.set
= pmc_usb_mux_set
;
326 port
->typec_mux
= typec_mux_register(pmc
->dev
, &mux_desc
);
327 if (IS_ERR(port
->typec_mux
)) {
328 ret
= PTR_ERR(port
->typec_mux
);
329 goto err_unregister_switch
;
332 desc
.fwnode
= fwnode
;
333 desc
.driver_data
= port
;
334 desc
.name
= fwnode_get_name(fwnode
);
335 desc
.set
= pmc_usb_set_role
;
337 port
->usb_sw
= usb_role_switch_register(pmc
->dev
, &desc
);
338 if (IS_ERR(port
->usb_sw
)) {
339 ret
= PTR_ERR(port
->usb_sw
);
340 goto err_unregister_mux
;
346 typec_mux_unregister(port
->typec_mux
);
348 err_unregister_switch
:
349 typec_switch_unregister(port
->typec_sw
);
354 static int pmc_usb_probe(struct platform_device
*pdev
)
356 struct fwnode_handle
*fwnode
= NULL
;
361 pmc
= devm_kzalloc(&pdev
->dev
, sizeof(*pmc
), GFP_KERNEL
);
365 device_for_each_child_node(&pdev
->dev
, fwnode
)
368 pmc
->port
= devm_kcalloc(&pdev
->dev
, pmc
->num_ports
,
369 sizeof(struct pmc_usb_port
), GFP_KERNEL
);
373 pmc
->dev
= &pdev
->dev
;
376 * For every physical USB connector (USB2 and USB3 combo) there is a
377 * child ACPI device node under the PMC mux ACPI device object.
379 for (i
= 0; i
< pmc
->num_ports
; i
++) {
380 fwnode
= device_get_next_child_node(pmc
->dev
, fwnode
);
384 ret
= pmc_usb_register_port(pmc
, i
, fwnode
);
386 goto err_remove_ports
;
389 platform_set_drvdata(pdev
, pmc
);
394 for (i
= 0; i
< pmc
->num_ports
; i
++) {
395 typec_switch_unregister(pmc
->port
[i
].typec_sw
);
396 typec_mux_unregister(pmc
->port
[i
].typec_mux
);
402 static int pmc_usb_remove(struct platform_device
*pdev
)
404 struct pmc_usb
*pmc
= platform_get_drvdata(pdev
);
407 for (i
= 0; i
< pmc
->num_ports
; i
++) {
408 typec_switch_unregister(pmc
->port
[i
].typec_sw
);
409 typec_mux_unregister(pmc
->port
[i
].typec_mux
);
415 static const struct acpi_device_id pmc_usb_acpi_ids
[] = {
419 MODULE_DEVICE_TABLE(acpi
, pmc_usb_acpi_ids
);
421 static struct platform_driver pmc_usb_driver
= {
423 .name
= "intel_pmc_usb",
424 .acpi_match_table
= ACPI_PTR(pmc_usb_acpi_ids
),
426 .probe
= pmc_usb_probe
,
427 .remove
= pmc_usb_remove
,
430 module_platform_driver(pmc_usb_driver
);
432 MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
433 MODULE_LICENSE("GPL v2");
434 MODULE_DESCRIPTION("Intel PMC USB mux control");