summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott <scollyer@chromium.org>2017-01-13 17:48:31 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-05-17 17:04:27 +0000
commit135c9cd1bcfc0cf44b9ccf333b3861a193712edb (patch)
tree53c681f85121d52fe06429c9becc8aff65ff2bd6
parentcdb7741359c96a73044ba754abda68e25f50555a (diff)
downloadchrome-ec-135c9cd1bcfc0cf44b9ccf333b3861a193712edb.tar.gz
servo_v4: Support to enable Type C DTS mode
- Defined the config option CONFIG_USB_PD_DTS to board.h. - Added ccd_set_mode function in board.c - Removed ccd attach/detach functions from board.c as that function is - now integrated in the the usb_pd state machine. - Removed the fixed polarity that was being used in usb_pd_config.h so that the DUT port could connect as a SNK device. - Defined PD_ROLE_DEFAULT to override the value in usb_Pd.h so that CHG is SNK and DUT is SRC This set of changes allows servo_v4 to act like a suzyq. Hoever, PD messaging is still not supported. The CHG port can still connect as a SNK device, but VBUS on the DUT is only being provided by the host and not the CHG port. BUG=chrome-os-partner:61878 BRANCH=None TEST=Manual Connected zinger to CHG port and verifed via servo_v4 console that it reached SNK_READY. Connected DUT port to Reef and verified that it reached SRC_ACCESSORY state and that the correct SBU polarity was selected and that lsusb shows H1 as a USB device. Bus 003 Device 042: ID 18d1:5014 Google Inc. Signed-off-by: Scott <scollyer@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/428309 Commit-Ready: Scott Collyer <scollyer@chromium.org> Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Change-Id: I4a0ab2468f383a3ba4db3a3236bb18df6a2c405a Reviewed-on: https://chromium-review.googlesource.com/506954 Reviewed-by: Nick Sanders <nsanders@chromium.org>
-rw-r--r--board/servo_v4/board.c253
-rw-r--r--board/servo_v4/board.h4
-rw-r--r--board/servo_v4/usb_pd_config.h113
-rw-r--r--board/servo_v4/usb_pd_policy.c27
4 files changed, 122 insertions, 275 deletions
diff --git a/board/servo_v4/board.c b/board/servo_v4/board.c
index 9fb6fbd502..99a0fa1500 100644
--- a/board/servo_v4/board.c
+++ b/board/servo_v4/board.c
@@ -6,6 +6,7 @@
#include "adc.h"
#include "adc_chip.h"
+#include "case_closed_debug.h"
#include "common.h"
#include "console.h"
#include "ec_version.h"
@@ -303,186 +304,63 @@ static void init_ioexpander(void)
i2c_write8(1, 0x40, 0x7, 0x0);
}
-/* State of CC lines presented to DUT */
-/* Dual Rd pulldown, classic debug device. */
-#define CCD_ID_RDRD 0
-/* RpUSB + Rp1A5, indicates a self powered dongle. */
-#define CCD_ID_RPUSB 1
-/* One Rd. Device w/o CCD */
-#define CCD_ID_NONE 4
-
-static int ccd_id = CCD_ID_NONE;
-
-/* Set CC values according to requested mode. */
-static void init_ccd(int mode)
-{
- int cc1_rd = GPIO_INPUT;
- int cc2_rd = GPIO_INPUT;
- int cc1_rpusb = GPIO_INPUT;
- int cc2_rpusb = GPIO_INPUT;
- int cc1_rp1a5 = GPIO_INPUT;
- int cc2_rp1a5 = GPIO_INPUT;
- int cc1_rp3a0 = GPIO_INPUT;
- int cc2_rp3a0 = GPIO_INPUT;
-
- switch (mode) {
- case CCD_ID_RDRD:
- cc1_rd = GPIO_OUT_LOW;
- cc2_rd = GPIO_OUT_LOW;
- break;
-
- case CCD_ID_RPUSB:
- cc1_rpusb = GPIO_OUT_HIGH;
- cc2_rp1a5 = GPIO_OUT_HIGH;
- break;
-
- default:
- cc1_rd = GPIO_OUT_LOW;
- mode = CCD_ID_NONE;
- break;
- }
-
- gpio_set_flags(GPIO_USB_DUT_CC1_RD, cc1_rd);
- gpio_set_flags(GPIO_USB_DUT_CC2_RD, cc2_rd);
- gpio_set_flags(GPIO_USB_DUT_CC1_RPUSB, cc1_rpusb);
- gpio_set_flags(GPIO_USB_DUT_CC2_RPUSB, cc2_rpusb);
- gpio_set_flags(GPIO_USB_DUT_CC1_RP1A5, cc1_rp1a5);
- gpio_set_flags(GPIO_USB_DUT_CC2_RP1A5, cc2_rp1a5);
- gpio_set_flags(GPIO_USB_DUT_CC1_RP3A0, cc1_rp3a0);
- gpio_set_flags(GPIO_USB_DUT_CC2_RP3A0, cc2_rp3a0);
-
- /* Disable CCD until we can detect orientation */
- gpio_set_level(GPIO_SBU_MUX_EN, 0);
- write_ioexpander(0, 0, 0);
-
- ccd_id = mode;
-}
-
-
-/* Define voltage thresholds for CCD and SBU USB detection */
+/* Define voltage thresholds for SBU USB detection */
#define GND_MAX_MV 350
-#define PULL_0V35_MV 350
-#define PULL_0V55_MV 550
-#define PULL_0V9_MV 900
-#define PULL_1V1_MV 1100
-#define PULL_2V0_MV 2000
-#define POWER_MIN_MV 3000
#define USB_HIGH_MV 1500
+/* Tracks current state of ccd */
+static int ccd_mode;
-/* Check if presented CCD was accepted by the device */
-static int check_ccd_request(int cc1, int cc2)
-{
- if ((ccd_id == CCD_ID_RDRD) &&
- (cc1 > PULL_0V35_MV) && (cc1 < PULL_0V55_MV) &&
- (cc2 > PULL_0V35_MV) && (cc2 < PULL_0V55_MV))
- return 1;
-
- if ((ccd_id == CCD_ID_RPUSB) &&
- (cc1 > PULL_0V35_MV) && (cc1 < PULL_0V55_MV) &&
- (cc2 > PULL_0V9_MV) && (cc2 < PULL_1V1_MV))
- return 1;
-
- return 0;
-}
+static void ccd_measure_sbu(void);
+DECLARE_DEFERRED(ccd_measure_sbu);
-/* Check if CC lines indicate an unplug event */
-static int check_usb_disconnect(int cc1, int cc2)
+static void ccd_measure_sbu(void)
{
- if ((cc1 < GND_MAX_MV) && (cc2 < GND_MAX_MV))
- return 1;
-
- if ((cc1 > POWER_MIN_MV) && (cc2 > POWER_MIN_MV))
- return 1;
-
- return 0;
+ int sbu1;
+ int sbu2;
+
+ /* Read sbu voltage levels */
+ sbu1 = adc_read_channel(ADC_SBU1_DET);
+ sbu2 = adc_read_channel(ADC_SBU2_DET);
+
+ /* USB FS pulls one line high for connect request */
+ if ((sbu1 > USB_HIGH_MV) && (sbu2 < GND_MAX_MV)) {
+ /* SBU flip = 1 */
+ write_ioexpander(0, 2, 1);
+ msleep(10);
+ gpio_set_level(GPIO_SBU_MUX_EN, 1);
+ ccd_mode = CCD_MODE_ENABLED;
+ CPRINTS("CCD: connected flip");
+ } else if ((sbu2 > USB_HIGH_MV) &&
+ (sbu1 < GND_MAX_MV)) {
+ /* SBU flip = 0 */
+ write_ioexpander(0, 2, 0);
+ msleep(10);
+ gpio_set_level(GPIO_SBU_MUX_EN, 1);
+ ccd_mode = CCD_MODE_ENABLED;
+ CPRINTS("CCD: connected noflip");
+ } else {
+ /* Measure again after 100 msec */
+ hook_call_deferred(&ccd_measure_sbu_data, 100 * MSEC);
+ }
}
-
-/* Current mode for CCD USB line connection */
-/* Cable not plugged in */
-#define CCD_MODE_DISCONNECTED 0
-/* Cable plugged in, CCD detected in default orientation */
-#define CCD_MODE_CONNECTED 1
-/* Cable plugged in, CCD detected in flip orientation */
-#define CCD_MODE_CONNECTED_FLIP 2
-/* Cable plugged in, nothing detected on SBU lines */
-#define CCD_MODE_CONNECTED_NONE 3
-/* No type-c cable in servo. */
-#define CCD_MODE_USBA 4
-
-static int mode = CCD_MODE_DISCONNECTED;
-
-/*
- * We don't have an available interrupt, so we'll just check this
- * every second. Update state every tick if necessary.
- */
-static void usb_sbu_tick(void)
+void ccd_set_mode(enum ccd_mode new_mode)
{
- int cc1, cc2;
-
- /* Check if we have a CCD cable */
- if ((mode == CCD_MODE_USBA) || !gpio_get_level(GPIO_DONGLE_DET)) {
- mode = CCD_MODE_USBA;
- return;
- }
-
- /* Check CC lines via ADC */
- cc1 = adc_read_channel(ADC_DUT_CC1_PD);
- cc2 = adc_read_channel(ADC_DUT_CC2_PD);
-
- if (mode == CCD_MODE_DISCONNECTED) {
- /* Check if both CC lines are pulled, and we are connected */
- if (check_ccd_request(cc1, cc2)) {
- int sbu1;
- int sbu2;
-
- /*
- * Give the onboard CCD micro 100ms
- * to notice and enable USB, then check adc levels.
- */
- usleep(100000);
- sbu1 = adc_read_channel(ADC_SBU1_DET);
- sbu2 = adc_read_channel(ADC_SBU2_DET);
-
- CPRINTS("CCD: Plug detect cc1:%d cc2:%d "
- "sbu1:%d, sbu2:%d",
- cc1, cc2, sbu1, sbu2);
-
- /* USB FS pulls one line high for connect request */
- if ((sbu1 > USB_HIGH_MV) && (sbu2 < GND_MAX_MV)) {
- /* SBU flip = 1 */
- write_ioexpander(0, 2, 1);
- usleep(10000);
- gpio_set_level(GPIO_SBU_MUX_EN, 1);
- mode = CCD_MODE_CONNECTED;
- CPRINTS("CCD: connected flip");
- } else if ((sbu2 > USB_HIGH_MV) &&
- (sbu1 < GND_MAX_MV)) {
- /* SBU flip = 0 */
- write_ioexpander(0, 2, 0);
- usleep(10000);
- gpio_set_level(GPIO_SBU_MUX_EN, 1);
- mode = CCD_MODE_CONNECTED_FLIP;
- CPRINTS("CCD: connected noflip");
- } else {
- mode = CCD_MODE_CONNECTED_NONE;
- CPRINTS("CCD: connected none");
- }
- }
- } else {
- /* mode == CCD_MODE_CONNECTED[_FLIP] */
- if (check_usb_disconnect(cc1, cc2)) {
- /* We are not connected to anything */
-
- /* Turn off CCD */
- gpio_set_level(GPIO_SBU_MUX_EN, 0);
- CPRINTS("CCD: disconnect");
- mode = CCD_MODE_DISCONNECTED;
- }
+ if (new_mode == CCD_MODE_ENABLED) {
+ /* Allow some time following turning on of VBUS */
+ hook_call_deferred(&ccd_measure_sbu_data,
+ PD_POWER_SUPPLY_TURN_ON_DELAY);
+ } else if (new_mode == CCD_MODE_DISABLED) {
+ /* We are not connected to anything */
+
+ /* Disable ccd_measure_sbu deferred call always */
+ hook_call_deferred(&ccd_measure_sbu_data, -1);
+ /* Turn off CCD */
+ gpio_set_level(GPIO_SBU_MUX_EN, 0);
+ CPRINTS("CCD: disconnect");
+ ccd_mode = CCD_MODE_DISABLED;
}
}
-DECLARE_HOOK(HOOK_TICK, usb_sbu_tick, HOOK_PRIO_DEFAULT);
-
static void board_init(void)
{
@@ -507,38 +385,7 @@ static void board_init(void)
init_ioexpander();
init_uservo_port();
- /*
- * TODO(crosbug.com/p/60828): The result of init_ccd() will be
- * overwritten when the usb pd protocol state machine attempts to attach
- * as SNK or SRC since it will modify the pullup/pulldown resistor on
- * the chosen polarity CC line.
- */
- /* Enable CCD if type-c */
- if (gpio_get_level(GPIO_DONGLE_DET))
- init_ccd(CCD_ID_RPUSB);
+ /* Initialize CCD mode and disable sbu mux. */
+ ccd_set_mode(CCD_MODE_DISABLED);
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
-
-static int command_ccd(int argc, char **argv)
-{
- int mode = CCD_ID_NONE;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- /* Handle requested mode */
- if (!strcasecmp(argv[1], "rdrd"))
- mode = CCD_ID_RDRD;
- else if (!strcasecmp(argv[1], "rpusb"))
- mode = CCD_ID_RPUSB;
- else if (!strcasecmp(argv[1], "off"))
- mode = CCD_ID_NONE;
- else
- return EC_ERROR_PARAM1;
-
- init_ccd(mode);
- ccprintf("DUT CC lines set to %s\n", argv[1]);
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(ccd, command_ccd,
- "[rdrd|rpusb|off]", "Set pullups or pulldowns to indicate CCD");
diff --git a/board/servo_v4/board.h b/board/servo_v4/board.h
index 94fc4bf69e..52bd17941f 100644
--- a/board/servo_v4/board.h
+++ b/board/servo_v4/board.h
@@ -78,12 +78,16 @@
#undef CONFIG_TASK_PROFILING
#define CONFIG_USB_POWER_DELIVERY
+#define CONFIG_USB_PD_DTS
#define CONFIG_USB_PD_DUAL_ROLE
#define CONFIG_USB_PD_INTERNAL_COMP
#define CONFIG_USB_PD_PORT_COUNT 2
#define CONFIG_USB_PD_TCPC
#define CONFIG_USB_PD_TCPM_STUB
+/* Override PD_ROLE_DEFAULT in usb_pd.h */
+#define PD_ROLE_DEFAULT(port) ((port) ? PD_ROLE_SOURCE : PD_ROLE_SINK)
+
/* 3.0A Standard-current Rp */
#define PD_SRC_VNC PD_SRC_DEF_VNC_MV
#define PD_SRC_RD_THRESHOLD PD_SRC_DEF_RD_THRESH_MV
diff --git a/board/servo_v4/usb_pd_config.h b/board/servo_v4/usb_pd_config.h
index 80e7bb7388..c9c21726e2 100644
--- a/board/servo_v4/usb_pd_config.h
+++ b/board/servo_v4/usb_pd_config.h
@@ -14,13 +14,6 @@
#ifndef __CROS_EC_USB_PD_CONFIG_H
#define __CROS_EC_USB_PD_CONFIG_H
-/*
- * For DUT PD port uses a fixed cable and both CC lines are connected. Need to
- * choose a default polarity. DUT_CC_POLARITY is this selection.
- */
-#define DUT_CC_POLARITY 0
-
-
/* NOTES: Servo V4 and glados equivalents:
* Glados Servo V4
* C0 CHG
@@ -226,49 +219,54 @@ static inline void pd_tx_init(void)
static inline void pd_set_host_mode(int port, int enable)
{
- if (port == 0) {
- /* CHG port. Rd is wired to 5k pulldown. */
- /* Can't set host mode. */
+ /*
+ * CHG (port == 0) port has fixed Rd attached and therefore can only
+ * present as a SNK device. If port != DUT (port == 1), then nothing to
+ * do in this function.
+ */
+ if (!port)
+ return;
+
+ if (enable) {
+ /*
+ * Servo_v4 in SRC mode acts as a DTS (debug test
+ * accessory) and needs to present Rp on both CC
+ * lines. In order to support orientation detection, the
+ * values of Rp1/Rp2 need to asymmetric with Rp1 > Rp2.
+ */
+
+ /* Set Rd for CC1/CC2 to High-Z. */
+ gpio_set_flags(GPIO_USB_DUT_CC1_RD, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RD, GPIO_INPUT);
+
+ /*
+ * TODO(crosbug.com/p/60794): Currently always advertising
+ * 1.5A. If CHG port is attached then can advertise 3A
+ * instead. Additionally, if CHG port is not attached and having
+ * to use host provided vbus, can 1.5A be advertised?
+ */
+ /* Pull up for host mode */
+ gpio_set_flags(GPIO_USB_DUT_CC1_RP1A5, GPIO_OUTPUT);
+ gpio_set_level(GPIO_USB_DUT_CC1_RP1A5, 1);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RPUSB, GPIO_OUTPUT);
+ gpio_set_level(GPIO_USB_DUT_CC2_RPUSB, 1);
+ /* Set TX Hi-Z */
+ gpio_set_flags(GPIO_USB_DUT_CC1_TX_DATA, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC2_TX_DATA, GPIO_INPUT);
} else {
- if (enable) {
- /*
- * TODO(crosbug.com/p/60792): Similar to what's done for
- * SNK mode, only want to adjust the CC line that
- * matches the chosen polarity for the DUT port. Since
- * DUT port uses a fixed cable and both CC lines are
- * connected will only need to toggle 1 of the CC lines.
- */
- /* High-Z is used for host mode. */
- gpio_set_flags(GPIO_USB_DUT_CC1_RD, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC2_RD, GPIO_INPUT);
- /* Pull up for host mode */
- gpio_set_flags(GPIO_USB_DUT_CC1_RP1A5, GPIO_OUTPUT);
- gpio_set_level(GPIO_USB_DUT_CC1_RP1A5, 1);
- gpio_set_flags(GPIO_USB_DUT_CC2_RP1A5, GPIO_OUTPUT);
- gpio_set_level(GPIO_USB_DUT_CC2_RP1A5, 1);
- /* Set TX Hi-Z */
- gpio_set_flags(GPIO_USB_DUT_CC1_TX_DATA, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC2_TX_DATA, GPIO_INPUT);
- } else {
- /* Set RD to High-Z for device mode. */
- gpio_set_flags(GPIO_USB_DUT_CC1_RP1A5, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC2_RP1A5, GPIO_INPUT);
- /*
- * TODO(crosbug.com/p/60828): Undo what was done in
- * init_ccd.
- */
- gpio_set_flags(GPIO_USB_DUT_CC1_RPUSB, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC2_RPUSB, GPIO_INPUT);
- if (DUT_CC_POLARITY == 0) {
- gpio_set_flags(GPIO_USB_DUT_CC1_RD,
- GPIO_OUTPUT);
- gpio_set_level(GPIO_USB_DUT_CC1_RD, 0);
- } else {
- gpio_set_flags(GPIO_USB_DUT_CC2_RD,
- GPIO_OUTPUT);
- gpio_set_level(GPIO_USB_DUT_CC2_RD, 0);
- }
- }
+ /* Set Rp for CC1/CC2 to High-Z. */
+ gpio_set_flags(GPIO_USB_DUT_CC1_RP3A0, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RP3A0, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC1_RP1A5, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RP1A5, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC1_RPUSB, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RPUSB, GPIO_INPUT);
+
+ /* DTS in SNK mode presents Rd on CC1/CC2 */
+ gpio_set_flags(GPIO_USB_DUT_CC1_RD, GPIO_OUTPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RD, GPIO_OUTPUT);
+ gpio_set_level(GPIO_USB_DUT_CC1_RD, 0);
+ gpio_set_level(GPIO_USB_DUT_CC2_RD, 0);
}
}
@@ -301,21 +299,8 @@ static inline int pd_adc_read(int port, int cc)
if (port == 0)
mv = adc_read_channel(cc ? ADC_CHG_CC2_PD : ADC_CHG_CC1_PD);
- else {
- /*
- * TODO(crosbug.com/p/60792): Only want to read the CC line that
- * matches the chosen polarity for DUT port. If not for the
- * chosen polarity, then return 0. This only works when the DUT
- * port is presenting as a SNK device. Need to fix this so that
- * the returned value for the cc line that doesn't match the
- * chosen polarity returns 0 for SNK and 3300 for SRC mode.
- */
- if (cc == DUT_CC_POLARITY)
- mv = adc_read_channel(cc ? ADC_DUT_CC2_PD :
- ADC_DUT_CC1_PD);
- else
- mv = 0;
- }
+ else
+ mv = adc_read_channel(cc ? ADC_DUT_CC2_PD : ADC_DUT_CC1_PD);
return mv;
}
diff --git a/board/servo_v4/usb_pd_policy.c b/board/servo_v4/usb_pd_policy.c
index e26562794b..48cce3519b 100644
--- a/board/servo_v4/usb_pd_policy.c
+++ b/board/servo_v4/usb_pd_policy.c
@@ -59,21 +59,32 @@ void pd_transition_voltage(int idx)
int pd_set_power_supply_ready(int port)
{
+ /* Port 0 can never provide vbus. */
+ if (!port)
+ return EC_ERROR_INVAL;
+
+ /*
+ * TODO(crosbug.com/p/60794): For now always assume VBUS is supplied by
+ * host. No support yet for using CHG VBUS passthru mode.
+ */
+
/*
- * TODO(crosbug.com/p/60794): Will likely need to set the GPIOs
- * DUT_CHG_EN and HOST_OR_CHG_CTL which control whether DUT port
- * provides VBUS from Host or CHG port.
+ * Select Host as source for VBUS.
+ * To select host, set GPIO_HOST_OR_CHG_CTL low. To select CHG as VBUS
+ * source, then set GPIO_HOST_OR_CHG_CTL high.
*/
+ gpio_set_level(GPIO_HOST_OR_CHG_CTL, 0);
+
+ /* Enable VBUS from the source selected above. */
+ gpio_set_level(GPIO_DUT_CHG_EN, 1);
+
return EC_SUCCESS; /* we are ready */
}
void pd_power_supply_reset(int port)
{
- /*
- * TODO(crosbug.com/p/60794): Will need to set the GPIOs
- * DUT_CHG_EN and HOST_OR_CHG_CTL which control whether DUT port
- * provides VBUS from Host or CHG port.
- */
+ /* Disable VBUS */
+ gpio_set_level(GPIO_DUT_CHG_EN, 0);
}
void pd_set_input_current_limit(int port, uint32_t max_ma,