1414#include <linux/soc/qcom/pdr.h>
1515#include <drm/bridge/aux-bridge.h>
1616
17+ #include <linux/usb/pd.h>
1718#include <linux/usb/typec_altmode.h>
1819#include <linux/usb/typec_dp.h>
1920#include <linux/usb/typec_mux.h>
2021#include <linux/usb/typec_retimer.h>
22+ #include <linux/usb/typec_tbt.h>
2123
2224#include <linux/soc/qcom/pmic_glink.h>
2325
@@ -37,11 +39,38 @@ struct usbc_write_req {
3739 __le32 reserved ;
3840};
3941
40- #define NOTIFY_PAYLOAD_SIZE 16
42+ struct usbc_sc8280x_dp_data {
43+ u8 pin_assignment : 6 ;
44+ u8 hpd_state : 1 ;
45+ u8 hpd_irq : 1 ;
46+ u8 res [7 ];
47+ };
48+
49+ /* Used for both TBT and USB4 notifications */
50+ struct usbc_sc8280x_tbt_data {
51+ u8 usb_speed : 3 ;
52+ u8 cable_type : 3 ;
53+ /* This field is NOP on USB4, all cables support rounded rates by spec */
54+ u8 rounded_cable : 1 ;
55+ u8 power_limited : 1 ;
56+ u8 res [11 ];
57+ };
58+
4159struct usbc_notify {
4260 struct pmic_glink_hdr hdr ;
43- char payload [NOTIFY_PAYLOAD_SIZE ];
44- u32 reserved ;
61+ u8 port_idx ;
62+ u8 orientation ;
63+ u8 mux_ctrl ;
64+ #define MUX_CTRL_STATE_NO_CONN 0
65+ #define MUX_CTRL_STATE_TUNNELING 4
66+
67+ u8 res ;
68+ __le16 vid ;
69+ __le16 svid ;
70+ union usbc_sc8280x_extended_data {
71+ struct usbc_sc8280x_dp_data dp ;
72+ struct usbc_sc8280x_tbt_data tbt ;
73+ } extended_data ;
4574};
4675
4776struct usbc_sc8180x_notify {
@@ -74,17 +103,20 @@ struct pmic_glink_altmode_port {
74103 struct typec_retimer * typec_retimer ;
75104 struct typec_retimer_state retimer_state ;
76105 struct typec_altmode dp_alt ;
106+ struct typec_altmode tbt_alt ;
77107
78108 struct work_struct work ;
79109
80110 struct auxiliary_device * bridge ;
81111
82112 enum typec_orientation orientation ;
83113 u16 svid ;
114+ struct usbc_sc8280x_tbt_data tbt_data ;
84115 u8 dp_data ;
85116 u8 mode ;
86117 u8 hpd_state ;
87118 u8 hpd_irq ;
119+ u8 mux_ctrl ;
88120};
89121
90122#define work_to_altmode (w ) container_of((w), struct pmic_glink_altmode, enable_work)
@@ -170,6 +202,102 @@ static void pmic_glink_altmode_enable_dp(struct pmic_glink_altmode *altmode,
170202 dev_err (altmode -> dev , "failed to setup retimer to DP: %d\n" , ret );
171203}
172204
205+ static void pmic_glink_altmode_enable_tbt (struct pmic_glink_altmode * altmode ,
206+ struct pmic_glink_altmode_port * port )
207+ {
208+ struct usbc_sc8280x_tbt_data * tbt = & port -> tbt_data ;
209+ struct typec_thunderbolt_data tbt_data = {};
210+ u32 cable_speed ;
211+ int ret ;
212+
213+ /* Device Discover Mode VDO */
214+ tbt_data .device_mode = TBT_MODE ;
215+ tbt_data .device_mode |= TBT_SET_ADAPTER (TBT_ADAPTER_TBT3 );
216+
217+ /* Cable Discover Mode VDO */
218+ tbt_data .cable_mode = TBT_MODE ;
219+
220+ if (tbt -> usb_speed == 0 ) {
221+ cable_speed = TBT_CABLE_USB3_PASSIVE ;
222+ } else if (tbt -> usb_speed == 1 ) {
223+ cable_speed = TBT_CABLE_10_AND_20GBPS ;
224+ } else {
225+ dev_err (altmode -> dev ,
226+ "Got illegal TBT3 cable speed value (%u), falling back to passive\n" ,
227+ tbt -> usb_speed );
228+ cable_speed = TBT_CABLE_USB3_PASSIVE ;
229+ }
230+ tbt_data .cable_mode |= TBT_SET_CABLE_SPEED (cable_speed );
231+
232+ if (tbt -> cable_type ) {
233+ tbt_data .cable_mode |= TBT_CABLE_ACTIVE_PASSIVE ;
234+ tbt_data .cable_mode |= TBT_SET_CABLE_ROUNDED (tbt -> rounded_cable );
235+ }
236+
237+ /* Enter Mode VDO */
238+ tbt_data .enter_vdo |= TBT_MODE ;
239+ tbt_data .enter_vdo |= TBT_ENTER_MODE_CABLE_SPEED (cable_speed );
240+
241+ if (tbt -> cable_type ) {
242+ tbt_data .enter_vdo |= TBT_CABLE_ACTIVE_PASSIVE ;
243+ tbt_data .enter_vdo |= TBT_SET_CABLE_ROUNDED (tbt -> rounded_cable );
244+ }
245+
246+ port -> state .alt = & port -> tbt_alt ;
247+ port -> state .data = & tbt_data ;
248+ port -> state .mode = TYPEC_MODAL_STATE (port -> mode );
249+
250+ ret = typec_mux_set (port -> typec_mux , & port -> state );
251+ if (ret )
252+ dev_err (altmode -> dev , "failed to switch mux to USB: %d\n" , ret );
253+
254+ port -> retimer_state .alt = & port -> tbt_alt ;
255+ port -> retimer_state .data = & tbt_data ;
256+ port -> retimer_state .mode = TYPEC_MODAL_STATE (port -> mode );
257+
258+ ret = typec_retimer_set (port -> typec_retimer , & port -> retimer_state );
259+ if (ret )
260+ dev_err (altmode -> dev , "failed to setup retimer to USB: %d\n" , ret );
261+ }
262+
263+ static void pmic_glink_altmode_enable_usb4 (struct pmic_glink_altmode * altmode ,
264+ struct pmic_glink_altmode_port * port )
265+ {
266+ struct usbc_sc8280x_tbt_data * tbt = & port -> tbt_data ;
267+ struct enter_usb_data data = {};
268+ int ret ;
269+
270+ data .eudo = FIELD_PREP (EUDO_USB_MODE_MASK , EUDO_USB_MODE_USB4 );
271+
272+ if (tbt -> usb_speed == 0 ) {
273+ data .eudo |= FIELD_PREP (EUDO_CABLE_SPEED_MASK , EUDO_CABLE_SPEED_USB4_GEN2 );
274+ } else if (tbt -> usb_speed == 1 ) {
275+ data .eudo |= FIELD_PREP (EUDO_CABLE_SPEED_MASK , EUDO_CABLE_SPEED_USB4_GEN3 );
276+ } else {
277+ pr_err ("Got illegal USB4 cable speed value (%u), falling back to G2\n" ,
278+ tbt -> usb_speed );
279+ data .eudo |= FIELD_PREP (EUDO_CABLE_SPEED_MASK , EUDO_CABLE_SPEED_USB4_GEN2 );
280+ }
281+
282+ data .eudo |= FIELD_PREP (EUDO_CABLE_TYPE_MASK , tbt -> cable_type );
283+
284+ port -> state .alt = NULL ;
285+ port -> state .data = & data ;
286+ port -> state .mode = TYPEC_MODE_USB4 ;
287+
288+ ret = typec_mux_set (port -> typec_mux , & port -> state );
289+ if (ret )
290+ dev_err (altmode -> dev , "failed to switch mux to USB: %d\n" , ret );
291+
292+ port -> retimer_state .alt = NULL ;
293+ port -> retimer_state .data = & data ;
294+ port -> retimer_state .mode = TYPEC_MODE_USB4 ;
295+
296+ ret = typec_retimer_set (port -> typec_retimer , & port -> retimer_state );
297+ if (ret )
298+ dev_err (altmode -> dev , "failed to setup retimer to USB: %d\n" , ret );
299+ }
300+
173301static void pmic_glink_altmode_enable_usb (struct pmic_glink_altmode * altmode ,
174302 struct pmic_glink_altmode_port * port )
175303{
@@ -222,22 +350,24 @@ static void pmic_glink_altmode_worker(struct work_struct *work)
222350
223351 typec_switch_set (alt_port -> typec_switch , alt_port -> orientation );
224352
225- if (alt_port -> svid == USB_TYPEC_DP_SID ) {
226- if ( alt_port -> mode == 0xff ) {
227- pmic_glink_altmode_safe ( altmode , alt_port );
228- } else {
229- pmic_glink_altmode_enable_dp ( altmode , alt_port ,
230- alt_port -> mode ,
231- alt_port -> hpd_state ,
232- alt_port -> hpd_irq );
233- }
353+ if (alt_port -> mux_ctrl == MUX_CTRL_STATE_NO_CONN ) {
354+ pmic_glink_altmode_safe ( altmode , alt_port );
355+ } else if ( alt_port -> svid == USB_TYPEC_TBT_SID ) {
356+ pmic_glink_altmode_enable_tbt ( altmode , alt_port );
357+ } else if ( alt_port -> svid == USB_TYPEC_DP_SID ) {
358+ pmic_glink_altmode_enable_dp ( altmode , alt_port ,
359+ alt_port -> mode ,
360+ alt_port -> hpd_state ,
361+ alt_port -> hpd_irq );
234362
235363 if (alt_port -> hpd_state )
236364 conn_status = connector_status_connected ;
237365 else
238366 conn_status = connector_status_disconnected ;
239367
240368 drm_aux_hpd_bridge_notify (& alt_port -> bridge -> dev , conn_status );
369+ } else if (alt_port -> mux_ctrl == MUX_CTRL_STATE_TUNNELING ) {
370+ pmic_glink_altmode_enable_usb4 (altmode , alt_port );
241371 } else {
242372 pmic_glink_altmode_enable_usb (altmode , alt_port );
243373 }
@@ -314,11 +444,10 @@ static void pmic_glink_altmode_sc8280xp_notify(struct pmic_glink_altmode *altmod
314444 u16 svid , const void * data , size_t len )
315445{
316446 struct pmic_glink_altmode_port * alt_port ;
447+ const struct usbc_sc8280x_tbt_data * tbt ;
448+ const struct usbc_sc8280x_dp_data * dp ;
317449 const struct usbc_notify * notify ;
318450 u8 orientation ;
319- u8 hpd_state ;
320- u8 hpd_irq ;
321- u8 mode ;
322451 u8 port ;
323452
324453 if (len != sizeof (* notify )) {
@@ -329,11 +458,8 @@ static void pmic_glink_altmode_sc8280xp_notify(struct pmic_glink_altmode *altmod
329458
330459 notify = data ;
331460
332- port = notify -> payload [0 ];
333- orientation = notify -> payload [1 ];
334- mode = FIELD_GET (SC8280XP_DPAM_MASK , notify -> payload [8 ]) - DPAM_HPD_A ;
335- hpd_state = FIELD_GET (SC8280XP_HPD_STATE_MASK , notify -> payload [8 ]);
336- hpd_irq = FIELD_GET (SC8280XP_HPD_IRQ_MASK , notify -> payload [8 ]);
461+ port = notify -> port_idx ;
462+ orientation = notify -> orientation ;
337463
338464 if (port >= ARRAY_SIZE (altmode -> ports ) || !altmode -> ports [port ].altmode ) {
339465 dev_dbg (altmode -> dev , "notification on undefined port %d\n" , port );
@@ -343,9 +469,21 @@ static void pmic_glink_altmode_sc8280xp_notify(struct pmic_glink_altmode *altmod
343469 alt_port = & altmode -> ports [port ];
344470 alt_port -> orientation = pmic_glink_altmode_orientation (orientation );
345471 alt_port -> svid = svid ;
346- alt_port -> mode = mode ;
347- alt_port -> hpd_state = hpd_state ;
348- alt_port -> hpd_irq = hpd_irq ;
472+ alt_port -> mux_ctrl = notify -> mux_ctrl ;
473+
474+ if (svid == USB_TYPEC_DP_SID ) {
475+ dp = & notify -> extended_data .dp ;
476+
477+ alt_port -> mode = dp -> pin_assignment - DPAM_HPD_A ;
478+ alt_port -> hpd_state = dp -> hpd_state ;
479+ alt_port -> hpd_irq = dp -> hpd_irq ;
480+ } else if (alt_port -> mux_ctrl == MUX_CTRL_STATE_TUNNELING ) {
481+ /* Valid for both USB4 and TBT3 */
482+ tbt = & notify -> extended_data .tbt ;
483+
484+ alt_port -> tbt_data = * tbt ;
485+ }
486+
349487 schedule_work (& alt_port -> work );
350488}
351489
@@ -471,6 +609,10 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev,
471609 alt_port -> dp_alt .mode = USB_TYPEC_DP_MODE ;
472610 alt_port -> dp_alt .active = 1 ;
473611
612+ alt_port -> tbt_alt .svid = USB_TYPEC_TBT_SID ;
613+ alt_port -> tbt_alt .mode = TYPEC_TBT_MODE ;
614+ alt_port -> tbt_alt .active = 1 ;
615+
474616 alt_port -> typec_mux = fwnode_typec_mux_get (fwnode );
475617 if (IS_ERR (alt_port -> typec_mux )) {
476618 fwnode_handle_put (fwnode );
0 commit comments