diff options
author | Sam Hurst <shurst@google.com> | 2020-05-26 10:01:04 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-06-22 22:44:42 +0000 |
commit | 7745df7b323104633933d9b56faa906e099017d4 (patch) | |
tree | 115cbac062f989e6ada41fdbbc62373679a528b7 /board/servo_v4p1/ccd_measure_sbu.c | |
parent | 9009125752041c05fdb288935aa1f3906ce2997e (diff) | |
download | chrome-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.c | 131 |
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); +} |