summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Pham <jackp@codeaurora.org>2016-10-19 12:54:58 -0700
committerAbhijeet Dharmapurikar <adharmap@codeaurora.org>2016-10-19 16:27:06 -0700
commit7ae4a1711ecb0fbd69578348a63e9592c611dda3 (patch)
tree07bb0a0314afc1c4fe25f47affd8f53f47614b1a
parentcb6c743a0642d37210b44f7e1a4edb23f0250e4b (diff)
usb: pd: Start state machine when PE_START is true
Support the new POWER_SUPPLY_PROP_PE_START property which indicates when the policy engine state machine can begin. This helps to simplify the psy_changed() routine as we can now rely on this property to indicate that PROP_TYPEC_MODE and PROP_TYPE are already settled. The state machine work can now simply begin when seeing a change in TYPEC_MODE. This replaces the previous use of PROP_PD_ALLOWED which prior to commit 18da08334eb3 ("usb: pd: Handle PD_ALLOWED within state machine") was intended to be a marker to start up the policy engine but now simply indicates whether or not to start PD comms. We can now move reading of this property to usbpd_set_state() as it is now only needed locally in the SNK_STARTUP handling. Change-Id: Ia0b9e5b011ae72e1afcaf5109b8253d124afc021 Signed-off-by: Jack Pham <jackp@codeaurora.org>
-rw-r--r--drivers/usb/pd/policy_engine.c177
1 files changed, 90 insertions, 87 deletions
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 26c91e0ce163..c81a56c7be49 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -299,7 +299,6 @@ struct usbpd {
enum power_supply_typec_mode typec_mode;
enum power_supply_type psy_type;
bool vbus_present;
- bool pd_allowed;
enum data_role current_dr;
enum power_role current_pr;
@@ -828,7 +827,15 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
}
}
- if (!pd->pd_allowed)
+ ret = power_supply_get_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_PD_ALLOWED, &val);
+ if (ret) {
+ usbpd_err(&pd->dev, "Unable to read USB PROP_PD_ALLOWED: %d\n",
+ ret);
+ break;
+ }
+
+ if (!val.intval)
break;
/* Reset protocol layer */
@@ -2036,41 +2043,41 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
struct usbpd *pd = container_of(nb, struct usbpd, psy_nb);
union power_supply_propval val;
enum power_supply_typec_mode typec_mode;
- bool do_work = false;
int ret;
if (ptr != pd->usb_psy || evt != PSY_EVENT_PROP_CHANGED)
return 0;
ret = power_supply_get_property(pd->usb_psy,
- POWER_SUPPLY_PROP_PD_ALLOWED, &val);
+ POWER_SUPPLY_PROP_TYPEC_MODE, &val);
if (ret) {
- usbpd_err(&pd->dev, "Unable to read USB PROP_PD_ALLOWED: %d\n",
- ret);
+ usbpd_err(&pd->dev, "Unable to read USB TYPEC_MODE: %d\n", ret);
return ret;
}
- if (pd->pd_allowed != val.intval)
- do_work = true;
- pd->pd_allowed = val.intval;
+ typec_mode = val.intval;
ret = power_supply_get_property(pd->usb_psy,
- POWER_SUPPLY_PROP_PRESENT, &val);
+ POWER_SUPPLY_PROP_PE_START, &val);
if (ret) {
- usbpd_err(&pd->dev, "Unable to read USB PRESENT: %d\n", ret);
+ usbpd_err(&pd->dev, "Unable to read USB PROP_PE_START: %d\n",
+ ret);
return ret;
}
- pd->vbus_present = val.intval;
+ /* Don't proceed if PE_START=0 as other props may still change */
+ if (!val.intval && !pd->pd_connected &&
+ typec_mode != POWER_SUPPLY_TYPEC_NONE)
+ return 0;
ret = power_supply_get_property(pd->usb_psy,
- POWER_SUPPLY_PROP_TYPEC_MODE, &val);
+ POWER_SUPPLY_PROP_PRESENT, &val);
if (ret) {
- usbpd_err(&pd->dev, "Unable to read USB TYPEC_MODE: %d\n", ret);
+ usbpd_err(&pd->dev, "Unable to read USB PRESENT: %d\n", ret);
return ret;
}
- typec_mode = val.intval;
+ pd->vbus_present = val.intval;
ret = power_supply_get_property(pd->usb_psy,
POWER_SUPPLY_PROP_TYPE, &val);
@@ -2079,91 +2086,87 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
return ret;
}
- if (pd->psy_type != val.intval)
- do_work = true;
pd->psy_type = val.intval;
+ if (pd->typec_mode == typec_mode)
+ return 0;
+
+ pd->typec_mode = typec_mode;
+
usbpd_dbg(&pd->dev, "typec mode:%d present:%d type:%d orientation:%d\n",
typec_mode, pd->vbus_present, pd->psy_type,
usbpd_get_plug_orientation(pd));
- if (pd->typec_mode != typec_mode) {
- pd->typec_mode = typec_mode;
- do_work = true;
-
- switch (typec_mode) {
- /* Disconnect */
- case POWER_SUPPLY_TYPEC_NONE:
- if (pd->in_pr_swap) {
- usbpd_dbg(&pd->dev, "Ignoring disconnect due to PR swap\n");
- do_work = false;
- }
+ switch (typec_mode) {
+ /* Disconnect */
+ case POWER_SUPPLY_TYPEC_NONE:
+ if (pd->in_pr_swap) {
+ usbpd_dbg(&pd->dev, "Ignoring disconnect due to PR swap\n");
+ return 0;
+ }
- /*
- * Workaround for PMIC HW bug.
- *
- * During hard reset when VBUS goes to 0 the CC logic
- * will report this as a disconnection. In those cases
- * it can be ignored, however the downside is that
- * pd->hard_reset can be momentarily true even when a
- * non-PD capable source is attached, and can't be
- * distinguished from a physical disconnect. In that
- * case, allow for the common case of disconnecting
- * from an SDP.
- *
- * The less common case is a PD-capable SDP which will
- * result in a hard reset getting treated like a
- * disconnect. We can live with this until the HW bug
- * is fixed: in which disconnection won't be reported
- * on VBUS loss alone unless pullup is also removed
- * from CC.
- */
- if (pd->psy_type != POWER_SUPPLY_TYPE_USB &&
- pd->current_state ==
- PE_SNK_TRANSITION_TO_DEFAULT) {
- usbpd_dbg(&pd->dev, "Ignoring disconnect due to hard reset\n");
- do_work = false;
- }
+ /*
+ * Workaround for PMIC HW bug.
+ *
+ * During hard reset when VBUS goes to 0 the CC logic
+ * will report this as a disconnection. In those cases
+ * it can be ignored, however the downside is that
+ * pd->hard_reset can be momentarily true even when a
+ * non-PD capable source is attached, and can't be
+ * distinguished from a physical disconnect. In that
+ * case, allow for the common case of disconnecting
+ * from an SDP.
+ *
+ * The less common case is a PD-capable SDP which will
+ * result in a hard reset getting treated like a
+ * disconnect. We can live with this until the HW bug
+ * is fixed: in which disconnection won't be reported
+ * on VBUS loss alone unless pullup is also removed
+ * from CC.
+ */
+ if (pd->psy_type != POWER_SUPPLY_TYPE_USB &&
+ pd->current_state ==
+ PE_SNK_TRANSITION_TO_DEFAULT) {
+ usbpd_dbg(&pd->dev, "Ignoring disconnect due to hard reset\n");
+ return 0;
+ }
- break;
+ break;
- /* Sink states */
- case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
- case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
- case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
- usbpd_info(&pd->dev, "Type-C Source (%s) connected\n",
- src_current(typec_mode));
- pd->current_pr = PR_SINK;
- pd->in_pr_swap = false;
- break;
+ /* Sink states */
+ case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
+ case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
+ case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
+ usbpd_info(&pd->dev, "Type-C Source (%s) connected\n",
+ src_current(typec_mode));
+ pd->current_pr = PR_SINK;
+ pd->in_pr_swap = false;
+ break;
- /* Source states */
- case POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE:
- case POWER_SUPPLY_TYPEC_SINK:
- usbpd_info(&pd->dev, "Type-C Sink%s connected\n",
- typec_mode == POWER_SUPPLY_TYPEC_SINK ?
- "" : " (powered)");
- pd->current_pr = PR_SRC;
- pd->in_pr_swap = false;
- break;
+ /* Source states */
+ case POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE:
+ case POWER_SUPPLY_TYPEC_SINK:
+ usbpd_info(&pd->dev, "Type-C Sink%s connected\n",
+ typec_mode == POWER_SUPPLY_TYPEC_SINK ?
+ "" : " (powered)");
+ pd->current_pr = PR_SRC;
+ pd->in_pr_swap = false;
+ break;
- case POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY:
- usbpd_info(&pd->dev, "Type-C Debug Accessory connected\n");
- break;
- case POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER:
- usbpd_info(&pd->dev, "Type-C Analog Audio Adapter connected\n");
- break;
- default:
- usbpd_warn(&pd->dev, "Unsupported typec mode:%d\n",
- typec_mode);
- break;
- }
+ case POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY:
+ usbpd_info(&pd->dev, "Type-C Debug Accessory connected\n");
+ break;
+ case POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER:
+ usbpd_info(&pd->dev, "Type-C Analog Audio Adapter connected\n");
+ break;
+ default:
+ usbpd_warn(&pd->dev, "Unsupported typec mode:%d\n",
+ typec_mode);
+ break;
}
- /* only queue state machine if CC state or PD_ALLOWED changes */
- if (do_work)
- kick_sm(pd, 0);
-
+ /* queue state machine due to CC state change */
+ kick_sm(pd, 0);
return 0;
}