diff options
author | Hemant Kumar <hemantk@codeaurora.org> | 2016-05-12 16:07:40 -0700 |
---|---|---|
committer | Kyle Yan <kyan@codeaurora.org> | 2016-05-25 14:18:53 -0700 |
commit | 77f6fd80444cc7796bb005061323801f73ccc197 (patch) | |
tree | 0934672fe815adee8951f60051849439a937ec51 /drivers/usb/pd | |
parent | 20b1701b73d9823dc61154211a28c9cc659d5e45 (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.c | 50 |
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"); |