platform/chrome: cros_ec_typec: Register port partner
authorPrashant Malani <pmalani@chromium.org>
Wed, 15 Apr 2020 05:29:43 +0000 (22:29 -0700)
committerEnric Balletbo i Serra <enric.balletbo@collabora.com>
Wed, 15 Apr 2020 06:00:20 +0000 (08:00 +0200)
Register (and unregister) the port partner when a connect (and
disconnect) is detected.

Co-developed-by: Jon Flatley <jflat@chromium.org>
Signed-off-by: Prashant Malani <pmalani@chromium.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
drivers/platform/chrome/cros_ec_typec.c

index 56ded09a60ffbecf514ab5dd4d19a68cfb9580a4..eda57db26f8dc2ff20b62fc0451c6fdea8b227d5 100644 (file)
@@ -22,6 +22,9 @@ struct cros_typec_port {
        struct typec_port *port;
        /* Initial capabilities for the port. */
        struct typec_capability caps;
+       struct typec_partner *partner;
+       /* Port partner PD identity info. */
+       struct usb_pd_identity p_identity;
 };
 
 /* Platform-specific data for the Chrome OS EC Type C controller. */
@@ -190,6 +193,30 @@ static int cros_typec_ec_command(struct cros_typec_data *typec,
        return ret;
 }
 
+static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num,
+                                 bool pd_en)
+{
+       struct cros_typec_port *port = typec->ports[port_num];
+       struct typec_partner_desc p_desc = {
+               .usb_pd = pd_en,
+       };
+       int ret = 0;
+
+       /*
+        * Fill an initial PD identity, which will then be updated with info
+        * from the EC.
+        */
+       p_desc.identity = &port->p_identity;
+
+       port->partner = typec_register_partner(port->port, &p_desc);
+       if (IS_ERR(port->partner)) {
+               ret = PTR_ERR(port->partner);
+               port->partner = NULL;
+       }
+
+       return ret;
+}
+
 static void cros_typec_set_port_params_v0(struct cros_typec_data *typec,
                int port_num, struct ec_response_usb_pd_control *resp)
 {
@@ -212,6 +239,8 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
 {
        struct typec_port *port = typec->ports[port_num]->port;
        enum typec_orientation polarity;
+       bool pd_en;
+       int ret;
 
        if (!(resp->enabled & PD_CTRL_RESP_ENABLED_CONNECTED))
                polarity = TYPEC_ORIENTATION_NONE;
@@ -226,6 +255,25 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
                        TYPEC_SOURCE : TYPEC_SINK);
        typec_set_vconn_role(port, resp->role & PD_CTRL_RESP_ROLE_VCONN ?
                        TYPEC_SOURCE : TYPEC_SINK);
+
+       /* Register/remove partners when a connect/disconnect occurs. */
+       if (resp->enabled & PD_CTRL_RESP_ENABLED_CONNECTED) {
+               if (typec->ports[port_num]->partner)
+                       return;
+
+               pd_en = resp->enabled & PD_CTRL_RESP_ENABLED_PD_CAPABLE;
+               ret = cros_typec_add_partner(typec, port_num, pd_en);
+               if (!ret)
+                       dev_warn(typec->dev,
+                                "Failed to register partner on port: %d\n",
+                                port_num);
+       } else {
+               if (!typec->ports[port_num]->partner)
+                       return;
+
+               typec_unregister_partner(typec->ports[port_num]->partner);
+               typec->ports[port_num]->partner = NULL;
+       }
 }
 
 static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)