Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: typec: Give the mux drivers all the details regarding the port state

Passing all the details that the alternate mode drivers
provide to the mux drivers during mode changes.

The mux drivers will in practice need to be able to make
decisions on their own. It is not enough that they get only
the requested port state. With the Thunderbolt 3 alternate
mode for example the mux driver will need to consider also
the capabilities of the cable before configuring the mux.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20191230142611.24921-13-heikki.krogerus@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Heikki Krogerus and committed by
Greg Kroah-Hartman
87e3daa0 0ac53493

+37 -13
+20 -9
drivers/usb/typec/bus.c
··· 10 10 11 11 #include "bus.h" 12 12 13 - static inline int typec_altmode_set_mux(struct altmode *alt, u8 state) 13 + static inline int 14 + typec_altmode_set_mux(struct altmode *alt, unsigned long conf, void *data) 14 15 { 15 - return alt->mux ? alt->mux->set(alt->mux, state) : 0; 16 + struct typec_mux_state state; 17 + 18 + if (!alt->mux) 19 + return 0; 20 + 21 + state.alt = &alt->adev; 22 + state.mode = conf; 23 + state.data = data; 24 + 25 + return alt->mux->set(alt->mux, &state); 16 26 } 17 27 18 - static int typec_altmode_set_state(struct typec_altmode *adev, int state) 28 + static int typec_altmode_set_state(struct typec_altmode *adev, 29 + unsigned long conf, void *data) 19 30 { 20 31 bool is_port = is_typec_port(adev->dev.parent); 21 32 struct altmode *port_altmode; ··· 34 23 35 24 port_altmode = is_port ? to_altmode(adev) : to_altmode(adev)->partner; 36 25 37 - ret = typec_altmode_set_mux(port_altmode, state); 26 + ret = typec_altmode_set_mux(port_altmode, conf, data); 38 27 if (ret) 39 28 return ret; 40 29 41 - blocking_notifier_call_chain(&port_altmode->nh, state, NULL); 30 + blocking_notifier_call_chain(&port_altmode->nh, conf, NULL); 42 31 43 32 return 0; 44 33 } ··· 78 67 is_port = is_typec_port(adev->dev.parent); 79 68 partner = altmode->partner; 80 69 81 - ret = typec_altmode_set_mux(is_port ? altmode : partner, (u8)conf); 70 + ret = typec_altmode_set_mux(is_port ? altmode : partner, conf, data); 82 71 if (ret) 83 72 return ret; 84 73 ··· 118 107 return -EPERM; 119 108 120 109 /* Moving to USB Safe State */ 121 - ret = typec_altmode_set_state(adev, TYPEC_STATE_SAFE); 110 + ret = typec_altmode_set_state(adev, TYPEC_STATE_SAFE, NULL); 122 111 if (ret) 123 112 return ret; 124 113 ··· 146 135 return -EOPNOTSUPP; 147 136 148 137 /* Moving to USB Safe State */ 149 - ret = typec_altmode_set_state(adev, TYPEC_STATE_SAFE); 138 + ret = typec_altmode_set_state(adev, TYPEC_STATE_SAFE, NULL); 150 139 if (ret) 151 140 return ret; 152 141 ··· 399 388 drv->remove(to_typec_altmode(dev)); 400 389 401 390 if (adev->active) { 402 - WARN_ON(typec_altmode_set_state(adev, TYPEC_STATE_SAFE)); 391 + WARN_ON(typec_altmode_set_state(adev, TYPEC_STATE_SAFE, NULL)); 403 392 typec_altmode_update_active(adev, false); 404 393 } 405 394
+5 -1
drivers/usb/typec/class.c
··· 1529 1529 */ 1530 1530 int typec_set_mode(struct typec_port *port, int mode) 1531 1531 { 1532 - return port->mux ? port->mux->set(port->mux, mode) : 0; 1532 + struct typec_mux_state state = { }; 1533 + 1534 + state.mode = mode; 1535 + 1536 + return port->mux ? port->mux->set(port->mux, &state) : 0; 1533 1537 } 1534 1538 EXPORT_SYMBOL_GPL(typec_set_mode); 1535 1539
+3 -2
drivers/usb/typec/mux/pi3usb30532.c
··· 73 73 return ret; 74 74 } 75 75 76 - static int pi3usb30532_mux_set(struct typec_mux *mux, int state) 76 + static int 77 + pi3usb30532_mux_set(struct typec_mux *mux, struct typec_mux_state *state) 77 78 { 78 79 struct pi3usb30532 *pi = typec_mux_get_drvdata(mux); 79 80 u8 new_conf; ··· 83 82 mutex_lock(&pi->lock); 84 83 new_conf = pi->conf; 85 84 86 - switch (state) { 85 + switch (state->mode) { 87 86 case TYPEC_STATE_SAFE: 88 87 new_conf = (new_conf & PI3USB30532_CONF_SWAP) | 89 88 PI3USB30532_CONF_OPEN;
+9 -1
include/linux/usb/typec_mux.h
··· 8 8 struct device; 9 9 struct typec_mux; 10 10 struct typec_switch; 11 + struct typec_altmode; 11 12 struct fwnode_handle; 12 13 13 14 typedef int (*typec_switch_set_fn_t)(struct typec_switch *sw, ··· 30 29 void typec_switch_set_drvdata(struct typec_switch *sw, void *data); 31 30 void *typec_switch_get_drvdata(struct typec_switch *sw); 32 31 33 - typedef int (*typec_mux_set_fn_t)(struct typec_mux *mux, int state); 32 + struct typec_mux_state { 33 + struct typec_altmode *alt; 34 + unsigned long mode; 35 + void *data; 36 + }; 37 + 38 + typedef int (*typec_mux_set_fn_t)(struct typec_mux *mux, 39 + struct typec_mux_state *state); 34 40 35 41 struct typec_mux_desc { 36 42 struct fwnode_handle *fwnode;