summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorHemant Kumar <hemantk@codeaurora.org>2016-05-12 13:57:03 -0700
committerKyle Yan <kyan@codeaurora.org>2016-05-25 14:18:30 -0700
commite89026c0e2393a555c718054be07db2152b81f2e (patch)
tree53f0ef3187665d7434088752e4856b05e269112b /drivers/usb
parent8a53f7d7fa27c7df54ac05d0a28750cfbf4114ba (diff)
usb: dwc3: Add support handle type-c plug orientation
Register callbacks for plug orientations in order to cache the current plug orientation reported by extcon. This allows super speed phy driver to configure the appropriate lane upon phy initialization. Change-Id: I906005680b4cc90cc38dc3d403beebf7aa515ad7 Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c54
1 files changed, 51 insertions, 3 deletions
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 2b0299c293e2..13ba52ad7b62 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -122,6 +122,13 @@ enum dwc3_id_state {
DWC3_ID_FLOAT,
};
+/* for type c cable */
+enum plug_orientation {
+ ORIENTATION_NONE,
+ ORIENTATION_CC1,
+ ORIENTATION_CC2,
+};
+
/* Input bits to state machine (mdwc->inputs) */
#define ID 0
@@ -196,6 +203,7 @@ struct dwc3_msm {
atomic_t in_p3;
unsigned int lpm_to_suspend_delay;
bool init;
+ enum plug_orientation typec_orientation;
};
#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
@@ -1998,6 +2006,11 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
/* Resume SS PHY */
if (mdwc->lpm_flags & MDWC3_SS_PHY_SUSPEND) {
+ mdwc->ss_phy->flags &= ~(PHY_LANE_A | PHY_LANE_B);
+ if (mdwc->typec_orientation == ORIENTATION_CC1)
+ mdwc->ss_phy->flags |= PHY_LANE_A;
+ if (mdwc->typec_orientation == ORIENTATION_CC2)
+ mdwc->ss_phy->flags |= PHY_LANE_B;
usb_phy_set_suspend(mdwc->ss_phy, 0);
mdwc->ss_phy->flags &= ~DEVICE_IN_SS_MODE;
mdwc->lpm_flags &= ~MDWC3_SS_PHY_SUSPEND;
@@ -2333,18 +2346,36 @@ static int dwc3_msm_id_notifier(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct dwc3_msm *mdwc = container_of(nb, struct dwc3_msm, id_nb);
+ struct extcon_dev *edev = ptr;
enum dwc3_id_state id;
+ int cc_state;
+
+ if (!edev) {
+ dev_err(mdwc->dev, "%s: edev null\n", __func__);
+ goto done;
+ }
id = event ? DWC3_ID_GROUND : DWC3_ID_FLOAT;
dev_dbg(mdwc->dev, "host:%ld (id:%d) event received\n", event, id);
+ cc_state = extcon_get_cable_state_(edev, EXTCON_USB_CC);
+ if (cc_state < 0) {
+ dev_err(mdwc->dev, "%s: failed to get cc state\n", __func__);
+ goto done;
+ }
+
+ mdwc->typec_orientation = cc_state ? ORIENTATION_CC2 : ORIENTATION_CC1;
+
+ dbg_event(0xFF, "cc_state", mdwc->typec_orientation);
+
if (mdwc->id_state != id) {
mdwc->id_state = id;
dbg_event(0xFF, "id_state", mdwc->id_state);
queue_work(mdwc->dwc3_wq, &mdwc->resume_work);
}
+done:
return NOTIFY_DONE;
}
@@ -2353,18 +2384,35 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb,
{
struct dwc3_msm *mdwc = container_of(nb, struct dwc3_msm, vbus_nb);
struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
+ struct extcon_dev *edev = ptr;
+ int cc_state;
+
+ if (!edev) {
+ dev_err(mdwc->dev, "%s: edev null\n", __func__);
+ goto done;
+ }
dev_dbg(mdwc->dev, "vbus:%ld event received\n", event);
if (mdwc->vbus_active == event)
return NOTIFY_DONE;
+ cc_state = extcon_get_cable_state_(edev, EXTCON_USB_CC);
+ if (cc_state < 0) {
+ dev_err(mdwc->dev, "%s: failed to get cc state\n", __func__);
+ goto done;
+ }
+
+ mdwc->typec_orientation = cc_state ? ORIENTATION_CC2 : ORIENTATION_CC1;
+
+ dbg_event(0xFF, "cc_state", mdwc->typec_orientation);
+
mdwc->vbus_active = event;
if (dwc->is_drd && !mdwc->in_restart) {
dbg_event(0xFF, "Q RW (vbus)", mdwc->vbus_active);
queue_work(mdwc->dwc3_wq, &mdwc->resume_work);
}
-
+done:
return NOTIFY_DONE;
}
@@ -2767,10 +2815,10 @@ static int dwc3_msm_probe(struct platform_device *pdev)
/* Update initial VBUS/ID state from extcon */
if (mdwc->extcon_vbus && extcon_get_cable_state_(mdwc->extcon_vbus,
EXTCON_USB))
- dwc3_msm_vbus_notifier(&mdwc->vbus_nb, true, NULL);
+ dwc3_msm_vbus_notifier(&mdwc->vbus_nb, true, mdwc->extcon_vbus);
if (mdwc->extcon_id && extcon_get_cable_state_(mdwc->extcon_id,
EXTCON_USB_HOST))
- dwc3_msm_id_notifier(&mdwc->id_nb, true, NULL);
+ dwc3_msm_id_notifier(&mdwc->id_nb, true, mdwc->extcon_id);
device_create_file(&pdev->dev, &dev_attr_mode);