aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/typec/tcpm.c60
1 files changed, 34 insertions, 26 deletions
diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index 8d3a9ad118aa..a15256c190e7 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -115,7 +115,8 @@
115 S(BIST_RX), \ 115 S(BIST_RX), \
116 \ 116 \
117 S(ERROR_RECOVERY), \ 117 S(ERROR_RECOVERY), \
118 S(ERROR_RECOVERY_WAIT_OFF) 118 S(PORT_RESET), \
119 S(PORT_RESET_WAIT_OFF)
119 120
120#define GENERATE_ENUM(e) e 121#define GENERATE_ENUM(e) e
121#define GENERATE_STRING(s) #s 122#define GENERATE_STRING(s) #s
@@ -230,6 +231,7 @@ struct tcpm_port {
230 231
231 struct mutex swap_lock; /* swap command lock */ 232 struct mutex swap_lock; /* swap command lock */
232 bool swap_pending; 233 bool swap_pending;
234 bool non_pd_role_swap;
233 struct completion swap_complete; 235 struct completion swap_complete;
234 int swap_status; 236 int swap_status;
235 237
@@ -2123,6 +2125,7 @@ static void tcpm_swap_complete(struct tcpm_port *port, int result)
2123 if (port->swap_pending) { 2125 if (port->swap_pending) {
2124 port->swap_status = result; 2126 port->swap_status = result;
2125 port->swap_pending = false; 2127 port->swap_pending = false;
2128 port->non_pd_role_swap = false;
2126 complete(&port->swap_complete); 2129 complete(&port->swap_complete);
2127 } 2130 }
2128} 2131}
@@ -2137,7 +2140,8 @@ static void run_state_machine(struct tcpm_port *port)
2137 break; 2140 break;
2138 /* SRC states */ 2141 /* SRC states */
2139 case SRC_UNATTACHED: 2142 case SRC_UNATTACHED:
2140 tcpm_swap_complete(port, -ENOTCONN); 2143 if (!port->non_pd_role_swap)
2144 tcpm_swap_complete(port, -ENOTCONN);
2141 tcpm_src_detach(port); 2145 tcpm_src_detach(port);
2142 if (tcpm_start_drp_toggling(port)) { 2146 if (tcpm_start_drp_toggling(port)) {
2143 tcpm_set_state(port, DRP_TOGGLING, 0); 2147 tcpm_set_state(port, DRP_TOGGLING, 0);
@@ -2292,7 +2296,8 @@ static void run_state_machine(struct tcpm_port *port)
2292 2296
2293 /* SNK states */ 2297 /* SNK states */
2294 case SNK_UNATTACHED: 2298 case SNK_UNATTACHED:
2295 tcpm_swap_complete(port, -ENOTCONN); 2299 if (!port->non_pd_role_swap)
2300 tcpm_swap_complete(port, -ENOTCONN);
2296 tcpm_snk_detach(port); 2301 tcpm_snk_detach(port);
2297 if (tcpm_start_drp_toggling(port)) { 2302 if (tcpm_start_drp_toggling(port)) {
2298 tcpm_set_state(port, DRP_TOGGLING, 0); 2303 tcpm_set_state(port, DRP_TOGGLING, 0);
@@ -2703,13 +2708,15 @@ static void run_state_machine(struct tcpm_port *port)
2703 break; 2708 break;
2704 case ERROR_RECOVERY: 2709 case ERROR_RECOVERY:
2705 tcpm_swap_complete(port, -EPROTO); 2710 tcpm_swap_complete(port, -EPROTO);
2711 tcpm_set_state(port, PORT_RESET, 0);
2712 break;
2713 case PORT_RESET:
2706 tcpm_reset_port(port); 2714 tcpm_reset_port(port);
2707
2708 tcpm_set_cc(port, TYPEC_CC_OPEN); 2715 tcpm_set_cc(port, TYPEC_CC_OPEN);
2709 tcpm_set_state(port, ERROR_RECOVERY_WAIT_OFF, 2716 tcpm_set_state(port, PORT_RESET_WAIT_OFF,
2710 PD_T_ERROR_RECOVERY); 2717 PD_T_ERROR_RECOVERY);
2711 break; 2718 break;
2712 case ERROR_RECOVERY_WAIT_OFF: 2719 case PORT_RESET_WAIT_OFF:
2713 tcpm_set_state(port, 2720 tcpm_set_state(port,
2714 tcpm_default_state(port), 2721 tcpm_default_state(port),
2715 port->vbus_present ? PD_T_PS_SOURCE_OFF : 0); 2722 port->vbus_present ? PD_T_PS_SOURCE_OFF : 0);
@@ -3041,7 +3048,7 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
3041 /* Do nothing, expected */ 3048 /* Do nothing, expected */
3042 break; 3049 break;
3043 3050
3044 case ERROR_RECOVERY_WAIT_OFF: 3051 case PORT_RESET_WAIT_OFF:
3045 tcpm_set_state(port, tcpm_default_state(port), 0); 3052 tcpm_set_state(port, tcpm_default_state(port), 0);
3046 break; 3053 break;
3047 3054
@@ -3138,7 +3145,7 @@ static int tcpm_dr_set(const struct typec_capability *cap,
3138 mutex_lock(&port->swap_lock); 3145 mutex_lock(&port->swap_lock);
3139 mutex_lock(&port->lock); 3146 mutex_lock(&port->lock);
3140 3147
3141 if (port->typec_caps.type != TYPEC_PORT_DRP || !port->pd_capable) { 3148 if (port->typec_caps.type != TYPEC_PORT_DRP) {
3142 ret = -EINVAL; 3149 ret = -EINVAL;
3143 goto port_unlock; 3150 goto port_unlock;
3144 } 3151 }
@@ -3159,10 +3166,26 @@ static int tcpm_dr_set(const struct typec_capability *cap,
3159 * Reject data role swap request in this case. 3166 * Reject data role swap request in this case.
3160 */ 3167 */
3161 3168
3169 if (!port->pd_capable) {
3170 /*
3171 * If the partner is not PD capable, reset the port to
3172 * trigger a role change. This can only work if a preferred
3173 * role is configured, and if it matches the requested role.
3174 */
3175 if (port->try_role == TYPEC_NO_PREFERRED_ROLE ||
3176 port->try_role == port->pwr_role) {
3177 ret = -EINVAL;
3178 goto port_unlock;
3179 }
3180 port->non_pd_role_swap = true;
3181 tcpm_set_state(port, PORT_RESET, 0);
3182 } else {
3183 tcpm_set_state(port, DR_SWAP_SEND, 0);
3184 }
3185
3162 port->swap_status = 0; 3186 port->swap_status = 0;
3163 port->swap_pending = true; 3187 port->swap_pending = true;
3164 reinit_completion(&port->swap_complete); 3188 reinit_completion(&port->swap_complete);
3165 tcpm_set_state(port, DR_SWAP_SEND, 0);
3166 mutex_unlock(&port->lock); 3189 mutex_unlock(&port->lock);
3167 3190
3168 if (!wait_for_completion_timeout(&port->swap_complete, 3191 if (!wait_for_completion_timeout(&port->swap_complete,
@@ -3171,6 +3194,7 @@ static int tcpm_dr_set(const struct typec_capability *cap,
3171 else 3194 else
3172 ret = port->swap_status; 3195 ret = port->swap_status;
3173 3196
3197 port->non_pd_role_swap = false;
3174 goto swap_unlock; 3198 goto swap_unlock;
3175 3199
3176port_unlock: 3200port_unlock:
@@ -3203,22 +3227,6 @@ static int tcpm_pr_set(const struct typec_capability *cap,
3203 goto port_unlock; 3227 goto port_unlock;
3204 } 3228 }
3205 3229
3206 if (!port->pd_capable) {
3207 /*
3208 * If the partner is not PD capable, reset the port to
3209 * trigger a role change. This can only work if a preferred
3210 * role is configured, and if it matches the requested role.
3211 */
3212 if (port->try_role == TYPEC_NO_PREFERRED_ROLE ||
3213 port->try_role == port->pwr_role) {
3214 ret = -EINVAL;
3215 goto port_unlock;
3216 }
3217 tcpm_set_state(port, HARD_RESET_SEND, 0);
3218 ret = 0;
3219 goto port_unlock;
3220 }
3221
3222 port->swap_status = 0; 3230 port->swap_status = 0;
3223 port->swap_pending = true; 3231 port->swap_pending = true;
3224 reinit_completion(&port->swap_complete); 3232 reinit_completion(&port->swap_complete);
@@ -3324,7 +3332,7 @@ static void tcpm_init(struct tcpm_port *port)
3324 * Some adapters need a clean slate at startup, and won't recover 3332 * Some adapters need a clean slate at startup, and won't recover
3325 * otherwise. So do not try to be fancy and force a clean disconnect. 3333 * otherwise. So do not try to be fancy and force a clean disconnect.
3326 */ 3334 */
3327 tcpm_set_state(port, ERROR_RECOVERY, 0); 3335 tcpm_set_state(port, PORT_RESET, 0);
3328} 3336}
3329 3337
3330void tcpm_tcpc_reset(struct tcpm_port *port) 3338void tcpm_tcpc_reset(struct tcpm_port *port)