summaryrefslogtreecommitdiff
path: root/board/servo_v4p1/ccd_measure_sbu.c
diff options
context:
space:
mode:
authorSam Hurst <shurst@google.com>2020-05-26 10:01:04 -0700
committerCommit Bot <commit-bot@chromium.org>2020-06-22 22:44:42 +0000
commit7745df7b323104633933d9b56faa906e099017d4 (patch)
tree115cbac062f989e6ada41fdbbc62373679a528b7 /board/servo_v4p1/ccd_measure_sbu.c
parent9009125752041c05fdb288935aa1f3906ce2997e (diff)
downloadchrome-ec-7745df7b323104633933d9b56faa906e099017d4.tar.gz
servo_v4p1: Add CCD measurement functionality
The CCD measurement functionality is only available in RO. BRANCH=none BUG=b:146793000 TEST=make -j buildall Signed-off-by: Sam Hurst <shurst@google.com> Change-Id: I4bf9885a8a76c8d9dbb688a72673726fb0a7efa5 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2216402 Reviewed-by: Wai-Hong Tam <waihong@google.com>
Diffstat (limited to 'board/servo_v4p1/ccd_measure_sbu.c')
-rw-r--r--board/servo_v4p1/ccd_measure_sbu.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/board/servo_v4p1/ccd_measure_sbu.c b/board/servo_v4p1/ccd_measure_sbu.c
new file mode 100644
index 0000000000..b9c9680cc9
--- /dev/null
+++ b/board/servo_v4p1/ccd_measure_sbu.c
@@ -0,0 +1,131 @@
+/* Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+/* CCD Measure SBU */
+
+#include "adc.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "ioexpanders.h"
+#include "timer.h"
+
+#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
+#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
+
+/*
+ * 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);
+
+ /*
+ * 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 {
+ /* Didn't find anything, reset state. */
+ last = MODE_SBU_OTHER;
+ count = 0;
+ }
+
+ /*
+ * 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 */
+ sbu_flip_sel(polarity);
+ gpio_set_level(GPIO_SBU_MUX_EN, 1);
+ msleep(10);
+ CPRINTS("CCD: connected %s",
+ polarity ? "flip" : "noflip");
+ }
+ }
+
+ /* Measure every 100ms, forever. */
+ hook_call_deferred(&ccd_measure_sbu_data, 100 * MSEC);
+}
+
+void ccd_enable(int enable)
+{
+ if (enable) {
+ hook_call_deferred(&ccd_measure_sbu_data, 0);
+ } else {
+ gpio_set_level(GPIO_SBU_MUX_EN, 0);
+ hook_call_deferred(&ccd_measure_sbu_data, -1);
+ }
+}
+
+void start_ccd_meas_sbu_cycle(void)
+{
+ hook_call_deferred(&ccd_measure_sbu_data, 1000 * MSEC);
+}