summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2015-01-04 13:39:38 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-07 02:32:38 +0000
commite39f43ed2d79195098c2373389f0495f20e3247c (patch)
treeb871704c8dbbd93801c9284ab8b5e08a9411ddad
parent563e7bed1ee5ec4b86b13d759507b5f185706c09 (diff)
downloadchrome-ec-e39f43ed2d79195098c2373389f0495f20e3247c.tar.gz
samus: pd: on PD connection, if sink, ask for power swap
For samus, on PD connection or on resume to S0, if we are a sink, and the other side supports PR_SWAP, then attempt a power swap. This adds callback functions into board policy file to check and issue power or data swaps if required by the product. BUG=chrome-os-partner:31195 BRANCH=samus TEST=connect samus to zinger and make sure zinger always ends up as SRC-UFP. connect samus to samus with both in S0 and see that they swap power roles once and not data roles. connect one samus in S0 to one samus in S5 and see that the one in S5 is sink. then when you boot the one in S5 it switches to a source. connect samus to samus with both in S0. do chgoverride 1 on one side to start charging from the other samus. then on the same side, turn off the machine (S5) and resume (S0), and see that it is still charging from the other samus (ie has not switched roles to source). Change-Id: Ifab2465fccef77448ac4771a3c2de1c867cbbec4 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/238302 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/dingdong/usb_pd_policy.c7
-rw-r--r--board/firefly/usb_pd_policy.c7
-rw-r--r--board/fruitpie/usb_pd_policy.c7
-rw-r--r--board/hoho/usb_pd_policy.c7
-rw-r--r--board/host/usb_pd_policy.c7
-rw-r--r--board/plankton/usb_pd_policy.c7
-rw-r--r--board/ryu/usb_pd_policy.c7
-rw-r--r--board/ryu_p1/usb_pd_policy.c7
-rw-r--r--board/samus_pd/usb_pd_policy.c11
-rw-r--r--board/twinkie/usb_pd_policy.c7
-rw-r--r--board/zinger/usb_pd_policy.c7
-rw-r--r--common/usb_pd_protocol.c95
-rw-r--r--include/usb_pd.h20
13 files changed, 134 insertions, 62 deletions
diff --git a/board/dingdong/usb_pd_policy.c b/board/dingdong/usb_pd_policy.c
index 85eb07020f..5c14e4a6da 100644
--- a/board/dingdong/usb_pd_policy.c
+++ b/board/dingdong/usb_pd_policy.c
@@ -86,8 +86,11 @@ void pd_execute_data_swap(int port, int data_role)
/* Do nothing */
}
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap)
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
{
}
/* ----------------- Vendor Defined Messages ------------------ */
diff --git a/board/firefly/usb_pd_policy.c b/board/firefly/usb_pd_policy.c
index 45042cd35a..5917e1a7ef 100644
--- a/board/firefly/usb_pd_policy.c
+++ b/board/firefly/usb_pd_policy.c
@@ -124,8 +124,11 @@ void pd_execute_data_swap(int port, int data_role)
/* Do nothing */
}
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap)
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
{
}
diff --git a/board/fruitpie/usb_pd_policy.c b/board/fruitpie/usb_pd_policy.c
index cf0b740260..ed7e1386fb 100644
--- a/board/fruitpie/usb_pd_policy.c
+++ b/board/fruitpie/usb_pd_policy.c
@@ -111,8 +111,11 @@ void pd_execute_data_swap(int port, int data_role)
/* Do nothing */
}
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap)
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
{
}
/* ----------------- Vendor Defined Messages ------------------ */
diff --git a/board/hoho/usb_pd_policy.c b/board/hoho/usb_pd_policy.c
index 8252e03d49..9ecfd38611 100644
--- a/board/hoho/usb_pd_policy.c
+++ b/board/hoho/usb_pd_policy.c
@@ -86,8 +86,11 @@ void pd_execute_data_swap(int port, int data_role)
/* Do nothing */
}
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap)
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
{
}
/* ----------------- Vendor Defined Messages ------------------ */
diff --git a/board/host/usb_pd_policy.c b/board/host/usb_pd_policy.c
index f477115e6f..d77731a8ff 100644
--- a/board/host/usb_pd_policy.c
+++ b/board/host/usb_pd_policy.c
@@ -95,8 +95,11 @@ void pd_execute_data_swap(int port, int data_role)
/* Do nothing */
}
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap)
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
{
}
diff --git a/board/plankton/usb_pd_policy.c b/board/plankton/usb_pd_policy.c
index ff6de38654..4e56ba8b36 100644
--- a/board/plankton/usb_pd_policy.c
+++ b/board/plankton/usb_pd_policy.c
@@ -137,8 +137,11 @@ void pd_execute_data_swap(int port, int data_role)
/* Do nothing */
}
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap)
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
{
}
diff --git a/board/ryu/usb_pd_policy.c b/board/ryu/usb_pd_policy.c
index aa2f62704b..b914cabc83 100644
--- a/board/ryu/usb_pd_policy.c
+++ b/board/ryu/usb_pd_policy.c
@@ -104,8 +104,11 @@ int pd_check_data_swap(int port, int data_role)
return 1;
}
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap)
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
{
}
diff --git a/board/ryu_p1/usb_pd_policy.c b/board/ryu_p1/usb_pd_policy.c
index e801cf49c2..99e06e39c1 100644
--- a/board/ryu_p1/usb_pd_policy.c
+++ b/board/ryu_p1/usb_pd_policy.c
@@ -105,8 +105,11 @@ int pd_check_data_swap(int port, int data_role)
return 1;
}
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap)
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
{
}
diff --git a/board/samus_pd/usb_pd_policy.c b/board/samus_pd/usb_pd_policy.c
index ecf2df31cc..f767a1d7cf 100644
--- a/board/samus_pd/usb_pd_policy.c
+++ b/board/samus_pd/usb_pd_policy.c
@@ -139,8 +139,15 @@ void pd_execute_data_swap(int port, int data_role)
pi3usb9281_set_switches(port, (data_role == PD_ROLE_UFP));
}
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap)
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+ /* If sink, and dual role toggling is on, then switch to source */
+ if (partner_pr_swap && pr_role == PD_ROLE_SINK &&
+ pd_get_dual_role() == PD_DRP_TOGGLE_ON)
+ pd_request_power_swap(port);
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
{
/* If UFP, try to switch to DFP */
if (partner_dr_swap && dr_role == PD_ROLE_UFP)
diff --git a/board/twinkie/usb_pd_policy.c b/board/twinkie/usb_pd_policy.c
index 4d568aff83..3491326ec3 100644
--- a/board/twinkie/usb_pd_policy.c
+++ b/board/twinkie/usb_pd_policy.c
@@ -100,8 +100,11 @@ int pd_check_data_swap(int port, int data_role)
return 1;
}
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap)
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
{
}
diff --git a/board/zinger/usb_pd_policy.c b/board/zinger/usb_pd_policy.c
index 09c52332f9..9559ec92b8 100644
--- a/board/zinger/usb_pd_policy.c
+++ b/board/zinger/usb_pd_policy.c
@@ -271,8 +271,11 @@ void pd_execute_data_swap(int port, int data_role)
/* Do nothing */
}
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap)
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
{
/* If DFP, try to switch to UFP */
if (partner_dr_swap && dr_role == PD_ROLE_DFP)
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index b231655080..bc9ecf98e6 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -210,19 +210,21 @@ static int pd_src_cap_cnt[PD_PORT_COUNT];
#define PD_FLAGS_DATA_SWAPPED (1 << 3) /* data swap complete */
#define PD_FLAGS_SNK_CAP_RECVD (1 << 4) /* sink capabilities received */
#define PD_FLAGS_GET_SNK_CAP_SENT (1 << 5) /* get sink cap sent */
-#define PD_FLAGS_NEW_CONTRACT (1 << 6) /* new power contract established */
-#define PD_FLAGS_EXPLICIT_CONTRACT (1 << 7) /* explicit pwr contract in place */
-#define PD_FLAGS_SFT_RST_DIS_COMM (1 << 8) /* disable comms after soft reset */
-#define PD_FLAGS_PREVIOUS_PD_CONN (1 << 9) /* previously PD connected */
+#define PD_FLAGS_EXPLICIT_CONTRACT (1 << 6) /* explicit pwr contract in place */
+#define PD_FLAGS_SFT_RST_DIS_COMM (1 << 7) /* disable comms after soft reset */
+#define PD_FLAGS_PREVIOUS_PD_CONN (1 << 8) /* previously PD connected */
+#define PD_FLAGS_CHECK_PR_ROLE (1 << 9)/* check power role in READY */
+#define PD_FLAGS_CHECK_DR_ROLE (1 << 10) /* check data role in READY */
/* Flags to clear on a disconnect */
#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \
PD_FLAGS_PARTNER_DR_DATA | \
PD_FLAGS_DATA_SWAPPED | \
PD_FLAGS_SNK_CAP_RECVD | \
PD_FLAGS_GET_SNK_CAP_SENT | \
- PD_FLAGS_NEW_CONTRACT | \
PD_FLAGS_EXPLICIT_CONTRACT | \
- PD_FLAGS_PREVIOUS_PD_CONN)
+ PD_FLAGS_PREVIOUS_PD_CONN | \
+ PD_FLAGS_CHECK_PR_ROLE | \
+ PD_FLAGS_CHECK_DR_ROLE)
static struct pd_protocol {
/* current port power role (SOURCE or SINK) */
@@ -1423,6 +1425,11 @@ void pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash,
}
#ifdef CONFIG_USB_PD_DUAL_ROLE
+enum pd_dual_role_states pd_get_dual_role(void)
+{
+ return drp_state;
+}
+
void pd_set_dual_role(enum pd_dual_role_states state)
{
int i;
@@ -1680,6 +1687,8 @@ void pd_task(void)
pd_set_vconn(port, pd[port].polarity, 1);
#endif
+ pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE |
+ PD_FLAGS_CHECK_DR_ROLE;
hard_reset_count = 0;
set_state(port, PD_STATE_SRC_STARTUP);
}
@@ -1721,7 +1730,6 @@ void pd_task(void)
* discover identity when we enter SRC_READY
*/
pd[port].flags |= PD_FLAGS_DATA_SWAPPED;
- pd[port].flags |= PD_FLAGS_NEW_CONTRACT;
/* reset various counters */
caps_count = 0;
src_connected = 0;
@@ -1821,7 +1829,6 @@ void pd_task(void)
res = send_control(port, PD_CTRL_PS_RDY);
if (res >= 0) {
timeout = 10*MSEC;
- pd[port].flags |= PD_FLAGS_NEW_CONTRACT;
/* it'a time to ping regularly the sink */
set_state(port, PD_STATE_SRC_READY);
} else {
@@ -1855,16 +1862,21 @@ void pd_task(void)
break;
}
- /* Check our role policy, which may trigger a swap */
- if (pd[port].flags & PD_FLAGS_NEW_CONTRACT) {
- pd_new_contract(
- port, PD_ROLE_SOURCE,
- pd[port].data_role,
- pd[port].flags &
- PD_FLAGS_PARTNER_DR_POWER,
- pd[port].flags &
- PD_FLAGS_PARTNER_DR_DATA);
- pd[port].flags &= ~PD_FLAGS_NEW_CONTRACT;
+ /* Check power role policy, which may trigger a swap */
+ if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) {
+ pd_check_pr_role(port, PD_ROLE_SOURCE,
+ pd[port].flags &
+ PD_FLAGS_PARTNER_DR_POWER);
+ pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE;
+ break;
+ }
+
+ /* Check data role policy, which may trigger a swap */
+ if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) {
+ pd_check_dr_role(port, pd[port].data_role,
+ pd[port].flags &
+ PD_FLAGS_PARTNER_DR_DATA);
+ pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE;
break;
}
@@ -2019,6 +2031,9 @@ void pd_task(void)
port, typec_curr, TYPE_C_VOLTAGE);
#endif
hard_reset_count = 0;
+ pd[port].flags |=
+ PD_FLAGS_CHECK_PR_ROLE |
+ PD_FLAGS_CHECK_DR_ROLE;
set_state(port, PD_STATE_SNK_DISCOVERY);
timeout = 10*MSEC;
hook_call_deferred(
@@ -2056,10 +2071,8 @@ void pd_task(void)
}
break;
case PD_STATE_SNK_HARD_RESET_RECOVER:
- if (pd[port].last_state != pd[port].task_state) {
+ if (pd[port].last_state != pd[port].task_state)
pd[port].flags |= PD_FLAGS_DATA_SWAPPED;
- pd[port].flags |= PD_FLAGS_NEW_CONTRACT;
- }
#ifdef CONFIG_USB_PD_NO_VBUS_DETECT
/*
* Can't measure vbus state so this is the maximum
@@ -2117,7 +2130,6 @@ void pd_task(void)
* discover identity when we enter SRC_READY
*/
pd[port].flags |= PD_FLAGS_DATA_SWAPPED;
- pd[port].flags |= PD_FLAGS_NEW_CONTRACT;
/*
* If we haven't passed hard reset counter,
@@ -2208,20 +2220,21 @@ void pd_task(void)
break;
}
- /*
- * Give time for source to check role policy first by
- * not running this the first time through state.
- */
- if ((pd[port].flags & PD_FLAGS_NEW_CONTRACT) &&
- pd[port].last_state == pd[port].task_state) {
- pd_new_contract(
- port, PD_ROLE_SINK,
- pd[port].data_role,
- pd[port].flags &
- PD_FLAGS_PARTNER_DR_POWER,
- pd[port].flags &
- PD_FLAGS_PARTNER_DR_DATA);
- pd[port].flags &= ~PD_FLAGS_NEW_CONTRACT;
+ /* Check power role policy, which may trigger a swap */
+ if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) {
+ pd_check_pr_role(port, PD_ROLE_SINK,
+ pd[port].flags &
+ PD_FLAGS_PARTNER_DR_POWER);
+ pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE;
+ break;
+ }
+
+ /* Check data role policy, which may trigger a swap */
+ if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) {
+ pd_check_dr_role(port, pd[port].data_role,
+ pd[port].flags &
+ PD_FLAGS_PARTNER_DR_DATA);
+ pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE;
break;
}
@@ -2481,8 +2494,18 @@ void pd_rx_event(int port)
#ifdef CONFIG_USB_PD_DUAL_ROLE
static void dual_role_on(void)
{
+ int i;
+
pd_set_dual_role(PD_DRP_TOGGLE_ON);
CPRINTS("chipset -> S0, enable dual-role toggling");
+
+ for (i = 0; i < PD_PORT_COUNT; i++) {
+#ifdef CONFIG_CHARGE_MANAGER
+ if (charge_manager_get_active_charge_port() != i)
+#endif
+ pd[i].flags |= PD_FLAGS_CHECK_PR_ROLE |
+ PD_FLAGS_CHECK_DR_ROLE;
+ }
}
DECLARE_HOOK(HOOK_CHIPSET_RESUME, dual_role_on, HOOK_PRIO_DEFAULT);
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 0dccc6695b..4a89e7d220 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -604,6 +604,12 @@ enum pd_dual_role_states {
PD_DRP_FORCE_SOURCE
};
/**
+ * Get dual role state
+ *
+ * @return Current dual-role state, from enum pd_dual_role_states
+ */
+enum pd_dual_role_states pd_get_dual_role(void);
+/**
* Set dual role state, from among enum pd_dual_role_states
*
* @param state New state of dual-role port, selected from
@@ -810,16 +816,22 @@ int pd_check_power_swap(int port);
int pd_check_data_swap(int port, int data_role);
/**
- * A new power contract has been established
+ * Check current power role for potential power swap
*
* @param port USB-C port number
* @param pr_role Our power role
- * @param dr_role Our data role
* @param partner_pr_swap Partner supports PR_SWAP
+ */
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap);
+
+/**
+ * Check current data role for potential data swap
+ *
+ * @param port USB-C port number
+ * @param dr_role Our data role
* @param partner_dr_swap Partner supports DR_SWAP
*/
-void pd_new_contract(int port, int pr_role, int dr_role,
- int partner_pr_swap, int partner_dr_swap);
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap);
/**
* Execute data swap.