Merge tag 'tag-chrome-platform-for-v5.18' of git://git.kernel.org/pub/scm/linux/kerne...
[linux-2.6-microblaze.git] / drivers / platform / chrome / cros_ec_typec.c
index 5de0bfb..4bd2752 100644 (file)
@@ -115,17 +115,18 @@ static int cros_typec_parse_port_props(struct typec_capability *cap,
                return ret;
        cap->data = ret;
 
+       /* Try-power-role is optional. */
        ret = fwnode_property_read_string(fwnode, "try-power-role", &buf);
        if (ret) {
-               dev_err(dev, "try-power-role not found: %d\n", ret);
-               return ret;
+               dev_warn(dev, "try-power-role not found: %d\n", ret);
+               cap->prefer_role = TYPEC_NO_PREFERRED_ROLE;
+       } else {
+               ret = typec_find_power_role(buf);
+               if (ret < 0)
+                       return ret;
+               cap->prefer_role = ret;
        }
 
-       ret = typec_find_power_role(buf);
-       if (ret < 0)
-               return ret;
-       cap->prefer_role = ret;
-
        cap->fwnode = fwnode;
 
        return 0;
@@ -227,6 +228,7 @@ static void cros_typec_remove_partner(struct cros_typec_data *typec,
        cros_typec_unregister_altmodes(typec, port_num, true);
 
        cros_typec_usb_disconnect_state(port);
+       port->mux_flags = USB_PD_MUX_NONE;
 
        typec_unregister_partner(port->partner);
        port->partner = NULL;
@@ -512,20 +514,38 @@ static int cros_typec_enable_usb4(struct cros_typec_data *typec,
 }
 
 static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
-                               uint8_t mux_flags,
                                struct ec_response_usb_pd_control_v2 *pd_ctrl)
 {
        struct cros_typec_port *port = typec->ports[port_num];
+       struct ec_response_usb_pd_mux_info resp;
+       struct ec_params_usb_pd_mux_info req = {
+               .port = port_num,
+       };
        struct ec_params_usb_pd_mux_ack mux_ack;
        enum typec_orientation orientation;
        int ret;
 
-       if (mux_flags == USB_PD_MUX_NONE) {
+       ret = cros_ec_command(typec->ec, 0, EC_CMD_USB_PD_MUX_INFO,
+                             &req, sizeof(req), &resp, sizeof(resp));
+       if (ret < 0) {
+               dev_warn(typec->dev, "Failed to get mux info for port: %d, err = %d\n",
+                        port_num, ret);
+               return ret;
+       }
+
+       /* No change needs to be made, let's exit early. */
+       if (port->mux_flags == resp.flags && port->role == pd_ctrl->role)
+               return 0;
+
+       port->mux_flags = resp.flags;
+       port->role = pd_ctrl->role;
+
+       if (port->mux_flags == USB_PD_MUX_NONE) {
                ret = cros_typec_usb_disconnect_state(port);
                goto mux_ack;
        }
 
-       if (mux_flags & USB_PD_MUX_POLARITY_INVERTED)
+       if (port->mux_flags & USB_PD_MUX_POLARITY_INVERTED)
                orientation = TYPEC_ORIENTATION_REVERSE;
        else
                orientation = TYPEC_ORIENTATION_NORMAL;
@@ -540,22 +560,22 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
        if (ret)
                return ret;
 
-       if (mux_flags & USB_PD_MUX_USB4_ENABLED) {
+       if (port->mux_flags & USB_PD_MUX_USB4_ENABLED) {
                ret = cros_typec_enable_usb4(typec, port_num, pd_ctrl);
-       } else if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) {
+       } else if (port->mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) {
                ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl);
-       } else if (mux_flags & USB_PD_MUX_DP_ENABLED) {
+       } else if (port->mux_flags & USB_PD_MUX_DP_ENABLED) {
                ret = cros_typec_enable_dp(typec, port_num, pd_ctrl);
-       } else if (mux_flags & USB_PD_MUX_SAFE_MODE) {
+       } else if (port->mux_flags & USB_PD_MUX_SAFE_MODE) {
                ret = cros_typec_usb_safe_state(port);
-       } else if (mux_flags & USB_PD_MUX_USB_ENABLED) {
+       } 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);
        } else {
                dev_dbg(typec->dev,
                        "Unrecognized mode requested, mux flags: %x\n",
-                       mux_flags);
+                       port->mux_flags);
        }
 
 mux_ack:
@@ -630,17 +650,6 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
        }
 }
 
-static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num,
-                                  struct ec_response_usb_pd_mux_info *resp)
-{
-       struct ec_params_usb_pd_mux_info req = {
-               .port = port_num,
-       };
-
-       return cros_ec_command(typec->ec, 0, EC_CMD_USB_PD_MUX_INFO, &req,
-                              sizeof(req), resp, sizeof(*resp));
-}
-
 /*
  * Helper function to register partner/plug altmodes.
  */
@@ -938,7 +947,6 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
 {
        struct ec_params_usb_pd_control req;
        struct ec_response_usb_pd_control_v2 resp;
-       struct ec_response_usb_pd_mux_info mux_resp;
        int ret;
 
        if (port_num < 0 || port_num >= typec->num_ports) {
@@ -958,6 +966,11 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
        if (ret < 0)
                return ret;
 
+       /* Update the switches if they exist, according to requested state */
+       ret = cros_typec_configure_mux(typec, port_num, &resp);
+       if (ret)
+               dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
+
        dev_dbg(typec->dev, "Enabled %d: 0x%hhx\n", port_num, resp.enabled);
        dev_dbg(typec->dev, "Role %d: 0x%hhx\n", port_num, resp.role);
        dev_dbg(typec->dev, "Polarity %d: 0x%hhx\n", port_num, resp.polarity);
@@ -973,27 +986,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
        if (typec->typec_cmd_supported)
                cros_typec_handle_status(typec, port_num);
 
-       /* Update the switches if they exist, according to requested state */
-       ret = cros_typec_get_mux_info(typec, port_num, &mux_resp);
-       if (ret < 0) {
-               dev_warn(typec->dev,
-                        "Failed to get mux info for port: %d, err = %d\n",
-                        port_num, ret);
-               return 0;
-       }
-
-       /* No change needs to be made, let's exit early. */
-       if (typec->ports[port_num]->mux_flags == mux_resp.flags &&
-           typec->ports[port_num]->role == resp.role)
-               return 0;
-
-       typec->ports[port_num]->mux_flags = mux_resp.flags;
-       typec->ports[port_num]->role = resp.role;
-       ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp);
-       if (ret)
-               dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
-
-       return ret;
+       return 0;
 }
 
 static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
@@ -1075,7 +1068,13 @@ static int cros_typec_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        typec->dev = dev;
+
        typec->ec = dev_get_drvdata(pdev->dev.parent);
+       if (!typec->ec) {
+               dev_err(dev, "couldn't find parent EC device\n");
+               return -ENODEV;
+       }
+
        platform_set_drvdata(pdev, typec);
 
        ret = cros_typec_get_cmd_version(typec);