summaryrefslogtreecommitdiff
path: root/test/vpd_api.c
diff options
context:
space:
mode:
authorSam Hurst <shurst@google.com>2018-09-13 09:27:08 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-04-08 22:30:19 -0700
commit0fe6147a9d8d9feef5049aa6c6c4a6ad30d12b26 (patch)
tree05d4509bcfe68a248ec3fa58168f3de2536c2d9c /test/vpd_api.c
parente097feb8b2db20cd2435a483517356defa222db1 (diff)
downloadchrome-ec-0fe6147a9d8d9feef5049aa6c6c4a6ad30d12b26.tar.gz
chocodile_vpdmcu: Firmware for chocodile mcu
Implement Chocodile Charge-Through Vconn Powered firmware for mcu using new Type-C/PD State machine stack. BUG=b:115626873 BRANCH=none TEST=manual Charge-Through was tested on an Atlas running a DRP USB-C/PD state machine with CTUnattached.SNK and CTAttached.SNK states. Signed-off-by: Sam Hurst <shurst@chromium.org> Change-Id: I847f1bcd2fc3ce41e66edd133a10c943d5e8c819 Reviewed-on: https://chromium-review.googlesource.com/1225250 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Tested-by: Sam Hurst <shurst@google.com> Reviewed-by: Stefan Reinauer <reinauer@google.com>
Diffstat (limited to 'test/vpd_api.c')
-rw-r--r--test/vpd_api.c586
1 files changed, 586 insertions, 0 deletions
diff --git a/test/vpd_api.c b/test/vpd_api.c
new file mode 100644
index 0000000000..960c0c664b
--- /dev/null
+++ b/test/vpd_api.c
@@ -0,0 +1,586 @@
+/* Copyright 2019 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.
+ */
+
+#include "registers.h"
+#include "vpd_api.h"
+#include "driver/tcpm/tcpm.h"
+#include "console.h"
+/*
+ * Polarity based on 'DFP Perspective' (see table USB Type-C Cable and Connector
+ * Specification)
+ *
+ * CC1 CC2 STATE POSITION
+ * ----------------------------------------
+ * open open NC N/A
+ * Rd open UFP attached 1
+ * open Rd UFP attached 2
+ * open Ra pwr cable no UFP N/A
+ * Ra open pwr cable no UFP N/A
+ * Rd Ra pwr cable & UFP 1
+ * Ra Rd pwr cable & UFP 2
+ * Rd Rd dbg accessory N/A
+ * Ra Ra audio accessory N/A
+ *
+ * Note, V(Rd) > V(Ra)
+ */
+#ifndef PD_SRC_RD_THRESHOLD
+#define PD_SRC_RD_THRESHOLD PD_SRC_DEF_RD_THRESH_MV
+#endif
+#ifndef PD_SRC_VNC
+#define PD_SRC_VNC PD_SRC_DEF_VNC_MV
+#endif
+
+#ifndef CC_RA
+#define CC_RA(port, cc, sel) (cc < pd_src_rd_threshold[ct_cc_rp_value])
+#endif
+#define CC_RD(cc) ((cc >= PD_SRC_RD_THRESHOLD) && (cc < PD_SRC_VNC))
+#ifndef CC_NC
+#define CC_NC(port, cc, sel) (cc >= PD_SRC_VNC)
+#endif
+
+/*
+ * Polarity based on 'UFP Perspective'.
+ *
+ * CC1 CC2 STATE POSITION
+ * ----------------------------------------
+ * open open NC N/A
+ * Rp open DFP attached 1
+ * open Rp DFP attached 2
+ * Rp Rp Accessory attached N/A
+ */
+#ifndef PD_SNK_VA
+#define PD_SNK_VA PD_SNK_VA_MV
+#endif
+
+#define CC_RP(cc) (cc >= PD_SNK_VA)
+
+/* Mock Board State */
+static enum vpd_pwr mock_vconn_pwr_sel_odl;
+static enum vpd_gpo mock_cc1_cc2_rd_l;
+static enum vpd_gpo mock_cc_db_en_od;
+static enum vpd_gpo mock_cc_rpusb_odh;
+static enum vpd_cc mock_ct_cl_sel;
+static int mock_mcu_cc_en;
+static enum vpd_billboard mock_present_billboard;
+static int mock_red_led;
+static int mock_green_led;
+static int mock_vbus_pass_en;
+
+static int mock_read_host_vbus;
+static int mock_read_ct_vbus;
+static int mock_read_vconn;
+
+static struct mock_pin mock_cc2_rpusb_odh;
+static struct mock_pin mock_cc2_rp3a0_rd_l;
+static struct mock_pin mock_cc1_rpusb_odh;
+static struct mock_pin mock_cc1_rp3a0_rd_l;
+static struct mock_pin mock_cc_vpdmcu;
+static struct mock_pin mock_cc_rp3a0_rd_l;
+
+/* Charge-Through pull up/down enabled */
+static int ct_cc_pull;
+/* Charge-Through pull up value */
+static int ct_cc_rp_value;
+
+/* Charge-Through pull up/down enabled */
+static int host_cc_pull;
+/* Charge-Through pull up value */
+static int host_cc_rp_value;
+
+/* Voltage thresholds for Ra attach in normal SRC mode */
+static int pd_src_rd_threshold[TYPEC_RP_RESERVED] = {
+ PD_SRC_DEF_RD_THRESH_MV,
+ PD_SRC_1_5_RD_THRESH_MV,
+ PD_SRC_3_0_RD_THRESH_MV,
+};
+
+enum vpd_pwr mock_get_vconn_pwr_source(void)
+{
+ return mock_vconn_pwr_sel_odl;
+}
+
+int mock_get_ct_cc1_rpusb(void)
+{
+ return mock_cc1_rpusb_odh.value;
+}
+
+int mock_get_ct_cc2_rpusb(void)
+{
+ return mock_cc2_rpusb_odh.value;
+}
+
+enum vpd_gpo mock_get_ct_rd(void)
+{
+ return mock_cc1_cc2_rd_l;
+}
+
+enum vpd_gpo mock_get_cc_rpusb_odh(void)
+{
+ return mock_cc_rpusb_odh;
+}
+
+enum vpd_gpo mock_get_cc_db_en_od(void)
+{
+ return mock_cc_db_en_od;
+}
+
+enum vpd_cc moch_get_ct_cl_sel(void)
+{
+ return mock_ct_cl_sel;
+}
+
+int mock_get_mcu_cc_en(void)
+{
+ return mock_mcu_cc_en;
+}
+
+enum vpd_billboard mock_get_present_billboard(void)
+{
+ return mock_present_billboard;
+}
+
+int mock_get_red_led(void)
+{
+ return mock_red_led;
+}
+
+int mock_get_green_led(void)
+{
+ return mock_green_led;
+}
+
+int mock_get_vbus_pass_en(void)
+{
+ return mock_vbus_pass_en;
+}
+
+void mock_set_host_cc_sink_voltage(int v)
+{
+ mock_cc_vpdmcu.value = v;
+}
+
+void mock_set_host_cc_source_voltage(int v)
+{
+ mock_cc_vpdmcu.value2 = v;
+}
+
+void mock_set_host_vbus(int v)
+{
+ mock_read_host_vbus = v;
+}
+
+void mock_set_ct_vbus(int v)
+{
+ mock_read_ct_vbus = v;
+}
+
+void mock_set_vconn(int v)
+{
+ mock_read_vconn = v;
+}
+
+int mock_get_cfg_cc2_rpusb_odh(void)
+{
+ return mock_cc2_rpusb_odh.cfg;
+}
+
+int mock_set_cc2_rpusb_odh(int v)
+{
+ if (mock_cc2_rpusb_odh.cfg == PIN_ADC) {
+ mock_cc2_rpusb_odh.value = v;
+ return 1;
+ }
+ return 0;
+}
+
+int mock_get_cfg_cc2_rp3a0_rd_l(void)
+{
+ return mock_cc2_rp3a0_rd_l.cfg;
+}
+
+int mock_set_cc2_rp3a0_rd_l(int v)
+{
+ if (mock_cc2_rp3a0_rd_l.cfg == PIN_ADC) {
+ mock_cc2_rp3a0_rd_l.value = v;
+ return 1;
+ }
+
+ return 0;
+}
+
+int mock_get_cc1_rpusb_odh(void)
+{
+ return mock_cc1_rpusb_odh.cfg;
+}
+
+int mock_set_cc1_rpusb_odh(int v)
+{
+ if (mock_cc1_rpusb_odh.cfg == PIN_ADC) {
+ mock_cc1_rpusb_odh.value = v;
+ return 1;
+ }
+
+ return 0;
+}
+
+int mock_get_cfg_cc_vpdmcu(void)
+{
+ return mock_cc_vpdmcu.cfg;
+}
+
+enum vpd_pin mock_get_cfg_cc_rp3a0_rd_l(void)
+{
+ return mock_cc_rp3a0_rd_l.cfg;
+}
+
+int mock_get_cc_rp3a0_rd_l(void)
+{
+ return mock_cc_rp3a0_rd_l.value;
+}
+
+int mock_get_cfg_cc1_rp3a0_rd_l(void)
+{
+ return mock_cc1_rp3a0_rd_l.cfg;
+}
+
+int mock_set_cc1_rp3a0_rd_l(int v)
+{
+ if (mock_cc1_rp3a0_rd_l.cfg == PIN_ADC) {
+ mock_cc1_rp3a0_rd_l.value = v;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Convert CC voltage to CC status */
+static int vpd_cc_voltage_to_status(int cc_volt, int cc_pull)
+{
+ /* If we have a pull-up, then we are source, check for Rd. */
+ if (cc_pull == TYPEC_CC_RP) {
+ if (CC_NC(0, cc_volt, 0))
+ return TYPEC_CC_VOLT_OPEN;
+ else if (CC_RA(0, cc_volt, 0))
+ return TYPEC_CC_VOLT_RA;
+ else
+ return TYPEC_CC_VOLT_RD;
+ /* If we have a pull-down, then we are sink, check for Rp. */
+ } else if (cc_pull == TYPEC_CC_RD || cc_pull == TYPEC_CC_RA_RD) {
+ if (cc_volt >= TYPE_C_SRC_3000_THRESHOLD)
+ return TYPEC_CC_VOLT_RP_3_0;
+ else if (cc_volt >= TYPE_C_SRC_1500_THRESHOLD)
+ return TYPEC_CC_VOLT_RP_1_5;
+ else if (CC_RP(cc_volt))
+ return TYPEC_CC_VOLT_RP_DEF;
+ else
+ return TYPEC_CC_VOLT_OPEN;
+ } else {
+ /* If we are open, then always return 0 */
+ return 0;
+ }
+}
+
+void vpd_ct_set_pull(int pull, int rp_value)
+{
+ ct_cc_pull = pull;
+
+ switch (pull) {
+ case TYPEC_CC_RP:
+ ct_cc_rp_value = rp_value;
+ vpd_cc1_cc2_db_en_l(GPO_HIGH);
+ switch (rp_value) {
+ case TYPEC_RP_USB:
+ vpd_config_cc1_rp3a0_rd_l(PIN_ADC, 0);
+ vpd_config_cc2_rp3a0_rd_l(PIN_ADC, 0);
+ vpd_config_cc1_rpusb_odh(PIN_GPO, 1);
+ vpd_config_cc2_rpusb_odh(PIN_GPO, 1);
+ break;
+ case TYPEC_RP_3A0:
+ vpd_config_cc1_rpusb_odh(PIN_ADC, 0);
+ vpd_config_cc2_rpusb_odh(PIN_ADC, 0);
+ vpd_config_cc1_rp3a0_rd_l(PIN_GPO, 1);
+ vpd_config_cc2_rp3a0_rd_l(PIN_GPO, 1);
+ break;
+ }
+ break;
+ case TYPEC_CC_RD:
+ vpd_config_cc1_rpusb_odh(PIN_ADC, 0);
+ vpd_config_cc2_rpusb_odh(PIN_ADC, 0);
+ vpd_config_cc1_rp3a0_rd_l(PIN_ADC, 0);
+ vpd_config_cc2_rp3a0_rd_l(PIN_ADC, 0);
+ vpd_cc1_cc2_db_en_l(GPO_LOW);
+ break;
+ case TYPEC_CC_OPEN:
+ vpd_cc1_cc2_db_en_l(GPO_HIGH);
+ vpd_config_cc1_rpusb_odh(PIN_ADC, 0);
+ vpd_config_cc2_rpusb_odh(PIN_ADC, 0);
+ vpd_config_cc1_rp3a0_rd_l(PIN_ADC, 0);
+ vpd_config_cc2_rp3a0_rd_l(PIN_ADC, 0);
+ break;
+ }
+}
+
+void vpd_ct_get_cc(int *cc1, int *cc2)
+{
+ int cc1_v;
+ int cc2_v;
+
+ switch (ct_cc_pull) {
+ case TYPEC_CC_RP:
+ switch (ct_cc_rp_value) {
+ case TYPEC_RP_USB:
+ cc1_v = mock_cc1_rp3a0_rd_l.value;
+ cc2_v = mock_cc2_rp3a0_rd_l.value;
+ break;
+ case TYPEC_RP_3A0:
+ cc1_v = mock_cc1_rpusb_odh.value;
+ cc2_v = mock_cc2_rpusb_odh.value;
+ break;
+ }
+
+ if (!cc1_v && !cc2_v) {
+ cc1_v = PD_SRC_VNC;
+ cc2_v = PD_SRC_VNC;
+ }
+ break;
+ case TYPEC_CC_RD:
+ cc1_v = mock_cc1_rpusb_odh.value;
+ cc2_v = mock_cc2_rpusb_odh.value;
+ break;
+ case TYPEC_CC_OPEN:
+ *cc1 = 0;
+ *cc2 = 0;
+ return;
+ }
+
+ *cc1 = vpd_cc_voltage_to_status(cc1_v, ct_cc_pull);
+ *cc2 = vpd_cc_voltage_to_status(cc2_v, ct_cc_pull);
+}
+
+void vpd_host_set_pull(int pull, int rp_value)
+{
+ host_cc_pull = pull;
+
+ switch (pull) {
+ case TYPEC_CC_RP:
+ vpd_cc_db_en_od(GPO_LOW);
+ host_cc_rp_value = rp_value;
+ switch (rp_value) {
+ case TYPEC_RP_USB:
+ vpd_config_cc_rp3a0_rd_l(PIN_CMP, 0);
+ vpd_cc_rpusb_odh(GPO_HIGH);
+ break;
+ case TYPEC_RP_3A0:
+ vpd_cc_rpusb_odh(GPO_HZ);
+ vpd_config_cc_rp3a0_rd_l(PIN_GPO, 1);
+ break;
+ }
+ break;
+ case TYPEC_CC_RD:
+ vpd_cc_rpusb_odh(GPO_HZ);
+ vpd_cc_db_en_od(GPO_LOW);
+
+ vpd_config_cc_rp3a0_rd_l(PIN_GPO, 0);
+ break;
+ case TYPEC_CC_RA_RD:
+ vpd_cc_rpusb_odh(GPO_HZ);
+ vpd_config_cc_rp3a0_rd_l(PIN_GPO, 0);
+
+ /*
+ * RA is connected to VCONN
+ * RD is connected to CC
+ */
+ vpd_cc_db_en_od(GPO_HZ);
+ break;
+ case TYPEC_CC_OPEN:
+ vpd_cc_rpusb_odh(GPO_HZ);
+ vpd_config_cc_rp3a0_rd_l(PIN_CMP, 0);
+ vpd_cc_db_en_od(GPO_LOW);
+
+ /*
+ * Do nothing. CC is open on entry to this function
+ */
+ break;
+ }
+}
+
+void vpd_host_get_cc(int *cc)
+{
+ int v;
+
+ if (host_cc_pull == TYPEC_CC_OPEN) {
+ *cc = 0;
+ return;
+ } else if (host_cc_pull == TYPEC_CC_RP) {
+ v = mock_cc_vpdmcu.value;
+ } else {
+ v = mock_cc_vpdmcu.value2;
+ }
+
+ *cc = vpd_cc_voltage_to_status(v, host_cc_pull);
+}
+
+void vpd_rx_enable(int en)
+{
+ if (en) {
+ mock_ct_cl_sel = 0;
+ mock_mcu_cc_en = 1;
+ }
+
+ tcpm_set_polarity(0, 0);
+ tcpm_set_rx_enable(0, en);
+}
+
+/*
+ * PA1: Configure as ADC, CMP, or GPO
+ */
+void vpd_config_cc_vpdmcu(enum vpd_pin cfg, int en)
+{
+ mock_cc_vpdmcu.cfg = cfg;
+
+ if (cfg == PIN_GPO)
+ mock_cc_vpdmcu.value = en ? 1 : 0;
+}
+
+/*
+ * PA2: Configure as COMP2_INM6 or GPO
+ */
+void vpd_config_cc_rp3a0_rd_l(enum vpd_pin cfg, int en)
+{
+ mock_cc_rp3a0_rd_l.cfg = cfg;
+
+ if (cfg == PIN_GPO)
+ mock_cc_rp3a0_rd_l.value = en ? 1 : 0;
+}
+
+/*
+ * PA4: Configure as ADC, CMP, or GPO
+ */
+void vpd_config_cc1_rp3a0_rd_l(enum vpd_pin cfg, int en)
+{
+ mock_cc1_rp3a0_rd_l.cfg = cfg;
+
+ if (cfg == PIN_GPO)
+ mock_cc1_rp3a0_rd_l.value = en ? 1 : 0;
+}
+
+/*
+ * PA5: Configure as ADC, COMP, or GPO
+ */
+void vpd_config_cc2_rp3a0_rd_l(enum vpd_pin cfg, int en)
+{
+ mock_cc2_rp3a0_rd_l.cfg = cfg;
+
+ if (cfg == PIN_GPO)
+ mock_cc2_rp3a0_rd_l.value = en ? 1 : 0;
+}
+
+/*
+ * PB0: Configure as ADC or GPO
+ */
+void vpd_config_cc1_rpusb_odh(enum vpd_pin cfg, int en)
+{
+ mock_cc1_rpusb_odh.cfg = cfg;
+
+ if (cfg == PIN_GPO)
+ mock_cc1_rpusb_odh.value = en ? 1 : 0;
+}
+
+/*
+ * PB1: Configure as ADC or GPO
+ */
+void vpd_config_cc2_rpusb_odh(enum vpd_pin cfg, int en)
+{
+ mock_cc2_rpusb_odh.cfg = cfg;
+
+ if (cfg == PIN_GPO)
+ mock_cc2_rpusb_odh.value = en ? 1 : 0;
+}
+
+int vpd_read_host_vbus(void)
+{
+ return mock_read_host_vbus;
+}
+
+int vpd_read_ct_vbus(void)
+{
+ return mock_read_ct_vbus;
+}
+
+int vpd_read_vconn(void)
+{
+ return mock_read_vconn;
+}
+
+int vpd_is_host_vbus_present(void)
+{
+ return (vpd_read_host_vbus() >= PD_SNK_VA);
+}
+
+int vpd_is_ct_vbus_present(void)
+{
+ return (vpd_read_ct_vbus() >= PD_SNK_VA);
+}
+
+int vpd_is_vconn_present(void)
+{
+ return (vpd_read_vconn() >= PD_SNK_VA);
+}
+
+int vpd_read_rdconnect_ref(void)
+{
+ return 200; /* 200 mV */
+}
+
+void vpd_red_led(int on)
+{
+ mock_red_led = on ? 0 : 1;
+}
+
+void vpd_green_led(int on)
+{
+ mock_green_led = on ? 0 : 1;
+}
+
+void vpd_vbus_pass_en(int en)
+{
+ mock_vbus_pass_en = en ? 1 : 0;
+}
+
+void vpd_present_billboard(enum vpd_billboard bb)
+{
+ mock_present_billboard = bb;
+}
+
+void vpd_mcu_cc_en(int en)
+{
+ mock_mcu_cc_en = en ? 1 : 0;
+}
+
+void vpd_ct_cc_sel(enum vpd_cc sel)
+{
+ mock_ct_cl_sel = sel;
+}
+
+/* Set as GPO High, GPO Low, or High-Z */
+void vpd_cc_db_en_od(enum vpd_gpo val)
+{
+ mock_cc_db_en_od = val;
+}
+
+void vpd_cc_rpusb_odh(enum vpd_gpo val)
+{
+ mock_cc_rpusb_odh = val;
+}
+
+void vpd_cc1_cc2_db_en_l(enum vpd_gpo val)
+{
+ mock_cc1_cc2_rd_l = val;
+}
+
+void vpd_vconn_pwr_sel_odl(enum vpd_pwr en)
+{
+ mock_vconn_pwr_sel_odl = en;
+}