platform/chrome: cros_ec_typec: Get retimer handle
authorPrashant Malani <pmalani@chromium.org>
Mon, 11 Jul 2022 07:23:03 +0000 (07:23 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 Jul 2022 12:44:08 +0000 (14:44 +0200)
Where available, obtain the handle to retimer switch specified via
firmware, and update the mux configuration callsites to add retimer
support for supported modes.

Signed-off-by: Prashant Malani <pmalani@chromium.org>
Link: https://lore.kernel.org/r/20220711072333.2064341-10-pmalani@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/platform/chrome/cros_ec_typec.c

index 39e6fd4..38c4ac7 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/usb/typec_altmode.h>
 #include <linux/usb/typec_dp.h>
 #include <linux/usb/typec_mux.h>
+#include <linux/usb/typec_retimer.h>
 #include <linux/usb/typec_tbt.h>
 #include <linux/usb/role.h>
 
@@ -53,6 +54,7 @@ struct cros_typec_port {
        struct usb_pd_identity c_identity;
        struct typec_switch *ori_sw;
        struct typec_mux *mux;
+       struct typec_retimer *retimer;
        struct usb_role_switch *role_sw;
 
        /* Variables keeping track of switch state. */
@@ -142,6 +144,12 @@ static int cros_typec_get_switch_handles(struct cros_typec_port *port,
                goto mux_err;
        }
 
+       port->retimer = fwnode_typec_retimer_get(fwnode);
+       if (IS_ERR(port->retimer)) {
+               dev_dbg(dev, "Retimer handle not found.\n");
+               goto retimer_sw_err;
+       }
+
        port->ori_sw = fwnode_typec_switch_get(fwnode);
        if (IS_ERR(port->ori_sw)) {
                dev_dbg(dev, "Orientation switch handle not found.\n");
@@ -159,6 +167,8 @@ static int cros_typec_get_switch_handles(struct cros_typec_port *port,
 role_sw_err:
        typec_switch_put(port->ori_sw);
 ori_sw_err:
+       typec_retimer_put(port->retimer);
+retimer_sw_err:
        typec_mux_put(port->mux);
 mux_err:
        return -ENODEV;
@@ -203,6 +213,21 @@ static void cros_typec_unregister_altmodes(struct cros_typec_data *typec, int po
        }
 }
 
+/*
+ * Map the Type-C Mux state to retimer state and call the retimer set function. We need this
+ * because we re-use the Type-C mux state for retimers.
+ */
+static int cros_typec_retimer_set(struct typec_retimer  *retimer, struct typec_mux_state state)
+{
+       struct typec_retimer_state rstate = {
+               .alt = state.alt,
+               .mode = state.mode,
+               .data = state.data,
+       };
+
+       return typec_retimer_set(retimer, &rstate);
+}
+
 static int cros_typec_usb_disconnect_state(struct cros_typec_port *port)
 {
        port->state.alt = NULL;
@@ -211,6 +236,7 @@ static int cros_typec_usb_disconnect_state(struct cros_typec_port *port)
 
        usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE);
        typec_switch_set(port->ori_sw, TYPEC_ORIENTATION_NONE);
+       cros_typec_retimer_set(port->retimer, port->state);
 
        return typec_mux_set(port->mux, &port->state);
 }
@@ -381,9 +407,14 @@ unregister_ports:
 
 static int cros_typec_usb_safe_state(struct cros_typec_port *port)
 {
+       int ret;
        port->state.mode = TYPEC_STATE_SAFE;
 
-       return typec_mux_set(port->mux, &port->state);
+       ret = cros_typec_retimer_set(port->retimer, port->state);
+       if (!ret)
+               ret = typec_mux_set(port->mux, &port->state);
+
+       return ret;
 }
 
 /*
@@ -480,7 +511,11 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec,
        port->state.data = &dp_data;
        port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode));
 
-       return typec_mux_set(port->mux, &port->state);
+       ret = cros_typec_retimer_set(port->retimer, port->state);
+       if (!ret)
+               ret = typec_mux_set(port->mux, &port->state);
+
+       return ret;
 }
 
 static int cros_typec_enable_usb4(struct cros_typec_data *typec,
@@ -569,7 +604,10 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
        } else if (port->mux_flags & USB_PD_MUX_USB_ENABLED) {
                port->state.alt = NULL;
                port->state.mode = TYPEC_STATE_USB;
-               ret = typec_mux_set(port->mux, &port->state);
+
+               ret = cros_typec_retimer_set(port->retimer, port->state);
+               if (!ret)
+                       ret = typec_mux_set(port->mux, &port->state);
        } else {
                dev_dbg(typec->dev,
                        "Unrecognized mode requested, mux flags: %x\n",