OSDN Git Service

usb: pd: Add support to notify plug orientation via extcon
authorHemant Kumar <hemantk@codeaurora.org>
Thu, 12 May 2016 23:07:40 +0000 (16:07 -0700)
committerKyle Yan <kyan@codeaurora.org>
Wed, 25 May 2016 21:18:53 +0000 (14:18 -0700)
Policy engine needs to provide the plug orientation upon
type-c cable plug in. qmp phy driver needs to program phy
lane based upon this information.

Change-Id: Idd236136c9f0a9163b4ae7a8405c412f1d69ca9e
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
drivers/usb/pd/policy_engine.c

index 0546839..6b636a4 100644 (file)
@@ -118,6 +118,12 @@ enum usbpd_data_msg_type {
        MSG_VDM = 0xF,
 };
 
+enum plug_orientation {
+       ORIENTATION_NONE,
+       ORIENTATION_CC1,
+       ORIENTATION_CC2,
+};
+
 /* Timeouts (in ms) */
 #define ERROR_RECOVERY_TIME    25
 #define SENDER_RESPONSE_TIME   30
@@ -239,10 +245,41 @@ static LIST_HEAD(_usbpd); /* useful for debugging */
 static const unsigned int usbpd_extcon_cable[] = {
        EXTCON_USB,
        EXTCON_USB_HOST,
+       EXTCON_USB_CC,
        EXTCON_NONE,
 };
 
-static const u32 usbpd_extcon_exclusive[] = {0xffffffff, 0};
+/* EXTCON_USB and EXTCON_USB_HOST are mutually exclusive */
+static const u32 usbpd_extcon_exclusive[] = {0x3, 0};
+
+static enum plug_orientation usbpd_get_plug_orientation(struct usbpd *pd)
+{
+       int ret;
+       union power_supply_propval val;
+
+       ret = power_supply_get_property(pd->usb_psy,
+               POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION, &val);
+       if (ret)
+               return ORIENTATION_NONE;
+
+       return val.intval;
+}
+
+static bool is_cable_flipped(struct usbpd *pd)
+{
+       enum plug_orientation cc;
+
+       cc = usbpd_get_plug_orientation(pd);
+       if (cc == ORIENTATION_CC2)
+               return true;
+
+       /*
+        * ORIENTATION_CC1 or ORIENTATION_NONE.
+        * Return value for ORIENTATION_NONE is
+        * "dont care" as disconnect handles it.
+        */
+       return false;
+}
 
 static int set_power_role(struct usbpd *pd, enum power_role pr)
 {
@@ -612,6 +649,9 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
                        if (pd->psy_type == POWER_SUPPLY_TYPE_USB ||
                                pd->psy_type == POWER_SUPPLY_TYPE_USB_CDP)
                                extcon_set_cable_state_(pd->extcon,
+                                               EXTCON_USB_CC,
+                                               is_cable_flipped(pd));
+                               extcon_set_cable_state_(pd->extcon,
                                                EXTCON_USB, 1);
                }
 
@@ -705,6 +745,8 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
                        extcon_set_cable_state_(pd->extcon, EXTCON_USB_HOST, 0);
 
                        pd->current_dr = DR_UFP;
+                       extcon_set_cable_state_(pd->extcon, EXTCON_USB_CC,
+                                       is_cable_flipped(pd));
                        extcon_set_cable_state_(pd->extcon, EXTCON_USB, 1);
                        pd_phy_update_roles(pd->current_dr, pd->current_pr);
                }
@@ -739,10 +781,14 @@ static void dr_swap(struct usbpd *pd)
 {
        if (pd->current_dr == DR_DFP) {
                extcon_set_cable_state_(pd->extcon, EXTCON_USB_HOST, 0);
+               extcon_set_cable_state_(pd->extcon, EXTCON_USB_CC,
+                               is_cable_flipped(pd));
                extcon_set_cable_state_(pd->extcon, EXTCON_USB, 1);
                pd->current_dr = DR_UFP;
        } else if (pd->current_dr == DR_UFP) {
                extcon_set_cable_state_(pd->extcon, EXTCON_USB, 0);
+               extcon_set_cable_state_(pd->extcon, EXTCON_USB_CC,
+                               is_cable_flipped(pd));
                extcon_set_cable_state_(pd->extcon, EXTCON_USB_HOST, 1);
                pd->current_dr = DR_DFP;
        }
@@ -865,6 +911,8 @@ static void usbpd_sm(struct work_struct *w)
                        if (pd->caps_count == 5 && pd->current_dr == DR_DFP) {
                                /* Likely not PD-capable, start host now */
                                extcon_set_cable_state_(pd->extcon,
+                                       EXTCON_USB_CC, is_cable_flipped(pd));
+                               extcon_set_cable_state_(pd->extcon,
                                                EXTCON_USB_HOST, 1);
                        } else if (pd->caps_count >= PD_CAPS_COUNT) {
                                dev_dbg(&pd->dev, "Src CapsCounter exceeded, disabling PD\n");