summaryrefslogtreecommitdiff
path: root/drivers/usb/pd
diff options
context:
space:
mode:
authorHemant Kumar <hemantk@codeaurora.org>2016-05-12 16:07:40 -0700
committerKyle Yan <kyan@codeaurora.org>2016-05-25 14:18:53 -0700
commit77f6fd80444cc7796bb005061323801f73ccc197 (patch)
tree0934672fe815adee8951f60051849439a937ec51 /drivers/usb/pd
parent20b1701b73d9823dc61154211a28c9cc659d5e45 (diff)
usb: pd: Add support to notify plug orientation via extcon
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>
Diffstat (limited to 'drivers/usb/pd')
-rw-r--r--drivers/usb/pd/policy_engine.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 05468398d34b..6b636a434966 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -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");