summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Hurst <shurst@google.com>2017-01-10 09:55:37 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-10-30 17:05:06 +0000
commit910d9c8ac31ed834d4ab6bf658d5ee21be332ca0 (patch)
treefbe9d4daa7567e52e57a0331d91fce7f336d839c
parent0e15ed7dc241187a3d15215c6af82e623bb6046d (diff)
downloadchrome-ec-910d9c8ac31ed834d4ab6bf658d5ee21be332ca0.tar.gz
pd: support gotoMin and giveBack
In Sink mode, on the receipt of a GotoMin message, reduce the current consumption to some minimum level. BUG=chrome-os-partner:33688 TEST=Manual testing Used a Kevin, with test routine, to test GotoMin feature on another Kevin unit. Test routine: if (!strcasecmp(argv[2], "gm")) { ccprintf("send goto min\n"); send_control(port, PD_CTRL_GOTO_MIN); send_control(port, PD_CTRL_PS_RDY); } Kevin with GotoMin feature: # ectool usbpdpower 0 Port 0: SNK DRP PD 4277mV / 3000mA, max 5000mV / 3000mA / 15000mW Port 1: Disconnected After Test routine is executed: # ectool usbpdpower 0 Port 0: SNK DRP PD 4906mV / 500mA, max 5000mV / 500mA / 2500mW Port 1: Disconnected BRANCH=none Change-Id: Iaac6e19706ceb10ccaff4d602d63fc086c808c8f Reviewed-on: https://chromium-review.googlesource.com/425728 Commit-Ready: Sam Hurst <shurst@google.com> Tested-by: Sam Hurst <shurst@google.com> Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/740001 Reviewed-by: Shawn N <shawnn@chromium.org> Reviewed-by: Sam Hurst <shurst@google.com> Tested-by: Shawn N <shawnn@chromium.org> Commit-Queue: Shawn N <shawnn@chromium.org>
-rw-r--r--board/host/board.h3
-rw-r--r--board/kevin/board.h4
-rw-r--r--board/kevin/usb_pd_policy.c10
-rw-r--r--common/usb_pd_policy.c30
-rw-r--r--common/usb_pd_protocol.c15
-rw-r--r--include/config.h3
-rw-r--r--include/usb_pd.h9
-rw-r--r--test/build.mk2
-rw-r--r--test/test_config.h5
-rw-r--r--test/usb_pd.c32
l---------test/usb_pd_giveback.tasklist1
11 files changed, 111 insertions, 3 deletions
diff --git a/board/host/board.h b/board/host/board.h
index a5b6a5dc20..aa82d600d4 100644
--- a/board/host/board.h
+++ b/board/host/board.h
@@ -69,4 +69,7 @@ extern const int supplier_priority[];
#define PD_MAX_CURRENT_MA 3000
#define PD_MAX_VOLTAGE_MV 20000
+#define PD_MIN_CURRENT_MA 500
+#define PD_MIN_POWER_MW 7500
+
#endif /* __CROS_EC_BOARD_H */
diff --git a/board/kevin/board.h b/board/kevin/board.h
index a0a2498945..7186e0fc45 100644
--- a/board/kevin/board.h
+++ b/board/kevin/board.h
@@ -135,6 +135,7 @@
#ifdef BOARD_KEVIN
#define CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD
+#define CONFIG_USB_PD_GIVE_BACK
#endif
#define PD_OPERATING_POWER_MW 15000
@@ -142,6 +143,9 @@
#define PD_MAX_CURRENT_MA 3000
#define PD_MAX_VOLTAGE_MV 20000
+#define PD_MIN_CURRENT_MA 500
+#define PD_MIN_POWER_MW 2500
+
#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */
#define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */
#define PD_VCONN_SWAP_DELAY 5000 /* us */
diff --git a/board/kevin/usb_pd_policy.c b/board/kevin/usb_pd_policy.c
index bc1910df55..d8cf201a94 100644
--- a/board/kevin/usb_pd_policy.c
+++ b/board/kevin/usb_pd_policy.c
@@ -60,6 +60,16 @@ int board_vbus_source_enabled(int port)
return vbus_en[port];
}
+void pd_snk_give_back(int port, uint32_t * const ma, uint32_t * const mv)
+{
+ /* Just reduce the current */
+ *ma = PD_MIN_CURRENT_MA;
+ pd_set_input_current_limit(port, *ma, *mv);
+#ifdef CONFIG_CHARGE_MANAGER
+ charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, *ma);
+#endif
+}
+
static void board_vbus_update_source_current(int port)
{
enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN;
diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c
index 6a3d8b3ee8..808b7e4bd1 100644
--- a/common/usb_pd_policy.c
+++ b/common/usb_pd_policy.c
@@ -179,6 +179,8 @@ int pd_build_request(int cnt, uint32_t *src_caps, uint32_t *rdo,
{
int pdo_index, flags = 0;
int uw;
+ int max_or_min_ma;
+ int max_or_min_mw;
if (req_type == PD_REQUEST_VSAFE5V)
/* src cap 0 should be vSafe5V */
@@ -197,11 +199,35 @@ int pd_build_request(int cnt, uint32_t *src_caps, uint32_t *rdo,
if (uw < (1000 * PD_OPERATING_POWER_MW))
flags |= RDO_CAP_MISMATCH;
+#ifdef CONFIG_USB_PD_GIVE_BACK
+ /* Tell source we are give back capable. */
+ flags |= RDO_GIVE_BACK;
+
+ /*
+ * BATTERY PDO: Inform the source that the sink will reduce
+ * power to this minimum level on receipt of a GotoMin Request.
+ */
+ max_or_min_mw = PD_MIN_POWER_MW;
+
+ /*
+ * FIXED or VARIABLE PDO: Inform the source that the sink will reduce
+ * current to this minimum level on receipt of a GotoMin Request.
+ */
+ max_or_min_ma = PD_MIN_CURRENT_MA;
+#else
+ /*
+ * Can't give back, so set maximum current and power to operating
+ * level.
+ */
+ max_or_min_ma = *ma;
+ max_or_min_mw = uw / 1000;
+#endif
+
if ((src_caps[pdo_index] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) {
int mw = uw / 1000;
- *rdo = RDO_BATT(pdo_index + 1, mw, mw, flags);
+ *rdo = RDO_BATT(pdo_index + 1, mw, max_or_min_mw, flags);
} else {
- *rdo = RDO_FIXED(pdo_index + 1, *ma, *ma, flags);
+ *rdo = RDO_FIXED(pdo_index + 1, *ma, max_or_min_ma, flags);
}
return EC_SUCCESS;
}
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index d057fc54e6..0485f6316e 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -881,6 +881,21 @@ static void handle_ctrl_request(int port, uint16_t head,
break;
#ifdef CONFIG_USB_PD_DUAL_ROLE
case PD_CTRL_GOTO_MIN:
+#ifdef CONFIG_USB_PD_GIVE_BACK
+ if (pd[port].task_state == PD_STATE_SNK_READY) {
+ /*
+ * Reduce power consumption now!
+ *
+ * The source will restore power to this sink
+ * by sending a new source cap message at a
+ * later time.
+ */
+ pd_snk_give_back(port, &pd[port].curr_limit,
+ &pd[port].supply_voltage);
+ set_state(port, PD_STATE_SNK_TRANSITION);
+ }
+#endif
+
break;
case PD_CTRL_PS_RDY:
if (pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE) {
diff --git a/include/config.h b/include/config.h
index 56c9b3bde3..d1595d4247 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2069,6 +2069,9 @@
/* Check whether PD is the sole power source before flash erase operation */
#undef CONFIG_USB_PD_FLASH_ERASE_CHECK
+/* Define if this board, operating as a sink, can give power back to a source */
+#undef CONFIG_USB_PD_GIVE_BACK
+
/* Major and Minor ChromeOS specific PD device Hardware IDs. */
#undef CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR
#undef CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 069125c432..c5feaf3699 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -911,6 +911,15 @@ int pd_is_max_request_allowed(void);
void pd_process_source_cap(int port, int cnt, uint32_t *src_caps);
/**
+ * Reduce the sink power consumption to a minimum value.
+ *
+ * @param port USB-C port number
+ * @param ma reduce current to minimum value.
+ * @param mv reduce voltage to minimum value.
+ */
+void pd_snk_give_back(int port, uint32_t * const ma, uint32_t * const mv);
+
+/**
* Put a cap on the max voltage requested as a sink.
* @param mv maximum voltage in millivolts.
*/
diff --git a/test/build.mk b/test/build.mk
index 1e45061502..d6f1ac6cb8 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -39,6 +39,7 @@ test-list-host+=math_util motion_lid sbs_charging_v2 battery_get_params_smart
test-list-host+=lightbar inductive_charging usb_pd fan charge_manager
test-list-host+=charge_manager_drp_charging charge_ramp
test-list-host+=rsa rsa3
+test-list-host+=usb_pd_giveback
endif
battery_get_params_smart-y=battery_get_params_smart.o
@@ -78,6 +79,7 @@ thermal-y=thermal.o
timer_calib-y=timer_calib.o
timer_dos-y=timer_dos.o
usb_pd-y=usb_pd.o
+usb_pd_giveback-y=usb_pd.o
utils-y=utils.o
battery_get_params_smart-y=battery_get_params_smart.o
lightbar-y=lightbar.o
diff --git a/test/test_config.h b/test/test_config.h
index 837dd8a5c0..9229c5cc8b 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -135,7 +135,7 @@ int ncp15wb_calculate_temp(uint16_t adc);
#define CONFIG_ALS_LIGHTBAR_DIMMING 0
#endif
-#ifdef TEST_USB_PD
+#if defined(TEST_USB_PD) || defined(TEST_USB_PD_GIVEBACK)
#define CONFIG_USB_POWER_DELIVERY
#define CONFIG_USB_PD_CUSTOM_VDM
#define CONFIG_USB_PD_DUAL_ROLE
@@ -144,7 +144,10 @@ int ncp15wb_calculate_temp(uint16_t adc);
#define CONFIG_USB_PD_TCPM_STUB
#define CONFIG_SHA256
#define CONFIG_SW_CRC
+#ifdef TEST_USB_PD_GIVEBACK
+#define CONFIG_USB_PD_GIVE_BACK
#endif
+#endif /* TEST_USB_PD || TEST_USB_PD_GIVEBACK */
#if defined(TEST_CHARGE_MANAGER) || defined(TEST_CHARGE_MANAGER_DRP_CHARGING)
#define CONFIG_CHARGE_MANAGER
diff --git a/test/usb_pd.c b/test/usb_pd.c
index 3368484a24..f9a40aefa4 100644
--- a/test/usb_pd.c
+++ b/test/usb_pd.c
@@ -24,6 +24,8 @@ struct pd_port_t {
int partner_polarity;
} pd_port[CONFIG_USB_PD_PORT_COUNT];
+static int give_back_called;
+
/* Mock functions */
int pd_adc_read(int port, int cc)
@@ -158,9 +160,39 @@ static void unplug(int port)
usleep(30 * MSEC);
}
+void pd_snk_give_back(int port, uint32_t * const ma, uint32_t * const mv)
+{
+ if (*ma == 3000)
+ give_back_called = 1;
+}
+
+/*
+static void simulate_ps_rdy(int port)
+{
+ uint16_t header = PD_HEADER(PD_CTRL_PS_RDY, PD_ROLE_SOURCE,
+ PD_ROLE_DFP, pd_port[port].msg_rx_id,
+ 0);
+
+ simulate_rx_msg(port, header, 0, NULL);
+}
+
+static void simulate_goto_min(int port)
+{
+ uint16_t header = PD_HEADER(PD_CTRL_GOTO_MIN, PD_ROLE_SOURCE,
+ PD_ROLE_DFP, pd_port[port].msg_rx_id, 0);
+
+ simulate_rx_msg(port, header, 0, NULL);
+}
+*/
+
static int test_request(void)
{
+#ifdef CONFIG_USB_PD_GIVE_BACK
+ uint32_t expected_rdo = RDO_FIXED(1, 900, PD_MIN_CURRENT_MA,
+ RDO_CAP_MISMATCH | RDO_GIVE_BACK);
+#else
uint32_t expected_rdo = RDO_FIXED(1, 900, 900, RDO_CAP_MISMATCH);
+#endif
plug_in_source(0, 0);
task_wake(PD_PORT_TO_TASK_ID(0));
diff --git a/test/usb_pd_giveback.tasklist b/test/usb_pd_giveback.tasklist
new file mode 120000
index 0000000000..45cc6c8aa2
--- /dev/null
+++ b/test/usb_pd_giveback.tasklist
@@ -0,0 +1 @@
+usb_pd.tasklist \ No newline at end of file