]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
usb: typec: Give the mux drivers all the details regarding the port state
authorHeikki Krogerus <heikki.krogerus@linux.intel.com>
Mon, 30 Dec 2019 14:26:08 +0000 (17:26 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jan 2020 09:50:13 +0000 (10:50 +0100)
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>
drivers/usb/typec/bus.c
drivers/usb/typec/class.c
drivers/usb/typec/mux/pi3usb30532.c
include/linux/usb/typec_mux.h

index e78c8a68c745245bf3da81ef3e0b1a146184661c..2e45eb479386febd043c077b33bdf1d036c801b5 100644 (file)
 
 #include "bus.h"
 
-static inline int typec_altmode_set_mux(struct altmode *alt, u8 state)
+static inline int
+typec_altmode_set_mux(struct altmode *alt, unsigned long conf, void *data)
 {
-       return alt->mux ? alt->mux->set(alt->mux, state) : 0;
+       struct typec_mux_state state;
+
+       if (!alt->mux)
+               return 0;
+
+       state.alt = &alt->adev;
+       state.mode = conf;
+       state.data = data;
+
+       return alt->mux->set(alt->mux, &state);
 }
 
-static int typec_altmode_set_state(struct typec_altmode *adev, int state)
+static int typec_altmode_set_state(struct typec_altmode *adev,
+                                  unsigned long conf, void *data)
 {
        bool is_port = is_typec_port(adev->dev.parent);
        struct altmode *port_altmode;
@@ -23,11 +34,11 @@ static int typec_altmode_set_state(struct typec_altmode *adev, int state)
 
        port_altmode = is_port ? to_altmode(adev) : to_altmode(adev)->partner;
 
-       ret = typec_altmode_set_mux(port_altmode, state);
+       ret = typec_altmode_set_mux(port_altmode, conf, data);
        if (ret)
                return ret;
 
-       blocking_notifier_call_chain(&port_altmode->nh, state, NULL);
+       blocking_notifier_call_chain(&port_altmode->nh, conf, NULL);
 
        return 0;
 }
@@ -67,7 +78,7 @@ int typec_altmode_notify(struct typec_altmode *adev,
        is_port = is_typec_port(adev->dev.parent);
        partner = altmode->partner;
 
-       ret = typec_altmode_set_mux(is_port ? altmode : partner, (u8)conf);
+       ret = typec_altmode_set_mux(is_port ? altmode : partner, conf, data);
        if (ret)
                return ret;
 
@@ -107,7 +118,7 @@ int typec_altmode_enter(struct typec_altmode *adev, u32 *vdo)
                return -EPERM;
 
        /* Moving to USB Safe State */
-       ret = typec_altmode_set_state(adev, TYPEC_STATE_SAFE);
+       ret = typec_altmode_set_state(adev, TYPEC_STATE_SAFE, NULL);
        if (ret)
                return ret;
 
@@ -135,7 +146,7 @@ int typec_altmode_exit(struct typec_altmode *adev)
                return -EOPNOTSUPP;
 
        /* Moving to USB Safe State */
-       ret = typec_altmode_set_state(adev, TYPEC_STATE_SAFE);
+       ret = typec_altmode_set_state(adev, TYPEC_STATE_SAFE, NULL);
        if (ret)
                return ret;
 
@@ -388,7 +399,7 @@ static int typec_remove(struct device *dev)
                drv->remove(to_typec_altmode(dev));
 
        if (adev->active) {
-               WARN_ON(typec_altmode_set_state(adev, TYPEC_STATE_SAFE));
+               WARN_ON(typec_altmode_set_state(adev, TYPEC_STATE_SAFE, NULL));
                typec_altmode_update_active(adev, false);
        }
 
index 08923637cd886727c2bbde682d0a19755375e60e..7c44e930602ff59eb37b77ed87fa8db31ce2834c 100644 (file)
@@ -1529,7 +1529,11 @@ EXPORT_SYMBOL_GPL(typec_get_orientation);
  */
 int typec_set_mode(struct typec_port *port, int mode)
 {
-       return port->mux ? port->mux->set(port->mux, mode) : 0;
+       struct typec_mux_state state = { };
+
+       state.mode = mode;
+
+       return port->mux ? port->mux->set(port->mux, &state) : 0;
 }
 EXPORT_SYMBOL_GPL(typec_set_mode);
 
index 5585b109095b8ed23a56e8bec3f6e74570e9243d..46457c133d2bcaa33121a4064ed1d0f5238ab076 100644 (file)
@@ -73,7 +73,8 @@ static int pi3usb30532_sw_set(struct typec_switch *sw,
        return ret;
 }
 
-static int pi3usb30532_mux_set(struct typec_mux *mux, int state)
+static int
+pi3usb30532_mux_set(struct typec_mux *mux, struct typec_mux_state *state)
 {
        struct pi3usb30532 *pi = typec_mux_get_drvdata(mux);
        u8 new_conf;
@@ -82,7 +83,7 @@ static int pi3usb30532_mux_set(struct typec_mux *mux, int state)
        mutex_lock(&pi->lock);
        new_conf = pi->conf;
 
-       switch (state) {
+       switch (state->mode) {
        case TYPEC_STATE_SAFE:
                new_conf = (new_conf & PI3USB30532_CONF_SWAP) |
                           PI3USB30532_CONF_OPEN;
index 873ace5b0cf861d8520d6bf991feecba6f8d9832..be7292c0be5e030ba36fe3e63925077bc50a0968 100644 (file)
@@ -8,6 +8,7 @@
 struct device;
 struct typec_mux;
 struct typec_switch;
+struct typec_altmode;
 struct fwnode_handle;
 
 typedef int (*typec_switch_set_fn_t)(struct typec_switch *sw,
@@ -29,7 +30,14 @@ void typec_switch_unregister(struct typec_switch *sw);
 void typec_switch_set_drvdata(struct typec_switch *sw, void *data);
 void *typec_switch_get_drvdata(struct typec_switch *sw);
 
-typedef int (*typec_mux_set_fn_t)(struct typec_mux *mux, int state);
+struct typec_mux_state {
+       struct typec_altmode *alt;
+       unsigned long mode;
+       void *data;
+};
+
+typedef int (*typec_mux_set_fn_t)(struct typec_mux *mux,
+                                 struct typec_mux_state *state);
 
 struct typec_mux_desc {
        struct fwnode_handle *fwnode;