OSDN Git Service

usb: typec: update partner power delivery support with opmode
authorHeikki Krogerus <heikki.krogerus@linux.intel.com>
Tue, 16 May 2017 12:26:11 +0000 (15:26 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 3 Jun 2017 09:02:58 +0000 (18:02 +0900)
If USB PD contract is established after creation of the
partner, the power delivery support attribute of the partner
needs to be updated separately. This can be done in
typec_set_pwr_opmode() by checking if the port has already
partner and updating the value if it does.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/typec/typec.c

index db5ee73..1a6822e 100644 (file)
@@ -1124,6 +1124,11 @@ void typec_set_vconn_role(struct typec_port *port, enum typec_role role)
 }
 EXPORT_SYMBOL_GPL(typec_set_vconn_role);
 
+static int partner_match(struct device *dev, void *data)
+{
+       return is_typec_partner(dev);
+}
+
 /**
  * typec_set_pwr_opmode - Report changed power operation mode
  * @port: The USB Type-C Port where the mode was changed
@@ -1137,12 +1142,26 @@ EXPORT_SYMBOL_GPL(typec_set_vconn_role);
 void typec_set_pwr_opmode(struct typec_port *port,
                          enum typec_pwr_opmode opmode)
 {
+       struct device *partner_dev;
+
        if (port->pwr_opmode == opmode)
                return;
 
        port->pwr_opmode = opmode;
        sysfs_notify(&port->dev.kobj, NULL, "power_operation_mode");
        kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+
+       partner_dev = device_find_child(&port->dev, NULL, partner_match);
+       if (partner_dev) {
+               struct typec_partner *partner = to_typec_partner(partner_dev);
+
+               if (opmode == TYPEC_PWR_MODE_PD && !partner->usb_pd) {
+                       partner->usb_pd = 1;
+                       sysfs_notify(&partner_dev->kobj, NULL,
+                                    "supports_usb_power_delivery");
+               }
+               put_device(partner_dev);
+       }
 }
 EXPORT_SYMBOL_GPL(typec_set_pwr_opmode);