summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/plankton/board.c87
1 files changed, 75 insertions, 12 deletions
diff --git a/board/plankton/board.c b/board/plankton/board.c
index 2e5f64418a..d52f94bca5 100644
--- a/board/plankton/board.c
+++ b/board/plankton/board.c
@@ -40,6 +40,7 @@ static enum typec_cable cable;
static int active_cc;
static int host_mode;
+static int drp_enable;
static int sn75dp130_dpcd_init(void);
@@ -127,6 +128,7 @@ enum usbc_action {
USBC_ACT_CABLE_POLARITY0,
USBC_ACT_CABLE_POLARITY1,
USBC_ACT_CCD_EN,
+ USBC_ACT_DRP_TOGGLE,
/* Number of USBC actions */
USBC_ACT_COUNT
@@ -147,18 +149,27 @@ static void set_active_cc(int cc)
{
active_cc = cc;
+ /*
+ * If DRP mode is enabled, then set both CC lines based
+ * on the current value of host_mode. If DRP mode is
+ * disabled then only set the active CC line.
+ */
/* Pull-up on CC2 */
gpio_set_flags(GPIO_USBC_CC2_HOST,
- (cc && host_mode) ? GPIO_OUT_HIGH : GPIO_INPUT);
+ ((cc || drp_enable) && host_mode) ?
+ GPIO_OUT_HIGH : GPIO_INPUT);
/* Pull-down on CC2 */
gpio_set_flags(GPIO_USBC_CC2_DEVICE_ODL,
- (cc && !host_mode) ? GPIO_OUT_LOW : GPIO_INPUT);
+ ((cc || drp_enable) && !host_mode) ?
+ GPIO_OUT_LOW : GPIO_INPUT);
/* Pull-up on CC1 */
gpio_set_flags(GPIO_USBC_CC1_HOST,
- (!cc && host_mode) ? GPIO_OUT_HIGH : GPIO_INPUT);
+ ((!cc || drp_enable) && host_mode) ?
+ GPIO_OUT_HIGH : GPIO_INPUT);
/* Pull-down on CC1 */
gpio_set_flags(GPIO_USBC_CC1_DEVICE_ODL,
- (!cc && !host_mode) ? GPIO_OUT_LOW : GPIO_INPUT);
+ ((!cc || drp_enable) && !host_mode) ?
+ GPIO_OUT_LOW : GPIO_INPUT);
}
/**
@@ -235,6 +246,39 @@ static void fake_disconnect_start(void)
}
DECLARE_DEFERRED(fake_disconnect_start);
+/**
+ * Enable or disable dualrole mode operation. By default Plankton has
+ * dualrole mode disabled and attempts to connect in a sink role. Console
+ * commands/button presses can cause it to switch to source_only/sink_only
+ * modes.
+ */
+static void update_usbc_dual_role(int dual_role)
+{
+ if (dual_role == PD_DRP_TOGGLE_ON) {
+ drp_enable = 1;
+ /*
+ * Cable detect is not needed when operating in dualrole mode
+ * since both CC lines are used and SRC/SNK changes are dictated
+ * by the USB PD protocol state machine.
+ */
+ hook_call_deferred(detect_cc_cable, -1);
+ /* Need to make sure both CC lines are set for SNK or SRC. */
+ set_active_cc(host_mode);
+ /* Ensure that PD communication is enabled. */
+ pd_comm_enable(1);
+ } else {
+ drp_enable = 0;
+ /*
+ * Dualrole mode is not active, resume cable detect function
+ * which controls which CC line is active.
+ */
+ hook_call_deferred(detect_cc_cable, 0);
+ }
+ /* Update dual role setting used in USB PD protocol state machine */
+ pd_set_dual_role(dual_role);
+ cprintf(CC_USBPD, "DRP = %d, host_mode = %d\n", drp_enable, host_mode);
+}
+
static void set_usbc_action(enum usbc_action act)
{
int need_soft_reset;
@@ -246,12 +290,12 @@ static void set_usbc_action(enum usbc_action act)
case USBC_ACT_20V_TO_DUT:
need_soft_reset = gpio_get_level(GPIO_VBUS_CHARGER_EN);
board_set_source_cap(src_cap_mapping[act]);
- pd_set_dual_role(PD_DRP_FORCE_SOURCE);
+ update_usbc_dual_role(PD_DRP_FORCE_SOURCE);
if (need_soft_reset)
pd_soft_reset();
break;
case USBC_ACT_DEVICE:
- pd_set_dual_role(PD_DRP_FORCE_SINK);
+ update_usbc_dual_role(PD_DRP_FORCE_SINK);
break;
case USBC_ACT_USBDP_TOGGLE:
was_usb_mode = gpio_get_level(GPIO_USBC_SS_USB_MODE);
@@ -314,6 +358,11 @@ static void set_usbc_action(enum usbc_action act)
gpio_set_level(GPIO_CASE_CLOSE_EN, 1);
gpio_set_level(GPIO_CASE_CLOSE_DFU_L, 1);
break;
+ case USBC_ACT_DRP_TOGGLE:
+ /* Toggle dualrole mode setting. */
+ update_usbc_dual_role(drp_enable ?
+ PD_DRP_TOGGLE_OFF : PD_DRP_TOGGLE_ON);
+ break;
default:
break;
}
@@ -520,6 +569,8 @@ static int cmd_usbc_action(int argc, char *argv[])
act = USBC_ACT_CABLE_POLARITY0;
else if (!strcasecmp(argv[1], "pol1"))
act = USBC_ACT_CABLE_POLARITY1;
+ else if (!strcasecmp(argv[1], "drp"))
+ act = USBC_ACT_DRP_TOGGLE;
else
return EC_ERROR_PARAM1;
@@ -528,7 +579,7 @@ static int cmd_usbc_action(int argc, char *argv[])
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(usbc_action, cmd_usbc_action,
- "<5v|12v|20v|ccd|dev|usb|dp|flip|pol0|pol1>",
+ "<5v|12v|20v|ccd|dev|usb|dp|flip|pol0|pol1|drp>",
"Set Plankton type-C port state",
NULL);
@@ -590,12 +641,20 @@ int board_fake_pd_adc_read(int cc)
/* Always disconnected */
return fake_pd_host_mode ? 3000 : 0;
} else {
- /* Only read the active CC line, fake disconnected on other */
- if (active_cc == cc)
+ if (drp_enable) {
+ /* Always read the req CC line when in drp mode */
return adc_read_channel(cc ? ADC_CH_CC2_PD :
ADC_CH_CC1_PD);
- else
- return host_mode ? 3000 : 0;
+ } else {
+ /*
+ * Only read the active CC line, fake disconnected
+ * on other CC line. */
+ if (active_cc == cc)
+ return adc_read_channel(cc ? ADC_CH_CC2_PD :
+ ADC_CH_CC1_PD);
+ else
+ return host_mode ? 3000 : 0;
+ }
}
}
@@ -607,7 +666,8 @@ static void board_update_fake_adc_value(int host_mode)
void board_pd_set_host_mode(int enable)
{
- cprintf(CC_USBPD, "Host mode: %d\n", enable);
+ if (!drp_enable)
+ cprintf(CC_USBPD, "Host mode: %d\n", enable);
if (board_pd_fake_disconnected()) {
board_update_fake_adc_value(enable);
@@ -647,6 +707,9 @@ static void board_init(void)
hpd_prev_ts = now.val;
gpio_enable_interrupt(GPIO_DPSRC_HPD);
+ /* Start up with dualrole mode off */
+ drp_enable = 0;
+
/* Enable interrupts on VBUS transitions. */
gpio_enable_interrupt(GPIO_VBUS_WAKE);