26
26
#include <linux/usb/pd_vdo.h>
27
27
#include <linux/usb/role.h>
28
28
#include <linux/usb/tcpm.h>
29
- #include <linux/usb/typec .h>
29
+ #include <linux/usb/typec_altmode .h>
30
30
#include <linux/workqueue.h>
31
31
32
32
#define FOREACH_STATE (S ) \
@@ -169,13 +169,14 @@ enum pd_msg_request {
169
169
/* Alternate mode support */
170
170
171
171
#define SVID_DISCOVERY_MAX 16
172
+ #define ALTMODE_DISCOVERY_MAX (SVID_DISCOVERY_MAX * MODE_DISCOVERY_MAX)
172
173
173
174
struct pd_mode_data {
174
175
int svid_index ; /* current SVID index */
175
176
int nsvids ;
176
177
u16 svids [SVID_DISCOVERY_MAX ];
177
178
int altmodes ; /* number of alternate modes */
178
- struct typec_altmode_desc altmode_desc [SVID_DISCOVERY_MAX ];
179
+ struct typec_altmode_desc altmode_desc [ALTMODE_DISCOVERY_MAX ];
179
180
};
180
181
181
182
struct pd_pps_data {
@@ -310,8 +311,8 @@ struct tcpm_port {
310
311
311
312
/* Alternate mode data */
312
313
struct pd_mode_data mode_data ;
313
- struct typec_altmode * partner_altmode [SVID_DISCOVERY_MAX * 6 ];
314
- struct typec_altmode * port_altmode [SVID_DISCOVERY_MAX * 6 ];
314
+ struct typec_altmode * partner_altmode [ALTMODE_DISCOVERY_MAX ];
315
+ struct typec_altmode * port_altmode [ALTMODE_DISCOVERY_MAX ];
315
316
316
317
/* Deadline in jiffies to exit src_try_wait state */
317
318
unsigned long max_wait ;
@@ -641,14 +642,14 @@ void tcpm_pd_transmit_complete(struct tcpm_port *port,
641
642
}
642
643
EXPORT_SYMBOL_GPL (tcpm_pd_transmit_complete );
643
644
644
- static int tcpm_mux_set (struct tcpm_port * port , enum tcpc_mux_mode mode ,
645
+ static int tcpm_mux_set (struct tcpm_port * port , int state ,
645
646
enum usb_role usb_role ,
646
647
enum typec_orientation orientation )
647
648
{
648
649
int ret ;
649
650
650
- tcpm_log (port , "Requesting mux mode %d, usb-role %d, orientation %d" ,
651
- mode , usb_role , orientation );
651
+ tcpm_log (port , "Requesting mux state %d, usb-role %d, orientation %d" ,
652
+ state , usb_role , orientation );
652
653
653
654
ret = typec_set_orientation (port -> typec_port , orientation );
654
655
if (ret )
@@ -660,7 +661,7 @@ static int tcpm_mux_set(struct tcpm_port *port, enum tcpc_mux_mode mode,
660
661
return ret ;
661
662
}
662
663
663
- return typec_set_mode (port -> typec_port , mode );
664
+ return typec_set_mode (port -> typec_port , state );
664
665
}
665
666
666
667
static int tcpm_set_polarity (struct tcpm_port * port ,
@@ -787,7 +788,7 @@ static int tcpm_set_roles(struct tcpm_port *port, bool attached,
787
788
else
788
789
usb_role = USB_ROLE_DEVICE ;
789
790
790
- ret = tcpm_mux_set (port , TYPEC_MUX_USB , usb_role , orientation );
791
+ ret = tcpm_mux_set (port , TYPEC_STATE_USB , usb_role , orientation );
791
792
if (ret < 0 )
792
793
return ret ;
793
794
@@ -1014,36 +1015,57 @@ static void svdm_consume_modes(struct tcpm_port *port, const __le32 *payload,
1014
1015
pmdata -> altmodes , paltmode -> svid ,
1015
1016
paltmode -> mode , paltmode -> vdo );
1016
1017
1017
- port -> partner_altmode [pmdata -> altmodes ] =
1018
- typec_partner_register_altmode (port -> partner , paltmode );
1019
- if (!port -> partner_altmode [pmdata -> altmodes ]) {
1020
- tcpm_log (port ,
1021
- "Failed to register modes for SVID 0x%04x" ,
1022
- paltmode -> svid );
1023
- return ;
1024
- }
1025
1018
pmdata -> altmodes ++ ;
1026
1019
}
1027
1020
}
1028
1021
1022
+ static void tcpm_register_partner_altmodes (struct tcpm_port * port )
1023
+ {
1024
+ struct pd_mode_data * modep = & port -> mode_data ;
1025
+ struct typec_altmode * altmode ;
1026
+ int i ;
1027
+
1028
+ for (i = 0 ; i < modep -> altmodes ; i ++ ) {
1029
+ altmode = typec_partner_register_altmode (port -> partner ,
1030
+ & modep -> altmode_desc [i ]);
1031
+ if (!altmode )
1032
+ tcpm_log (port , "Failed to register partner SVID 0x%04x" ,
1033
+ modep -> altmode_desc [i ].svid );
1034
+ port -> partner_altmode [i ] = altmode ;
1035
+ }
1036
+ }
1037
+
1029
1038
#define supports_modal (port ) PD_IDH_MODAL_SUPP((port)->partner_ident.id_header)
1030
1039
1031
1040
static int tcpm_pd_svdm (struct tcpm_port * port , const __le32 * payload , int cnt ,
1032
1041
u32 * response )
1033
1042
{
1034
- u32 p0 = le32_to_cpu (payload [0 ]);
1035
- int cmd_type = PD_VDO_CMDT (p0 );
1036
- int cmd = PD_VDO_CMD (p0 );
1043
+ struct typec_altmode * adev ;
1044
+ struct typec_altmode * pdev ;
1037
1045
struct pd_mode_data * modep ;
1046
+ u32 p [PD_MAX_PAYLOAD ];
1038
1047
int rlen = 0 ;
1039
- u16 svid ;
1048
+ int cmd_type ;
1049
+ int cmd ;
1040
1050
int i ;
1041
1051
1052
+ for (i = 0 ; i < cnt ; i ++ )
1053
+ p [i ] = le32_to_cpu (payload [i ]);
1054
+
1055
+ cmd_type = PD_VDO_CMDT (p [0 ]);
1056
+ cmd = PD_VDO_CMD (p [0 ]);
1057
+
1042
1058
tcpm_log (port , "Rx VDM cmd 0x%x type %d cmd %d len %d" ,
1043
- p0 , cmd_type , cmd , cnt );
1059
+ p [ 0 ] , cmd_type , cmd , cnt );
1044
1060
1045
1061
modep = & port -> mode_data ;
1046
1062
1063
+ adev = typec_match_altmode (port -> port_altmode , ALTMODE_DISCOVERY_MAX ,
1064
+ PD_VDO_VID (p [0 ]), PD_VDO_OPOS (p [0 ]));
1065
+
1066
+ pdev = typec_match_altmode (port -> partner_altmode , ALTMODE_DISCOVERY_MAX ,
1067
+ PD_VDO_VID (p [0 ]), PD_VDO_OPOS (p [0 ]));
1068
+
1047
1069
switch (cmd_type ) {
1048
1070
case CMDT_INIT :
1049
1071
switch (cmd ) {
@@ -1065,17 +1087,19 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
1065
1087
case CMD_EXIT_MODE :
1066
1088
break ;
1067
1089
case CMD_ATTENTION :
1068
- break ;
1090
+ /* Attention command does not have response */
1091
+ typec_altmode_attention (adev , p [1 ]);
1092
+ return 0 ;
1069
1093
default :
1070
1094
break ;
1071
1095
}
1072
1096
if (rlen >= 1 ) {
1073
- response [0 ] = p0 | VDO_CMDT (CMDT_RSP_ACK );
1097
+ response [0 ] = p [ 0 ] | VDO_CMDT (CMDT_RSP_ACK );
1074
1098
} else if (rlen == 0 ) {
1075
- response [0 ] = p0 | VDO_CMDT (CMDT_RSP_NAK );
1099
+ response [0 ] = p [ 0 ] | VDO_CMDT (CMDT_RSP_NAK );
1076
1100
rlen = 1 ;
1077
1101
} else {
1078
- response [0 ] = p0 | VDO_CMDT (CMDT_RSP_BUSY );
1102
+ response [0 ] = p [ 0 ] | VDO_CMDT (CMDT_RSP_BUSY );
1079
1103
rlen = 1 ;
1080
1104
}
1081
1105
break ;
@@ -1108,14 +1132,39 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
1108
1132
svdm_consume_modes (port , payload , cnt );
1109
1133
modep -> svid_index ++ ;
1110
1134
if (modep -> svid_index < modep -> nsvids ) {
1111
- svid = modep -> svids [modep -> svid_index ];
1135
+ u16 svid = modep -> svids [modep -> svid_index ];
1112
1136
response [0 ] = VDO (svid , 1 , CMD_DISCOVER_MODES );
1113
1137
rlen = 1 ;
1114
1138
} else {
1115
- /* enter alternate mode if/when implemented */
1139
+ tcpm_register_partner_altmodes ( port );
1116
1140
}
1117
1141
break ;
1118
1142
case CMD_ENTER_MODE :
1143
+ typec_altmode_update_active (pdev , true);
1144
+
1145
+ if (typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt )) {
1146
+ response [0 ] = VDO (adev -> svid , 1 , CMD_EXIT_MODE );
1147
+ response [0 ] |= VDO_OPOS (adev -> mode );
1148
+ return 1 ;
1149
+ }
1150
+ return 0 ;
1151
+ case CMD_EXIT_MODE :
1152
+ typec_altmode_update_active (pdev , false);
1153
+
1154
+ /* Back to USB Operation */
1155
+ WARN_ON (typec_altmode_notify (adev , TYPEC_STATE_USB ,
1156
+ NULL ));
1157
+ break ;
1158
+ default :
1159
+ break ;
1160
+ }
1161
+ break ;
1162
+ case CMDT_RSP_NAK :
1163
+ switch (cmd ) {
1164
+ case CMD_ENTER_MODE :
1165
+ /* Back to USB Operation */
1166
+ WARN_ON (typec_altmode_notify (adev , TYPEC_STATE_USB ,
1167
+ NULL ));
1119
1168
break ;
1120
1169
default :
1121
1170
break ;
@@ -1125,6 +1174,9 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
1125
1174
break ;
1126
1175
}
1127
1176
1177
+ /* Informing the alternate mode drivers about everything */
1178
+ typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt );
1179
+
1128
1180
return rlen ;
1129
1181
}
1130
1182
@@ -1408,6 +1460,57 @@ static int tcpm_validate_caps(struct tcpm_port *port, const u32 *pdo,
1408
1460
return 0 ;
1409
1461
}
1410
1462
1463
+ static int tcpm_altmode_enter (struct typec_altmode * altmode )
1464
+ {
1465
+ struct tcpm_port * port = typec_altmode_get_drvdata (altmode );
1466
+ u32 header ;
1467
+
1468
+ mutex_lock (& port -> lock );
1469
+ header = VDO (altmode -> svid , 1 , CMD_ENTER_MODE );
1470
+ header |= VDO_OPOS (altmode -> mode );
1471
+
1472
+ tcpm_queue_vdm (port , header , NULL , 0 );
1473
+ mod_delayed_work (port -> wq , & port -> vdm_state_machine , 0 );
1474
+ mutex_unlock (& port -> lock );
1475
+
1476
+ return 0 ;
1477
+ }
1478
+
1479
+ static int tcpm_altmode_exit (struct typec_altmode * altmode )
1480
+ {
1481
+ struct tcpm_port * port = typec_altmode_get_drvdata (altmode );
1482
+ u32 header ;
1483
+
1484
+ mutex_lock (& port -> lock );
1485
+ header = VDO (altmode -> svid , 1 , CMD_EXIT_MODE );
1486
+ header |= VDO_OPOS (altmode -> mode );
1487
+
1488
+ tcpm_queue_vdm (port , header , NULL , 0 );
1489
+ mod_delayed_work (port -> wq , & port -> vdm_state_machine , 0 );
1490
+ mutex_unlock (& port -> lock );
1491
+
1492
+ return 0 ;
1493
+ }
1494
+
1495
+ static int tcpm_altmode_vdm (struct typec_altmode * altmode ,
1496
+ u32 header , const u32 * data , int count )
1497
+ {
1498
+ struct tcpm_port * port = typec_altmode_get_drvdata (altmode );
1499
+
1500
+ mutex_lock (& port -> lock );
1501
+ tcpm_queue_vdm (port , header , data , count - 1 );
1502
+ mod_delayed_work (port -> wq , & port -> vdm_state_machine , 0 );
1503
+ mutex_unlock (& port -> lock );
1504
+
1505
+ return 0 ;
1506
+ }
1507
+
1508
+ static const struct typec_altmode_ops tcpm_altmode_ops = {
1509
+ .enter = tcpm_altmode_enter ,
1510
+ .exit = tcpm_altmode_exit ,
1511
+ .vdm = tcpm_altmode_vdm ,
1512
+ };
1513
+
1411
1514
/*
1412
1515
* PD (data, control) command handling functions
1413
1516
*/
@@ -2539,7 +2642,7 @@ static int tcpm_src_attach(struct tcpm_port *port)
2539
2642
out_disable_pd :
2540
2643
port -> tcpc -> set_pd_rx (port -> tcpc , false);
2541
2644
out_disable_mux :
2542
- tcpm_mux_set (port , TYPEC_MUX_NONE , USB_ROLE_NONE ,
2645
+ tcpm_mux_set (port , TYPEC_STATE_SAFE , USB_ROLE_NONE ,
2543
2646
TYPEC_ORIENTATION_NONE );
2544
2647
return ret ;
2545
2648
}
@@ -2585,7 +2688,7 @@ static void tcpm_reset_port(struct tcpm_port *port)
2585
2688
tcpm_init_vconn (port );
2586
2689
tcpm_set_current_limit (port , 0 , 0 );
2587
2690
tcpm_set_polarity (port , TYPEC_POLARITY_CC1 );
2588
- tcpm_mux_set (port , TYPEC_MUX_NONE , USB_ROLE_NONE ,
2691
+ tcpm_mux_set (port , TYPEC_STATE_SAFE , USB_ROLE_NONE ,
2589
2692
TYPEC_ORIENTATION_NONE );
2590
2693
tcpm_set_attached_state (port , false);
2591
2694
port -> try_src_count = 0 ;
@@ -4706,6 +4809,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
4706
4809
dev_name (dev ), paltmode -> svid );
4707
4810
break ;
4708
4811
}
4812
+ typec_altmode_set_drvdata (alt , port );
4813
+ alt -> ops = & tcpm_altmode_ops ;
4709
4814
port -> port_altmode [i ] = alt ;
4710
4815
i ++ ;
4711
4816
paltmode ++ ;
0 commit comments