diff options
author | Scott <scollyer@chromium.org> | 2017-01-13 17:48:31 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2017-05-17 17:04:27 +0000 |
commit | 135c9cd1bcfc0cf44b9ccf333b3861a193712edb (patch) | |
tree | 53c681f85121d52fe06429c9becc8aff65ff2bd6 | |
parent | cdb7741359c96a73044ba754abda68e25f50555a (diff) | |
download | chrome-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.c | 253 | ||||
-rw-r--r-- | board/servo_v4/board.h | 4 | ||||
-rw-r--r-- | board/servo_v4/usb_pd_config.h | 113 | ||||
-rw-r--r-- | board/servo_v4/usb_pd_policy.c | 27 |
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, |