summaryrefslogtreecommitdiff
path: root/board/servo_v4/board.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/servo_v4/board.c')
-rw-r--r--board/servo_v4/board.c197
1 files changed, 93 insertions, 104 deletions
diff --git a/board/servo_v4/board.c b/board/servo_v4/board.c
index 15a5fcdd42..e39654a3d5 100644
--- a/board/servo_v4/board.c
+++ b/board/servo_v4/board.c
@@ -268,128 +268,114 @@ static void init_ioexpander(void)
i2c_write8(1, GPIOX_I2C_ADDR, GPIOX_DIR_PORT_B, 0x18);
}
-/* Define voltage thresholds for SBU USB detection */
-#define GND_MAX_MV 350
-#define USB_HIGH_MV 1500
+/*
+ * Define voltage thresholds for SBU USB detection.
+ *
+ * Max observed USB low across sampled systems: 666mV
+ * Min observed USB high across sampled systems: 3026mV
+ */
+#define GND_MAX_MV 700
+#define USB_HIGH_MV 2500
+#define SBU_DIRECT 0
+#define SBU_FLIP 1
+
+#define MODE_SBU_DISCONNECT 0
+#define MODE_SBU_CONNECT 1
+#define MODE_SBU_FLIP 2
+#define MODE_SBU_OTHER 3
static void ccd_measure_sbu(void);
DECLARE_DEFERRED(ccd_measure_sbu);
-
static void ccd_measure_sbu(void)
{
int sbu1;
int sbu2;
+ int mux_en;
+ static int count /* = 0 */;
+ static int last /* = 0 */;
+ static int polarity /* = 0 */;
/* Read sbu voltage levels */
sbu1 = adc_read_channel(ADC_SBU1_DET);
sbu2 = adc_read_channel(ADC_SBU2_DET);
+ mux_en = gpio_get_level(GPIO_SBU_MUX_EN);
- /* 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);
- CPRINTS("CCD: connected flip");
- } else if ((sbu2 > USB_HIGH_MV) &&
- (sbu1 < GND_MAX_MV)) {
- /* SBU flip = 0 */
- write_ioexpander(0, 2, 0);
- msleep(10);
- CPRINTS("CCD: connected noflip");
+ /*
+ * While SBU_MUX is disabled (SuzyQ unplugged), we'll poll the SBU lines
+ * to check if an idling, unconfigured USB device is present.
+ * USB FS pulls one line high for connect request.
+ * If so, and it persists for 500ms, we'll enable the SuzyQ in that
+ * orientation.
+ */
+ if ((!mux_en) && (sbu1 > USB_HIGH_MV) && (sbu2 < GND_MAX_MV)) {
+ /* Check flip connection polarity. */
+ if (last != MODE_SBU_FLIP) {
+ last = MODE_SBU_FLIP;
+ polarity = SBU_FLIP;
+ count = 0;
+ } else {
+ count++;
+ }
+ } else if ((!mux_en) && (sbu2 > USB_HIGH_MV) && (sbu1 < GND_MAX_MV)) {
+ /* Check direct connection polarity. */
+ if (last != MODE_SBU_CONNECT) {
+ last = MODE_SBU_CONNECT;
+ polarity = SBU_DIRECT;
+ count = 0;
+ } else {
+ count++;
+ }
+ /*
+ * If SuzyQ is enabled, we'll poll for a persistent no-signal for
+ * 500ms. Since USB is differential, we should never see GND/GND
+ * while the device is connected.
+ * If disconnected, electrically remove SuzyQ.
+ */
+ } else if ((mux_en) && (sbu1 < GND_MAX_MV) && (sbu2 < GND_MAX_MV)) {
+ /* Check for SBU disconnect if connected. */
+ if (last != MODE_SBU_DISCONNECT) {
+ last = MODE_SBU_DISCONNECT;
+ count = 0;
+ } else {
+ count++;
+ }
} else {
- /* Measure again after 100 msec */
- hook_call_deferred(&ccd_measure_sbu_data, 100 * MSEC);
+ /* Didn't find anything, reset state. */
+ last = MODE_SBU_OTHER;
+ count = 0;
}
-}
-
-static uint8_t ccd_keepalive_enabled;
-static int command_keepalive(int argc, char **argv)
-{
- int val;
- if (argc > 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (argc == 2) {
- if (!parse_bool(argv[1], &val))
- return EC_ERROR_PARAM1;
-
- ccd_keepalive_enabled = val;
+ /*
+ * We have seen a new state continuously for 500ms.
+ * Let's update the mux to enable/disable SuzyQ appropriately.
+ */
+ if (count > 5) {
+ if (mux_en) {
+ /* Disable mux as it's disconnected now. */
+ gpio_set_level(GPIO_SBU_MUX_EN, 0);
+ msleep(10);
+ CPRINTS("CCD: disconnected.");
+ } else {
+ /* SBU flip = polarity */
+ write_ioexpander(0, 2, polarity);
+ gpio_set_level(GPIO_SBU_MUX_EN, 1);
+ msleep(10);
+ CPRINTS("CCD: connected %s",
+ polarity ? "noflip" : "flip");
+ }
}
- ccprintf("ccd_keepalive: %sabled\n",
- ccd_keepalive_enabled ? "en" : "dis");
- return EC_SUCCESS;
+ /* Measure every 100ms, forever. */
+ hook_call_deferred(&ccd_measure_sbu_data, 100 * MSEC);
}
-DECLARE_CONSOLE_COMMAND(keepalive, command_keepalive, "[enable | disable]",
- "Enable CCD keepalive. Prevents SBU sampling.");
-
-static void check_for_disconnect(void);
-DECLARE_DEFERRED(check_for_disconnect);
-static void check_for_disconnect(void)
-{
- static uint8_t entries;
- int dut_is_connected = pd_is_connected(1);
-
- entries++;
-
- if (dut_is_connected) {
- entries = 0;
- return;
- } else if ((entries < 3) && !dut_is_connected) {
- /* Hmm, it's still not connected? Let's keep checking. */
- hook_call_deferred(&check_for_disconnect_data, 100 * MSEC);
- return;
- }
- /*
- * Hmm, okay. Maybe the DUT is actually disconnected. Clear
- * the CCD keepalive such that the auto flip orientation
- * detection will work upon a plug in.
- */
- CPRINTS("DUT seems disconnected. Clearing CCD keepalive.");
- entries = 0;
- ccd_keepalive_enabled = 0;
-}
void ccd_enable(int enable)
{
- if (enable) {
- /*
- * Unfortunately the polarity detect is designed for real plug
- * events, and only accurately detects pre-connect idle. If
- * there's active traffic on the line (like while EC is
- * rebooting) this could pretty much go either way. Therefore,
- * if CCD keepalive is enabled, let's not measure the SBU lines
- * and leave the mux alone. Most likely nothing has changed.
- *
- * NOTE: Once CCD keepalive has been enabled, it will remained
- * enabled until the DUT is seen disconnected for at least
- * 900ms.
- */
- if (!ccd_keepalive_enabled)
- /* Allow some time following turning on of VBUS */
- hook_call_deferred(&ccd_measure_sbu_data,
- PD_POWER_SUPPLY_TURN_ON_DELAY);
- } else {
- /* We are not connected to anything */
-
- /* Disable ccd_measure_sbu deferred call always */
- hook_call_deferred(&ccd_measure_sbu_data, -1);
-
- /*
- * In a bit, start checking to see if we're still
- * disconnected.
- */
- hook_call_deferred(&check_for_disconnect_data, 600 * MSEC);
-
- /*
- * The DUT port has detected a detach event. Don't want to
- * disconnect the SBU mux here so that the H1 USB console can
- * remain connected.
- */
- CPRINTS("CCD: TypeC detach, no change to SBU mux");
- }
+ /*
+ * We may use this if displayport is ever enabled.
+ * For now, CCD is always enabled on SBU.
+ */
}
int board_get_version(void)
@@ -441,16 +427,19 @@ static void board_init(void)
system_set_bbram(SYSTEM_BBRAM_IDX_PD1, 0);
/*
- * Enable SBU mux. The polarity is set each time a new PD attach event
- * occurs. But, the SBU mux is not disabled on detach so that the H1 USB
- * console will survie a DUT EC reset.
+ * Disable SBU mux. The polarity is set each time a presense is detected
+ * on SBU, and wired thorugh. On missing voltage on SBU. SBU wires are
+ * disconnected.
*/
- gpio_set_level(GPIO_SBU_MUX_EN, 1);
+ gpio_set_level(GPIO_SBU_MUX_EN, 0);
/*
* Voltage transition needs to occur in lockstep between the CHG and
* DUT ports, so initially limit voltage to 5V.
*/
pd_set_max_voltage(PD_MIN_MV);
+
+ hook_call_deferred(&ccd_measure_sbu_data, 1000 * MSEC);
+
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);