summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2014-10-15 13:54:13 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-10-22 02:23:35 +0000
commit7eaa290c35a1ca5571854c7d31a5a125af665b65 (patch)
tree988251431ae31e2fad1079d5e301276e60b78bff
parent93aa23c6856b8b78f2c6a980ad0e82cb802afc3c (diff)
downloadchrome-ec-7eaa290c35a1ca5571854c7d31a5a125af665b65.tar.gz
usb_pd_protocol: Add support for charge_manager and voltage reporting
Integrate charge_manager and include several API changes designed for reporting voltage. 1. Make pd_choose_voltage set the chosen voltage for use by caller. 2. Add voltage parameter to pd_set_input_current. 3. Add pd_get_role to grab the sync / source state of a port. 4. Add charge manager PD + type C port initialization to the pd state machine. BUG=chrome-os-partner:32003 TEST=Manual on samus. Insert Apple charger, verify charge limit is selected appropriately. Insert PD charger, verify that charge port switches to PD port. Remove + reinsert chargers, verify that port / limit is selected appropriately. Remove battery, insert power source, verify that our power source port never becomes disabled. BRANCH=samus Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Change-Id: Idf3198c71d2ddf1e401e766fc82a4b7a02aed068 Reviewed-on: https://chromium-review.googlesource.com/223758 Reviewed-by: Alec Berg <alecaberg@chromium.org>
-rw-r--r--board/dingdong/usb_pd_policy.c10
-rw-r--r--board/firefly/usb_pd_policy.c10
-rw-r--r--board/fruitpie/usb_pd_policy.c10
-rw-r--r--board/hoho/usb_pd_policy.c10
-rw-r--r--board/host/usb_pd_policy.c17
-rw-r--r--board/plankton/usb_pd_policy.c10
-rw-r--r--board/ryu/usb_pd_policy.c10
-rw-r--r--board/samus_pd/usb_pd_policy.c10
-rw-r--r--board/twinkie/usb_pd_policy.c17
-rw-r--r--common/usb_pd_protocol.c107
-rw-r--r--include/usb.h2
-rw-r--r--include/usb_pd.h36
12 files changed, 200 insertions, 49 deletions
diff --git a/board/dingdong/usb_pd_policy.c b/board/dingdong/usb_pd_policy.c
index 64663172f3..1751407cdc 100644
--- a/board/dingdong/usb_pd_policy.c
+++ b/board/dingdong/usb_pd_policy.c
@@ -32,7 +32,8 @@ const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
/* Desired voltage requested as a sink (in millivolts) */
static unsigned select_mv = 5000;
-int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
+int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo,
+ uint32_t *curr_limit, uint32_t *supply_voltage)
{
int i;
int ma;
@@ -56,10 +57,13 @@ int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
ma = 10 * (src_caps[i] & 0x3FF);
*rdo = RDO_FIXED(i + 1, ma, ma, 0);
CPRINTF("Request [%d] %dV %dmA\n", i, set_mv/1000, ma);
- return ma;
+ *curr_limit = ma;
+ *supply_voltage = set_mv;
+ return EC_SUCCESS;
}
-void pd_set_input_current_limit(int port, uint32_t max_ma)
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
{
/* No battery, nothing to do */
return;
diff --git a/board/firefly/usb_pd_policy.c b/board/firefly/usb_pd_policy.c
index dd36fce43c..adccea1126 100644
--- a/board/firefly/usb_pd_policy.c
+++ b/board/firefly/usb_pd_policy.c
@@ -38,7 +38,8 @@ const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
/* Desired voltage requested as a sink (in millivolts) */
static unsigned select_mv = 20000;
-int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
+int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo,
+ uint32_t *curr_limit, uint32_t *supply_voltage)
{
int i;
int ma;
@@ -62,10 +63,13 @@ int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
ma = 10 * (src_caps[i] & 0x3FF);
*rdo = RDO_FIXED(i + 1, ma, ma, 0);
CPRINTF("Request [%d] %dV %dmA\n", i, set_mv/1000, ma);
- return ma;
+ *curr_limit = ma;
+ *supply_voltage = set_mv;
+ return EC_SUCCESS;
}
-void pd_set_input_current_limit(int port, uint32_t max_ma)
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
{
/* No battery, nothing to do */
return;
diff --git a/board/fruitpie/usb_pd_policy.c b/board/fruitpie/usb_pd_policy.c
index 8a80175c4f..f3e41b40c5 100644
--- a/board/fruitpie/usb_pd_policy.c
+++ b/board/fruitpie/usb_pd_policy.c
@@ -34,7 +34,8 @@ const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
/* Cap on the max voltage requested as a sink (in millivolts) */
static unsigned max_mv = -1; /* no cap */
-int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
+int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo,
+ uint32_t *curr_limit, uint32_t *supply_voltage)
{
int i;
int sel_mv;
@@ -75,10 +76,13 @@ int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
CPRINTF("Request [%d] %dV %dmA\n",
max_i, sel_mv/1000, ma);
}
- return max_ma;
+ *curr_limit = max_ma;
+ *supply_voltage = sel_mv;
+ return EC_SUCCESS;
}
-void pd_set_input_current_limit(int port, uint32_t max_ma)
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
{
int rv = charger_set_input_current(MAX(max_ma,
CONFIG_CHARGER_INPUT_CURRENT));
diff --git a/board/hoho/usb_pd_policy.c b/board/hoho/usb_pd_policy.c
index 7560821c1d..ce4ee055a0 100644
--- a/board/hoho/usb_pd_policy.c
+++ b/board/hoho/usb_pd_policy.c
@@ -32,7 +32,8 @@ const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
/* Desired voltage requested as a sink (in millivolts) */
static unsigned select_mv = 5000;
-int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
+int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo,
+ uint32_t *curr_limit, uint32_t *supply_voltage)
{
int i;
int ma;
@@ -56,10 +57,13 @@ int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
ma = 10 * (src_caps[i] & 0x3FF);
*rdo = RDO_FIXED(i + 1, ma, ma, 0);
CPRINTF("Request [%d] %dV %dmA\n", i, set_mv/1000, ma);
- return ma;
+ *curr_limit = ma;
+ *supply_voltage = set_mv;
+ return EC_SUCCESS;
}
-void pd_set_input_current_limit(int port, uint32_t max_ma)
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
{
/* No battery, nothing to do */
return;
diff --git a/board/host/usb_pd_policy.c b/board/host/usb_pd_policy.c
index 6237f05d5d..c1630aff0d 100644
--- a/board/host/usb_pd_policy.c
+++ b/board/host/usb_pd_policy.c
@@ -26,7 +26,8 @@ const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
/* Cap on the max voltage requested as a sink (in millivolts) */
static unsigned max_mv = -1; /* no cap */
-int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
+int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo,
+ uint32_t *curr_limit, uint32_t *supply_voltage)
{
int i;
int sel_mv;
@@ -56,14 +57,17 @@ int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
if ((src_caps[max_i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) {
int uw = 250000 * (src_caps[max_i] & 0x3FF);
*rdo = RDO_BATT(max_i + 1, uw/2, uw, 0);
- CPRINTF("Request [%d] %dV %d/%d mW\n",
- max_i, sel_mv/1000, uw/1000, uw/1000);
+ *curr_limit = uw/sel_mv;
+ CPRINTF("Request [%d] %dV %dmW\n",
+ max_i, sel_mv/1000, uw/1000);
} else {
int ma = 10 * (src_caps[max_i] & 0x3FF);
*rdo = RDO_FIXED(max_i + 1, ma / 2, ma, 0);
- CPRINTF("Request [%d] %dV %d/%d mA\n",
- max_i, sel_mv/1000, max_i, ma/2, ma);
+ *curr_limit = ma;
+ CPRINTF("Request [%d] %dV %dmA\n",
+ max_i, sel_mv/1000, ma);
}
+ *supply_voltage = sel_mv;
return EC_SUCCESS;
}
@@ -109,7 +113,8 @@ void pd_power_supply_reset(int port)
/* Not implemented */
}
-void pd_set_input_current_limit(int port, uint32_t max_ma)
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
{
/* Not implemented */
}
diff --git a/board/plankton/usb_pd_policy.c b/board/plankton/usb_pd_policy.c
index 8bfe5d41fd..80742b6a5b 100644
--- a/board/plankton/usb_pd_policy.c
+++ b/board/plankton/usb_pd_policy.c
@@ -57,7 +57,8 @@ int pd_get_source_pdo(const uint32_t **src_pdo)
return pd_src_pdo_cnts[pd_src_pdo_idx];
}
-int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
+int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo,
+ uint32_t *curr_limit, uint32_t *supply_voltage)
{
int i;
int ma;
@@ -81,10 +82,13 @@ int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
ma = 10 * (src_caps[i] & 0x3FF);
*rdo = RDO_FIXED(i + 1, ma, ma, 0);
CPRINTF("Request [%d] %dV %dmA\n", i, set_mv/1000, ma);
- return ma;
+ *curr_limit = ma;
+ *supply_voltage = set_mv;
+ return EC_SUCCESS;
}
-void pd_set_input_current_limit(int port, uint32_t max_ma)
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
{
/* No battery, nothing to do */
return;
diff --git a/board/ryu/usb_pd_policy.c b/board/ryu/usb_pd_policy.c
index 4237158593..561e6666ab 100644
--- a/board/ryu/usb_pd_policy.c
+++ b/board/ryu/usb_pd_policy.c
@@ -35,7 +35,8 @@ const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
/* Cap on the max voltage requested as a sink (in millivolts) */
static unsigned max_mv = -1; /* no cap */
-int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
+int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo,
+ uint32_t *curr_limit, uint32_t *supply_voltage)
{
int i;
int sel_mv;
@@ -76,10 +77,13 @@ int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
CPRINTF("Request [%d] %dV %dmA\n",
max_i, sel_mv/1000, ma);
}
- return max_ma;
+ *curr_limit = max_ma;
+ *supply_voltage = sel_mv;
+ return EC_SUCCESS;
}
-void pd_set_input_current_limit(int port, uint32_t max_ma)
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
{
int rv = charge_set_input_current_limit(MAX(max_ma,
CONFIG_CHARGER_INPUT_CURRENT));
diff --git a/board/samus_pd/usb_pd_policy.c b/board/samus_pd/usb_pd_policy.c
index 403adb9af1..680895ae72 100644
--- a/board/samus_pd/usb_pd_policy.c
+++ b/board/samus_pd/usb_pd_policy.c
@@ -37,7 +37,8 @@ static unsigned max_mv = -1; /* no cap */
/* PD MCU status for host response */
static struct ec_response_pd_status pd_status;
-int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
+int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo,
+ uint32_t *curr_limit, uint32_t *supply_voltage)
{
int i;
int sel_mv;
@@ -78,7 +79,9 @@ int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
CPRINTF("Request [%d] %dV %dmA\n",
max_i, sel_mv/1000, ma);
}
- return max_ma;
+ *curr_limit = max_ma;
+ *supply_voltage = sel_mv;
+ return EC_SUCCESS;
}
void pd_set_max_voltage(unsigned mv)
@@ -140,7 +143,8 @@ static void pd_send_ec_int(void)
gpio_set_level(GPIO_EC_INT, 0);
}
-void pd_set_input_current_limit(int port, uint32_t max_ma)
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
{
pd_status.curr_lim_ma = max_ma;
pd_send_ec_int();
diff --git a/board/twinkie/usb_pd_policy.c b/board/twinkie/usb_pd_policy.c
index 99d3611609..acfa5ab4e5 100644
--- a/board/twinkie/usb_pd_policy.c
+++ b/board/twinkie/usb_pd_policy.c
@@ -33,7 +33,8 @@ const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
/* Cap on the max voltage requested as a sink (in millivolts) */
static unsigned max_mv = -1; /* no cap */
-int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
+int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo,
+ uint32_t *curr_limit, uint32_t *supply_voltage)
{
int i;
int sel_mv;
@@ -63,18 +64,22 @@ int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
if ((src_caps[max_i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) {
int uw = 250000 * (src_caps[i] & 0x3FF);
*rdo = RDO_BATT(max_i + 1, uw/2, uw, 0);
- CPRINTF("Request [%d] %dV %d/%d mW\n",
- max_i, sel_mv/1000, uw/1000, uw/1000);
+ *curr_limit = uw/sel_mv;
+ CPRINTF("Request [%d] %dV %dmW\n",
+ max_i, sel_mv/1000, uw/1000);
} else {
int ma = 10 * (src_caps[max_i] & 0x3FF);
*rdo = RDO_FIXED(max_i + 1, ma / 2, ma, 0);
- CPRINTF("Request [%d] %dV %d/%d mA\n",
- max_i, sel_mv/1000, max_i, ma/2, ma);
+ *curr_limit = ma;
+ CPRINTF("Request [%d] %dV %dmA\n",
+ max_i, sel_mv/1000, ma);
}
+ *supply_voltage = sel_mv;
return EC_SUCCESS;
}
-void pd_set_input_current_limit(uint32_t max_ma)
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
{
}
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 6e57bcfcc6..3c4106afb8 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -5,6 +5,7 @@
#include "adc.h"
#include "board.h"
+#include "charge_manager.h"
#include "chipset.h"
#include "common.h"
#include "console.h"
@@ -153,6 +154,18 @@ static const uint8_t dec4b5b[] = {
#define GET_POLARITY(cc1, cc2) (CC_RD(cc2) || CC_RA(cc1))
#define IS_CABLE(cc1, cc2) (CC_RD(cc1) || CC_RD(cc2))
+/*
+ * Type C power source charge current limits are identified by their cc
+ * voltage (set by selecting the proper Rd resistor). Any voltage below
+ * TYPE_C_SRC_500_THRESHOLD will not be identified as a type C charger.
+ */
+#define TYPE_C_SRC_500_THRESHOLD PD_SRC_RD_THRESHOLD
+#define TYPE_C_SRC_1500_THRESHOLD 660 /* mV */
+#define TYPE_C_SRC_3000_THRESHOLD 1230 /* mV */
+
+/* Type C supply voltage (mV) */
+#define TYPE_C_VOLTAGE 5000 /* mV */
+
/* PD counter definitions */
#define PD_MESSAGE_ID_COUNT 7
#define PD_RETRY_COUNT 2
@@ -221,8 +234,9 @@ static struct pd_protocol {
uint8_t ping_enabled;
#ifdef CONFIG_USB_PD_DUAL_ROLE
- /* Current limit based on the last request message */
+ /* Current limit / voltage based on the last request message */
uint32_t curr_limit;
+ uint32_t supply_voltage;
#endif
/* PD state for Vendor Defined Messages */
@@ -653,10 +667,13 @@ static void execute_hard_reset(int port)
PD_STATE_SNK_DISCONNECTED : PD_STATE_SRC_DISCONNECTED);
/* Clear the input current limit */
- pd_set_input_current_limit(port, 0);
+ pd_set_input_current_limit(port, 0, 0);
+#ifdef CONFIG_CHARGE_MANAGER
+ typec_set_input_current_limit(port, 0, 0);
+#endif /* CONFIG_CHARGE_MANAGER */
#else
set_state(port, PD_STATE_SRC_DISCONNECTED);
-#endif
+#endif /* CONFIG_USB_PD_DUAL_ROLE */
pd_power_supply_reset(port);
pd[port].src_recover = get_time().val + PD_T_SRC_RECOVER;
CPRINTF("HARD RESET!\n");
@@ -697,13 +714,15 @@ static void pd_store_src_cap(int port, int cnt, uint32_t *src_caps)
static void pd_send_request_msg(int port)
{
- uint32_t rdo;
+ uint32_t rdo, curr_limit, supply_voltage;
int res;
/* we were waiting for them, let's process them */
- res = pd_choose_voltage(pd_src_cap_cnt[port], pd_src_caps[port], &rdo);
- if (res >= 0) {
- pd[port].curr_limit = res;
+ res = pd_choose_voltage(pd_src_cap_cnt[port], pd_src_caps[port], &rdo,
+ &curr_limit, &supply_voltage);
+ if (res == EC_SUCCESS) {
+ pd[port].curr_limit = curr_limit;
+ pd[port].supply_voltage = supply_voltage;
res = send_request(port, rdo);
if (res >= 0)
set_state(port, PD_STATE_SNK_REQUESTED);
@@ -797,7 +816,8 @@ static void handle_ctrl_request(int port, uint16_t head,
set_state(port, PD_STATE_HARD_RESET);
} else if (pd[port].role == PD_ROLE_SINK) {
set_state(port, PD_STATE_SNK_READY);
- pd_set_input_current_limit(port, pd[port].curr_limit);
+ pd_set_input_current_limit(port, pd[port].curr_limit,
+ pd[port].supply_voltage);
}
break;
case PD_CTRL_REJECT:
@@ -1128,7 +1148,13 @@ void pd_set_dual_role(enum pd_dual_role_states state)
}
}
}
-#endif
+
+int pd_get_role(int port)
+{
+ return pd[port].role;
+}
+
+#endif /* CONFIG_USB_PD_DUAL_ROLE */
int pd_get_polarity(int port)
{
@@ -1162,6 +1188,40 @@ void pd_ping_enable(int port, int enable)
pd[port].ping_enabled = enable;
}
+#ifdef CONFIG_CHARGE_MANAGER
+/*
+ * Initialize type C and PD current limits based upon cc_voltage. The PD
+ * current limit may be revised upward (or downward to zero) depending on
+ * PD negotiation.
+ */
+void pd_init_current_limits(int port, int cc_voltage)
+{
+ int charge;
+
+ /* Detect type C charger current limit based upon vbus voltage. */
+ if (cc_voltage > TYPE_C_SRC_3000_THRESHOLD)
+ charge = 3000;
+ else if (cc_voltage > TYPE_C_SRC_1500_THRESHOLD)
+ charge = 1500;
+ else if (cc_voltage > PD_SNK_VA)
+ charge = 500;
+ else
+ charge = 0;
+ typec_set_input_current_limit(port, charge, TYPE_C_VOLTAGE);
+
+ /*
+ * Set the initial PD current limit based upon cc_voltage. If a PD
+ * charger is attached, this will get changed upward later once
+ * negotiation is complete.
+ */
+ if (cc_voltage > PD_SNK_VA)
+ charge = PD_MIN_MA;
+ else
+ charge = 0;
+ pd_set_input_current_limit(port, charge, PD_MIN_MV);
+}
+#endif /* CONFIG_CHARGE_MANAGER */
+
void pd_task(void)
{
int head;
@@ -1173,7 +1233,10 @@ void pd_task(void)
#ifdef CONFIG_USB_PD_DUAL_ROLE
uint64_t next_role_swap = PD_T_DRP_SNK;
int hard_reset_count = 0;
-#endif
+#ifdef CONFIG_CHARGE_MANAGER
+ static int initialized[PD_PORT_COUNT];
+#endif /* CONFIG_CHARGE_MANAGER */
+#endif /* CONFIG_USB_PD_DUAL_ROLE */
enum pd_states this_state;
timestamp_t now;
int caps_count = 0;
@@ -1395,12 +1458,30 @@ void pd_task(void)
pd[port].polarity);
/* reset message ID on connection */
pd[port].msg_id = 0;
+#ifdef CONFIG_CHARGE_MANAGER
+ initialized[port] = 1;
+ pd_init_current_limits(port,
+ pd[port].
+ polarity ?
+ cc2_volt :
+ cc1_volt);
+#endif
set_state(port, PD_STATE_SNK_DISCOVERY);
timeout = 10*MSEC;
break;
}
}
+#ifdef CONFIG_CHARGE_MANAGER
+ /*
+ * Set charge limit to zero if we have yet to set
+ * a limit for this port.
+ */
+ if (!initialized[port]) {
+ initialized[port] = 1;
+ pd_init_current_limits(port, 0);
+ }
+#endif
/*
* If no source detected, reset hard reset counter and
* check for role swap
@@ -1417,7 +1498,6 @@ void pd_task(void)
/* Swap states quickly */
timeout = 2*MSEC;
}
-
break;
case PD_STATE_SNK_DISCOVERY:
/*
@@ -1530,7 +1610,10 @@ void pd_task(void)
/* Sink: detect disconnect by monitoring VBUS */
set_state(port, PD_STATE_SNK_DISCONNECTED);
/* Clear the input current limit */
- pd_set_input_current_limit(port, 0);
+ pd_set_input_current_limit(port, 0, 0);
+#ifdef CONFIG_CHARGE_MANAGER
+ typec_set_input_current_limit(port, 0, 0);
+#endif
/* set timeout small to reconnect fast */
timeout = 5*MSEC;
}
diff --git a/include/usb.h b/include/usb.h
index 53e53939d7..98e81794ab 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -186,6 +186,8 @@ struct usb_endpoint_descriptor {
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
+#define USB_BC12_CHARGE_VOLTAGE 5000 /* mA */
+
/* Helpers for descriptors */
#define WIDESTR(quote) WIDESTR2(quote)
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 29c0165ad2..405f35024b 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -499,6 +499,13 @@ enum pd_dual_role_states {
* enum pd_dual_role_states
*/
void pd_set_dual_role(enum pd_dual_role_states state);
+
+/**
+ * Get role, from among PD_ROLE_SINK and PD_ROLE_SOURCE
+ *
+ * @param port Port number from which to get role
+ */
+int pd_get_role(int port);
#endif
/* Control Message type */
@@ -561,6 +568,12 @@ enum pd_data_msg_type {
#define PD_RST2 0x19
#define PD_EOP 0x0D
+/* Minimum PD supply current (mA) */
+#define PD_MIN_MA 500
+
+/* Minimum PD voltage (mV) */
+#define PD_MIN_MV 5000
+
/* --- Policy layer functions --- */
/**
@@ -569,9 +582,12 @@ enum pd_data_msg_type {
* @param cnt the number of Power Data Objects.
* @param src_caps Power Data Objects representing the source capabilities.
* @param rdo requested Request Data Object.
- * @return <0 if invalid, else value is the current limit of the RDO data
+ * @param curr_limit selected current limit (stored on success)
+ * @param supply_voltage selected supply voltage (stored on success)
+ * @return <0 if invalid, else EC_SUCCESS
*/
-int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo);
+int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo,
+ uint32_t *curr_limit, uint32_t *supply_voltage);
/**
* Put a cap on the max voltage requested as a sink.
@@ -612,12 +628,24 @@ int pd_set_power_supply_ready(int port);
void pd_request_source_voltage(int port, int mv);
/**
- * Set the input current limit.
+ * Set the PD input current limit.
+ *
+ * @port USB-C port number
+ * @max_ma Maximum current limit
+ * @supply_voltage Voltage at which current limit is applied
+ */
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage);
+
+/**
+ * Set the type-C input current limit.
*
* @port USB-C port number
* @max_ma Maximum current limit
+ * @supply_voltage Voltage at which current limit is applied
*/
-void pd_set_input_current_limit(int port, uint32_t max_ma);
+void typec_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage);
/**
* Verify board specific health status : current, voltages...