summaryrefslogtreecommitdiff
path: root/board/chocodile_vpdmcu
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 /board/chocodile_vpdmcu
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 'board/chocodile_vpdmcu')
-rw-r--r--board/chocodile_vpdmcu/board.c70
-rw-r--r--board/chocodile_vpdmcu/board.h139
-rw-r--r--board/chocodile_vpdmcu/build.mk16
-rw-r--r--board/chocodile_vpdmcu/ec.tasklist22
-rw-r--r--board/chocodile_vpdmcu/gpio.inc80
-rw-r--r--board/chocodile_vpdmcu/usb_pd_config.h163
-rw-r--r--board/chocodile_vpdmcu/vpd_api.c531
-rw-r--r--board/chocodile_vpdmcu/vpd_api.h276
8 files changed, 1297 insertions, 0 deletions
diff --git a/board/chocodile_vpdmcu/board.c b/board/chocodile_vpdmcu/board.c
new file mode 100644
index 0000000000..ea4d129502
--- /dev/null
+++ b/board/chocodile_vpdmcu/board.c
@@ -0,0 +1,70 @@
+/* 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.
+ */
+
+/* chocodile board configuration */
+
+#include "adc.h"
+#include "adc_chip.h"
+#include "common.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "i2c.h"
+#include "registers.h"
+#include "switch.h"
+#include "system.h"
+#include "task.h"
+#include "usb_pd.h"
+#include "usb_pd_tcpc.h"
+#include "util.h"
+#include "vpd_api.h"
+
+#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
+
+void board_config_pre_init(void)
+{
+ /* enable SYSCFG clock */
+ STM32_RCC_APB2ENR |= 1 << 0;
+}
+
+#include "gpio_list.h"
+
+/* Initialize board. */
+static void board_init(void)
+{
+ /* Do nothing */
+}
+DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
+
+/* ADC channels */
+const struct adc_t adc_channels[] = {
+ /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */
+ [ADC_VCONN_VSENSE] = {
+ "VCONN_VSENSE", 3000, 4096, 0, STM32_AIN(ADC_VCONN_VSENSE)},
+ [ADC_CC_VPDMCU] = {
+ "CC_VPDMCU", 3000, 4096, 0, STM32_AIN(ADC_CC_VPDMCU)},
+ [ADC_CC_RP3A0_RD_L] = {
+ "CC_RP3A0_RD_L", 3000, 4096, 0, STM32_AIN(ADC_CC_RP3A0_RD_L)},
+ [ADC_RDCONNECT_REF] = {
+ "RDCONNECT_REF", 3000, 4096, 0, STM32_AIN(ADC_RDCONNECT_REF)},
+ [ADC_CC1_RP3A0_RD_L] = {
+ "CC1_RP1A5_ODH", 3000, 4096, 0, STM32_AIN(ADC_CC1_RP3A0_RD_L)},
+ [ADC_CC2_RP3A0_RD_L] = {
+ "CC2_RP1A5_ODH", 3000, 4096, 0, STM32_AIN(ADC_CC2_RP3A0_RD_L)},
+ [ADC_HOST_VBUS_VSENSE] = {
+ "HOST_VBUS_VSENSE", 3000, 4096, 0, STM32_AIN(ADC_HOST_VBUS_VSENSE)},
+ [ADC_CHARGE_VBUS_VSENSE] = {
+ "CHARGE_VBUS_VSENSE", 3000, 4096, 0, STM32_AIN(ADC_CHARGE_VBUS_VSENSE)},
+ [ADC_CC1_RPUSB_ODH] = {
+ "CC1_RPUSB_ODH", 3000, 4096, 0, STM32_AIN(ADC_CC1_RPUSB_ODH)},
+ [ADC_CC2_RPUSB_ODH] = {
+ "CC2_RPUSB_ODH", 3000, 4096, 0, STM32_AIN(ADC_CC2_RPUSB_ODH)},
+};
+BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
+
+void tcpc_alert_clear(int port)
+{
+ /* Do nothing */
+}
diff --git a/board/chocodile_vpdmcu/board.h b/board/chocodile_vpdmcu/board.h
new file mode 100644
index 0000000000..850d1d0011
--- /dev/null
+++ b/board/chocodile_vpdmcu/board.h
@@ -0,0 +1,139 @@
+/* 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.
+ */
+
+/* chocodile_mcu board configuration */
+
+#ifndef __CROS_EC_BOARD_H
+#define __CROS_EC_BOARD_H
+
+/*
+ * The console task is too big to include in both RO and RW images. Therefore,
+ * if the console task is defined, then only build an RW image. This can be
+ * useful for debugging to have a full console. Otherwise, without this task,
+ * a full RO and RW is built with a limited one-way output console.
+ */
+#ifdef HAS_TASK_CONSOLE
+/*
+ * The flash size is only 32kB.
+ * No space for 2 partitions,
+ * put only RW at the beginning of the flash
+ */
+#undef CONFIG_FW_INCLUDE_RO
+#undef CONFIG_RW_MEM_OFF
+#define CONFIG_RW_MEM_OFF 0
+#undef CONFIG_RO_SIZE
+#define CONFIG_RO_SIZE 0
+/* Fake full size if we had a RO partition */
+#undef CONFIG_RW_SIZE
+#define CONFIG_RW_SIZE CONFIG_FLASH_SIZE
+#endif /* HAS_TASK_CONSOLE */
+
+/* 48 MHz SYSCLK clock frequency */
+#define CPU_CLOCK 48000000
+
+/* the UART console is on USART1 (PA9/PA10) */
+#undef CONFIG_UART_CONSOLE
+#define CONFIG_UART_CONSOLE 1
+
+/* Optional features */
+#define CONFIG_ADC
+#undef CONFIG_ADC_WATCHDOG
+#define CONFIG_ADC_SAMPLE_TIME STM32_ADC_SMPR_41_5_CY
+#define CONFIG_BOARD_PRE_INIT
+#define CONFIG_COMMON_GPIO_SHORTNAMES
+#undef CONFIG_DEBUG_ASSERT
+#define CONFIG_FORCE_CONSOLE_RESUME
+#define CONFIG_HIBERNATE
+#undef CONFIG_HOSTCMD_EVENTS
+#define CONFIG_HW_CRC
+#undef CONFIG_LID_SWITCH
+#define CONFIG_LOW_POWER_IDLE
+#define CONFIG_LTO
+#define CONFIG_STM_HWTIMER32
+#undef CONFIG_TASK_PROFILING
+#undef CONFIG_UART_TX_BUF_SIZE
+#undef CONFIG_UART_TX_DMA
+#undef CONFIG_UART_RX_DMA
+#define CONFIG_UART_TX_BUF_SIZE 128
+#define CONFIG_USB_PD_PORT_COUNT 1
+#define CONFIG_USB_PD_TCPC
+#define CONFIG_USB_PD_VBUS_DETECT_NONE
+#define CONFIG_USB_PD_TCPM_STUB
+#define CONFIG_USB_SM_FRAMEWORK
+#define CONFIG_USB_TYPEC_CTVPD
+#define CONFIG_USB_PD_DUAL_ROLE
+#define CONFIG_USB_PD_INTERNAL_COMP
+#define CONFIG_VBOOT_HASH
+#define CONFIG_WATCHDOG
+#undef CONFIG_WATCHDOG_HELP
+#undef CONFIG_SM_NESTING_NUM
+#define CONFIG_SM_NESTING_NUM 3
+
+#define CONFIG_USB_PID 0x5036
+#define VPD_HW_VERSION 0x0001
+#define VPD_FW_VERSION 0x0001
+
+/* USB bcdDevice */
+#define USB_BCD_DEVICE 0
+
+/* Vbus impedance in milliohms */
+#define VPD_VBUS_IMPEDANCE 65
+
+/* GND impedance in milliohms */
+#define VPD_GND_IMPEDANCE 33
+
+/*
+ * TODO(crosbug.com/p/50519): Remove CONFIG_SYSTEM_UNLOCKED prior to building
+ * MP FW.
+ */
+#define CONFIG_SYSTEM_UNLOCKED
+
+#ifdef HAS_TASK_CONSOLE
+#undef CONFIG_CONSOLE_HISTORY
+#define CONFIG_CONSOLE_HISTORY 2
+
+#else
+#undef CONFIG_CONSOLE_CMDHELP
+#define CONFIG_DEBUG_PRINTF
+#define UARTN CONFIG_UART_CONSOLE
+#define UARTN_BASE STM32_USART_BASE(CONFIG_UART_CONSOLE)
+#endif /* HAS_TASK_CONSOLE */
+
+/* Use PSTATE embedded in the RO image, not in its own erase block */
+#undef CONFIG_FLASH_PSTATE_BANK
+#undef CONFIG_FW_PSTATE_SIZE
+#define CONFIG_FW_PSTATE_SIZE 0
+
+#ifndef __ASSEMBLER__
+
+/* Timer selection */
+#define TIM_CLOCK32 2
+#define TIM_ADC 3
+
+#include "gpio_signal.h"
+
+/* ADC signal */
+enum adc_channel {
+ ADC_VCONN_VSENSE = 0,
+ ADC_CC_VPDMCU,
+ ADC_CC_RP3A0_RD_L,
+ ADC_RDCONNECT_REF,
+ ADC_CC1_RP3A0_RD_L,
+ ADC_CC2_RP3A0_RD_L,
+ ADC_HOST_VBUS_VSENSE,
+ ADC_CHARGE_VBUS_VSENSE,
+ ADC_CC1_RPUSB_ODH,
+ ADC_CC2_RPUSB_ODH,
+ /* Number of ADC channels */
+ ADC_CH_COUNT
+};
+
+/* 1.5A Rp */
+#define PD_SRC_VNC PD_SRC_1_5_VNC_MV
+#define PD_SRC_RD_THRESHOLD PD_SRC_1_5_RD_THRESH_MV
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* __CROS_EC_BOARD_H */
diff --git a/board/chocodile_vpdmcu/build.mk b/board/chocodile_vpdmcu/build.mk
new file mode 100644
index 0000000000..d4e5f58962
--- /dev/null
+++ b/board/chocodile_vpdmcu/build.mk
@@ -0,0 +1,16 @@
+# -*- makefile -*-
+# 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.
+#
+# Board specific files build
+
+# the IC is STmicro STM32F051K8U6TR
+CHIP:=stm32
+CHIP_FAMILY:=stm32f0
+CHIP_VARIANT:=stm32f05x
+
+board-y=board.o vpd_api.o
+#
+# This target builds RW only. Therefore, remove RO from dependencies.
+all_deps=$(patsubst ro,,$(def_all_deps))
diff --git a/board/chocodile_vpdmcu/ec.tasklist b/board/chocodile_vpdmcu/ec.tasklist
new file mode 100644
index 0000000000..e386c745e3
--- /dev/null
+++ b/board/chocodile_vpdmcu/ec.tasklist
@@ -0,0 +1,22 @@
+/* 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.
+ */
+
+/**
+ * List of enabled tasks in the priority order
+ *
+ * The first one has the lowest priority.
+ *
+ * For each task, use the macro TASK_ALWAYS(n, r, d, s) for base tasks and
+ * TASK_NOTEST(n, r, d, s) for tasks that can be excluded in test binaries,
+ * where :
+ * 'n' in the name of the task
+ * 'r' in the main routine of the task
+ * 'd' in an opaque parameter passed to the routine at startup
+ * 's' is the stack size in bytes; must be a multiple of 8
+ */
+#define CONFIG_TASK_LIST \
+ TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE)
diff --git a/board/chocodile_vpdmcu/gpio.inc b/board/chocodile_vpdmcu/gpio.inc
new file mode 100644
index 0000000000..a34c617ef1
--- /dev/null
+++ b/board/chocodile_vpdmcu/gpio.inc
@@ -0,0 +1,80 @@
+/* -*- mode:c -*-
+ *
+ * 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.
+ */
+
+/* Declare symbolic names for all the GPIOs that we care about.
+ * Note: Those with interrupt handlers must be declared first. */
+
+/* Divided Vconn voltage sense */
+GPIO(VCONN_VSENSE, PIN(A, 0), GPIO_ANALOG)
+/* CC ADC, PD in comparator, or tx enable out (low) */
+GPIO(CC_VPDMCU, PIN(A, 1), GPIO_ANALOG)
+/* CC 0.2V comparator during charge-through, active Rd (low) or Rp3A0 (high) */
+GPIO(CC_RP3A0_RD_L, PIN(A, 2), GPIO_ANALOG)
+/* 0.2V resistor divider for various CC comapators */
+GPIO(RDCONNECT_REF, PIN(A, 3), GPIO_ANALOG)
+/* Charger CC1 0.2V comparator and ADC, drive a Rp3A0 (high) or Rd (low) */
+GPIO(CC1_RP3A0_RD_L, PIN(A, 4), GPIO_ANALOG)
+/* Charger CC2 0.2V comparator and ADC, drive a Rp3A0 (high) or Rd (low) */
+GPIO(CC2_RP3A0_RD_L, PIN(A, 5), GPIO_ANALOG)
+/* Divided host VBUS voltage sense */
+GPIO(HOST_VBUS_VSENSE, PIN(A, 6), GPIO_ANALOG)
+/* Divided charger VBUS voltage sense */
+GPIO(CHARGER_VBUS_VSENSE, PIN(A, 7), GPIO_ANALOG)
+/* Charger CC1 ADC, or drive a RpUSB (high) */
+GPIO(CC1_RPUSB_ODH, PIN(B, 0), GPIO_ANALOG)
+/* Charger CC2 ADC, or drive a RpUSB (high) */
+GPIO(CC2_RPUSB_ODH, PIN(B, 1), GPIO_ANALOG)
+
+/* PD TX data output */
+GPIO(CC_TX_DATA, PIN(B, 4), GPIO_INPUT)
+
+/* Enables the VBUS pass-through (high) */
+GPIO(VBUS_PASS_EN, PIN(B, 2), GPIO_OUT_LOW)
+
+/*
+ * Desired billboard state. One of "no billboard/nothing connected" (low),
+ * "source connected but not in charge-through" (pull-up), or "sink connected"
+ * (high)
+ */
+GPIO(PRESENT_BILLBOARD, PIN(A, 8), GPIO_OUT_LOW)
+
+/* Enables cReceiver and the path to the PD RX/TX, RpUSB, and Rp1A5 */
+GPIO(VPDMCU_CC_EN, PIN(A, 11), GPIO_OUT_LOW)
+
+/* Disables dead battery Rd on host side (low) */
+GPIO(CC_DB_EN_OD, PIN(A, 12), GPIO_ODR_HIGH)
+
+/* RpUSB on host side (high) */
+GPIO(CC_RPUSB_ODH, PIN(A, 13), GPIO_INPUT)
+
+/*
+ * Controls the dead-battery pull-downs on charger side; either dead battery
+ * Rd (low) or Hi-Z (high)
+ */
+GPIO(CC1_CC2_DB_EN_L, PIN(A, 15), GPIO_OUT_LOW)
+
+/* Chooses between Vconn (low) and VBUS (high) */
+GPIO(VCONN_PWR_SEL_ODL, PIN(B, 6), GPIO_INPUT)
+
+/* Passes CC1 to the host CC (high) */
+GPIO(CC1_SEL, PIN(F, 0), GPIO_OUT_LOW)
+/* Passes CC2 to the host CC (high) */
+GPIO(CC2_SEL, PIN(F, 1), GPIO_OUT_LOW)
+/* Debug red LED driver (low). Keep off for power measurements */
+GPIO(DEBUG_LED_R_L, PIN(B, 5), GPIO_ODR_HIGH)
+/* Debug green LED driver (low). Keep off for power measurements */
+GPIO(DEBUG_LED_G_L, PIN(B, 7), GPIO_ODR_HIGH)
+
+UNIMPLEMENTED(WP_L)
+UNIMPLEMENTED(ENTERING_RW)
+
+/* SCK(PB3): PD_TX_CLK_IN - Clock input for PD TX */
+ALTERNATE(PIN_MASK(B, 0x0008), 0, MODULE_USB_PD, 0)
+/* TIM16_CH1(PB8): PD_TX_CLK_OUT - Clock generator for PD TX */
+ALTERNATE(PIN_MASK(B, 0x0100), 2, MODULE_USB_PD, 0)
+/* USART1 (PA9/PA10): TX/RX for debug and programming */
+ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, 0)
diff --git a/board/chocodile_vpdmcu/usb_pd_config.h b/board/chocodile_vpdmcu/usb_pd_config.h
new file mode 100644
index 0000000000..a6c1adbc61
--- /dev/null
+++ b/board/chocodile_vpdmcu/usb_pd_config.h
@@ -0,0 +1,163 @@
+/* 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 "adc.h"
+#include "chip/stm32/registers.h"
+#include "ec_commands.h"
+#include "gpio.h"
+#include "vpd_api.h"
+
+/* USB Power delivery board configuration */
+
+#ifndef __CROS_EC_USB_PD_CONFIG_H
+#define __CROS_EC_USB_PD_CONFIG_H
+
+/* Timer selection for baseband PD communication */
+#define TIM_CLOCK_PD_TX_C0 16
+#define TIM_CLOCK_PD_RX_C0 1
+
+#define TIM_CLOCK_PD_TX(p) TIM_CLOCK_PD_TX_C0
+#define TIM_CLOCK_PD_RX(p) TIM_CLOCK_PD_RX_C0
+
+/* Timer channel */
+#define TIM_TX_CCR_C0 1
+#define TIM_RX_CCR_C0 1
+
+/* RX timer capture/compare register */
+#define TIM_CCR_C0 (&STM32_TIM_CCRx(TIM_CLOCK_PD_RX_C0, TIM_RX_CCR_C0))
+#define TIM_RX_CCR_REG(p) TIM_CCR_C0
+
+/* TX and RX timer register */
+#define TIM_REG_TX_C0 (STM32_TIM_BASE(TIM_CLOCK_PD_TX_C0))
+#define TIM_REG_RX_C0 (STM32_TIM_BASE(TIM_CLOCK_PD_RX_C0))
+#define TIM_REG_TX(p) TIM_REG_TX_C0
+#define TIM_REG_RX(p) TIM_REG_RX_C0
+
+/* use the hardware accelerator for CRC */
+#define CONFIG_HW_CRC
+
+/* TX uses SPI1 on PB3-4 for port C0 */
+#define SPI_REGS(p) STM32_SPI1_REGS
+
+static inline void spi_enable_clock(int port)
+{
+ STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI1;
+}
+
+/* SPI1_TX no remap needed */
+#define DMAC_SPI_TX(p) STM32_DMAC_CH3
+
+/* RX is using COMP1 triggering TIM1 CH1 */
+#define CMP1OUTSEL STM32_COMP_CMP1OUTSEL_TIM1_IC1
+#define CMP2OUTSEL 0
+
+#define TIM_TX_CCR_IDX(p) TIM_TX_CCR_C0
+#define TIM_RX_CCR_IDX(p) TIM_RX_CCR_C0
+#define TIM_CCR_CS 1
+
+/* EXTI line 21 is connected to the CMP1 output */
+#define EXTI_COMP1_MASK (1 << 21)
+/* EXTI line 22 is connected to the CMP1 output */
+#define EXTI_COMP2_MASK (1 << 22)
+
+#define EXTI_COMP_MASK(p) (EXTI_COMP1_MASK | EXTI_COMP2_MASK)
+#define IRQ_COMP STM32_IRQ_COMP
+/* triggers packet detection on comparator falling edge */
+#define EXTI_XTSR STM32_EXTI_FTSR
+
+/* TIM1_CH1 no remap needed */
+#define DMAC_TIM_RX(p) STM32_DMAC_CH2
+
+/* the pins used for communication need to be hi-speed */
+static inline void pd_set_pins_speed(int port)
+{
+ /*
+ * 40 MHz pin speed on SPI PB3&4,
+ * (USB_C0_TX_CLKIN & USB_C0_CC1_TX_DATA)
+ *
+ * 40 MHz pin speed on TIM17_CH1 (PB7),
+ * (PD_TX_CLK_OUT)
+ */
+ STM32_GPIO_OSPEEDR(GPIO_B) |= 0x0000C3C0;
+}
+
+/* Reset SPI peripheral used for TX */
+static inline void pd_tx_spi_reset(int port)
+{
+ /* Reset SPI1 */
+ STM32_RCC_APB2RSTR |= (1 << 12);
+ STM32_RCC_APB2RSTR &= ~(1 << 12);
+}
+
+/* Drive the CC line from the TX block */
+static inline void pd_tx_enable(int port, int polarity)
+{
+ /* USB_CC_TX_DATA: PB4 is SPI1 MISO */
+ STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B)
+ & ~(3 << (2*4))) /* PB4 disable ADC */
+ | (2 << (2*4)); /* Set as SPI1_MISO */
+ /* MCU ADC PA1 pin output low */
+ STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A)
+ & ~(3 << (2*1))) /* PA1 disable ADC */
+ | (1 << (2*1)); /* Set as GPO */
+ gpio_set_level(GPIO_CC_VPDMCU, 0);
+}
+
+/* Put the TX driver in Hi-Z state */
+static inline void pd_tx_disable(int port, int polarity)
+{
+ /* Set CC_TX_DATA to Hi-Z, PB4 is SPI1 MISO */
+ STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B)
+ & ~(3 << (2*4)));
+ /* set ADC PA1 pin to ADC function (Hi-Z) */
+ STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A)
+ | (3 << (2*1))); /* PA1 as ADC */
+}
+
+/* we know the plug polarity, do the right configuration */
+static inline void pd_select_polarity(int port, int polarity)
+{
+ /*
+ * use the right comparator : CC1 -> PA1 (COMP1 INP)
+ * use VrefInt / 2 as INM (about 600mV)
+ */
+ STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK)
+ | STM32_COMP_CMP1EN | STM32_COMP_CMP1INSEL_VREF12;
+}
+
+/* Initialize pins used for TX and put them in Hi-Z */
+static inline void pd_tx_init(void)
+{
+ gpio_config_module(MODULE_USB_PD, 1);
+}
+
+static inline void pd_set_host_mode(int port, int enable)
+{
+ /* Do nothing */
+}
+
+/**
+ * Initialize various GPIOs and interfaces to safe state at start of pd_task.
+ *
+ * These include:
+ * Physical layer CC transmit.
+ *
+ * @param port USB-C port number
+ * @param power_role Power role of device
+ */
+static inline void pd_config_init(int port, uint8_t power_role)
+{
+ /* Initialize TX pins and put them in Hi-Z */
+ pd_tx_init();
+ pd_tx_disable(0, 0);
+}
+
+static inline int pd_adc_read(int port, int cc)
+{
+ return 0;
+}
+
+#endif /* __CROS_EC_USB_PD_CONFIG_H */
+
diff --git a/board/chocodile_vpdmcu/vpd_api.c b/board/chocodile_vpdmcu/vpd_api.c
new file mode 100644
index 0000000000..ecbedd082f
--- /dev/null
+++ b/board/chocodile_vpdmcu/vpd_api.c
@@ -0,0 +1,531 @@
+/* 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 "adc.h"
+#include "gpio.h"
+#include "registers.h"
+#include "vpd_api.h"
+#include "driver/tcpm/tcpm.h"
+
+/*
+ * Polarity based on 'DFP Perspective' (see table 4-10 USB Type-C Cable and
+ * Connector Specification Release 1.3)
+ *
+ * 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
+
+#undef CC_RA
+#define CC_RA(cc, sel) (cc < pd_src_rd_threshold[sel])
+#undef CC_RD
+#define CC_RD(cc, sel) ((cc >= pd_src_rd_threshold[sel]) && (cc < PD_SRC_VNC))
+
+/* (15.8K / (100K + 15.8K)) * 1000 = 136.4 */
+#define VBUS_SCALE_FACTOR 136
+/* (118K / (100K + 118K)) * 1000 = 541.3 */
+#define VCONN_SCALE_FACTOR 541
+
+#define VBUS_DETECT_THRESHOLD 2500 /* mV */
+#define VCONN_DETECT_THRESHOLD 2500 /* mV */
+
+#define SCALE(vmeas, sfactor) (((vmeas) * 1000) / (sfactor))
+
+/*
+ * Type C power source charge current limits are identified by their cc
+ * voltage (set by selecting the proper Rd resistor). Any voltage below
+ * TYPE_C_SRC_500_THRESHOLD will not be identified as a type C charger.
+ */
+#define TYPE_C_SRC_DEFAULT_THRESHOLD 200 /* mV */
+#define TYPE_C_SRC_1500_THRESHOLD 660 /* mV */
+#define TYPE_C_SRC_3000_THRESHOLD 1230 /* mV */
+
+/* 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,
+};
+
+/* 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_RD(cc_volt, ct_cc_rp_value))
+ return TYPEC_CC_RD;
+ else if (CC_RA(cc_volt, ct_cc_rp_value))
+ return TYPEC_CC_VOLT_RA;
+ else
+ return TYPEC_CC_VOLT_OPEN;
+ /* 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_volt >= TYPE_C_SRC_DEFAULT_THRESHOLD)
+ 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_GPO, 0);
+ vpd_config_cc2_rp3a0_rd_l(PIN_GPO, 0);
+ vpd_cc1_cc2_db_en_l(GPO_HIGH);
+ 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 = adc_read_channel(ADC_CC1_RP3A0_RD_L);
+ cc2_v = adc_read_channel(ADC_CC2_RP3A0_RD_L);
+ break;
+ case TYPEC_RP_3A0:
+ cc1_v = adc_read_channel(ADC_CC1_RPUSB_ODH);
+ cc2_v = adc_read_channel(ADC_CC2_RPUSB_ODH);
+ break;
+ }
+ break;
+ case TYPEC_CC_RD:
+ cc1_v = adc_read_channel(ADC_CC1_RPUSB_ODH);
+ cc2_v = adc_read_channel(ADC_CC2_RPUSB_ODH);
+ 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);
+ break;
+ }
+}
+
+void vpd_host_get_cc(int *cc)
+{
+ *cc = vpd_cc_voltage_to_status(
+ adc_read_channel(ADC_CC_VPDMCU), host_cc_pull);
+}
+
+void vpd_rx_enable(int en)
+{
+ tcpm_set_rx_enable(0, en);
+}
+
+/*
+ * PA2: Configure as COMP2_INM6 or GPO
+ */
+void vpd_config_cc_rp3a0_rd_l(enum vpd_pin cfg, int en)
+{
+ if (cfg == PIN_GPO) {
+ /* Set output value in register */
+ gpio_set_level(GPIO_CC_RP3A0_RD_L, en ? 1 : 0);
+
+ /* Disable Analog mode and Enable GPO */
+ STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A)
+ & ~(3 << (2*2))) /* PA2 disable ADC */
+ | (1 << (2*2)); /* Set as GPO */
+ } else {
+ /* Set PA2 pin to ANALOG function */
+ STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A)
+ | (3 << (2*2))); /* PA2 in ANALOG mode */
+
+ /* Set PA3 pin to ANALOG function */
+ STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A)
+ | (3 << (2*3))); /* PA3 in ANALOG mode */
+
+ /* Disable Window Mode. Select PA3 */
+ STM32_COMP_CSR &= ~STM32_COMP_WNDWEN;
+
+ /* No output selection. We will use Interrupt */
+ STM32_COMP_CSR &= ~STM32_COMP_CMP2OUTSEL_NONE;
+
+ /* Not inverting */
+ STM32_COMP_CSR &= ~STM32_COMP_CMP2POL;
+
+ /* Select COMP2_INM6 (PA2) */
+ STM32_COMP_CSR |= STM32_COMP_CMP2INSEL_INM6;
+
+ /* COMP Enable */
+ STM32_COMP_CSR |= STM32_COMP_CMP2EN;
+ }
+}
+
+/*
+ * PA4: Configure as ADC, CMP, or GPO
+ */
+void vpd_config_cc1_rp3a0_rd_l(enum vpd_pin cfg, int en)
+{
+ if (cfg == PIN_GPO) {
+ /* Default high. Enable cc1 Rp3A0 pullup */
+ gpio_set_level(GPIO_CC1_RP3A0_RD_L, en ? 1 : 0);
+
+ /* Disable Analog mode and Enable GPO */
+ STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A)
+ & ~(3 << (2*4))) /* PA4 disable ADC */
+ | (1 << (2*4)); /* Set as GPO */
+ }
+
+ if (cfg == PIN_ADC || cfg == PIN_CMP) {
+ /* Disable COMP2 */
+ STM32_COMP_CSR &= ~STM32_COMP_CMP2EN;
+
+ /* Set PA4 pin to Analog mode */
+ STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A)
+ | (3 << (2*4))); /* PA4 in ANALOG mode */
+
+ if (cfg == PIN_CMP) {
+ /* Set PA3 pin to ANALOG function */
+ STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A)
+ | (3 << (2*3))); /* PA3 in ANALOG mode */
+
+ /* Disable Window Mode. Select PA3*/
+ STM32_COMP_CSR &= ~STM32_COMP_WNDWEN;
+
+ /* No output selection. We will use Interrupt */
+ STM32_COMP_CSR &= ~STM32_COMP_CMP2OUTSEL_NONE;
+
+ /* Select COMP2_INM4 (PA4) */
+ STM32_COMP_CSR |= STM32_COMP_CMP2INSEL_INM4;
+
+ /* COMP2 Enable */
+ STM32_COMP_CSR |= STM32_COMP_CMP2EN;
+ }
+ }
+}
+
+/*
+ * PA5: Configure as ADC, COMP, or GPO
+ */
+void vpd_config_cc2_rp3a0_rd_l(enum vpd_pin cfg, int en)
+{
+ if (cfg == PIN_GPO) {
+ /* Set output value in register */
+ gpio_set_level(GPIO_CC2_RP3A0_RD_L, en ? 1 : 0);
+
+ /* Disable Analog mode and Enable GPO */
+ STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A)
+ & ~(3 << (2*5))) /* PA5 disable ADC */
+ | (1 << (2*5)); /* Set as GPO */
+ }
+
+ if (cfg == PIN_ADC || cfg == PIN_CMP) {
+ /* Disable COMP2 */
+ STM32_COMP_CSR &= ~STM32_COMP_CMP2EN;
+
+ /* Set PA5 pin to ANALOG function */
+ STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A)
+ | (3 << (2*5))); /* PA5 in ANALOG mode */
+
+ if (cfg == PIN_CMP) {
+ /* Set PA3 pin to ANALOG function */
+ STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A)
+ | (3 << (2*3))); /* PA3 in ANALOG mode */
+
+ /* Disable Window Mode. */
+ STM32_COMP_CSR &= ~STM32_COMP_WNDWEN;
+
+ /* No output selection. We will use Interrupt */
+ STM32_COMP_CSR &= ~STM32_COMP_CMP2OUTSEL_NONE;
+
+ /* Select COMP2_INM5 (PA5) */
+ STM32_COMP_CSR |= STM32_COMP_CMP2INSEL_INM5;
+
+ /* COMP2 Enable */
+ STM32_COMP_CSR |= STM32_COMP_CMP2EN;
+ }
+ }
+}
+
+/*
+ * PB0: Configure as ADC or GPO
+ */
+void vpd_config_cc1_rpusb_odh(enum vpd_pin cfg, int en)
+{
+ if (cfg == PIN_GPO) {
+ /* Set output value in register */
+ gpio_set_level(GPIO_CC1_RPUSB_ODH, en ? 1 : 0);
+
+ /* Disable Analog mode and Enable GPO */
+ STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B)
+ & ~(3 << (2*0))) /* PB0 disable ADC */
+ | (1 << (2*0)); /* Set as GPO */
+ } else {
+ /* Enable Analog mode */
+ STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B)
+ | (3 << (2*0))); /* PB0 in ANALOG mode */
+ }
+}
+
+/*
+ * PB1: Configure as ADC or GPO
+ */
+void vpd_config_cc2_rpusb_odh(enum vpd_pin cfg, int en)
+{
+ if (cfg == PIN_GPO) {
+ /* Set output value in register */
+ gpio_set_level(GPIO_CC2_RPUSB_ODH, en ? 1 : 0);
+
+ /* Disable Analog mode and Enable GPO */
+ STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B)
+ & ~(3 << (2*1))) /* PB1 disable ADC */
+ | (1 << (2*1)); /* Set as GPO */
+ } else {
+ /* Enable Analog mode */
+ STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B)
+ | (3 << (2*1))); /* PB1 in ANALOG mode */
+ }
+}
+
+inline int vpd_read_cc_vpdmcu(void)
+{
+ return adc_read_channel(ADC_CC_VPDMCU);
+}
+
+inline int vpd_read_host_vbus(void)
+{
+ return SCALE(adc_read_channel(ADC_HOST_VBUS_VSENSE), VBUS_SCALE_FACTOR);
+}
+
+inline int vpd_read_ct_vbus(void)
+{
+ return SCALE(adc_read_channel(ADC_CHARGE_VBUS_VSENSE),
+ VBUS_SCALE_FACTOR);
+}
+
+inline int vpd_read_vconn(void)
+{
+ return SCALE(adc_read_channel(ADC_VCONN_VSENSE), VCONN_SCALE_FACTOR);
+}
+
+inline int vpd_is_host_vbus_present(void)
+{
+ return (vpd_read_host_vbus() >= VBUS_DETECT_THRESHOLD);
+}
+
+inline int vpd_is_ct_vbus_present(void)
+{
+ return (vpd_read_ct_vbus() >= VBUS_DETECT_THRESHOLD);
+}
+
+inline int vpd_is_vconn_present(void)
+{
+ return (vpd_read_vconn() >= VCONN_DETECT_THRESHOLD);
+}
+
+inline int vpd_read_rdconnect_ref(void)
+{
+ return adc_read_channel(ADC_RDCONNECT_REF);
+}
+
+void vpd_red_led(int on)
+{
+ gpio_set_level(GPIO_DEBUG_LED_R_L, (on) ? 0 : 1);
+}
+
+void vpd_green_led(int on)
+{
+ gpio_set_level(GPIO_DEBUG_LED_G_L, (on) ? 0 : 1);
+}
+
+void vpd_vbus_pass_en(int en)
+{
+ gpio_set_level(GPIO_VBUS_PASS_EN, (en) ? 1 : 0);
+}
+
+void vpd_present_billboard(enum vpd_billboard bb)
+{
+ switch (bb) {
+ case BB_NONE:
+ gpio_set_level(GPIO_PRESENT_BILLBOARD, 0);
+ gpio_set_flags(GPIO_PRESENT_BILLBOARD, GPIO_OUTPUT);
+ break;
+ case BB_SRC:
+ gpio_set_flags(GPIO_PRESENT_BILLBOARD, GPIO_INPUT);
+ /* Enable Pull-up on PA8 */
+ STM32_GPIO_PUPDR(GPIO_A) |= (1 << (2 * 8));
+ break;
+ case BB_SNK:
+ gpio_set_level(GPIO_PRESENT_BILLBOARD, 1);
+ gpio_set_flags(GPIO_PRESENT_BILLBOARD, GPIO_OUTPUT);
+ break;
+ }
+}
+
+void vpd_mcu_cc_en(int en)
+{
+ gpio_set_level(GPIO_VPDMCU_CC_EN, (en) ? 1 : 0);
+}
+
+void vpd_ct_cc_sel(enum vpd_cc sel)
+{
+ switch (sel) {
+ case CT_OPEN:
+ gpio_set_level(GPIO_CC1_SEL, 0);
+ gpio_set_level(GPIO_CC2_SEL, 0);
+ break;
+ case CT_CC1:
+ gpio_set_level(GPIO_CC2_SEL, 0);
+ gpio_set_level(GPIO_CC1_SEL, 1);
+ break;
+ case CT_CC2:
+ gpio_set_level(GPIO_CC1_SEL, 0);
+ gpio_set_level(GPIO_CC2_SEL, 1);
+ break;
+ }
+}
+
+/* Set as GPO High, GPO Low, or High-Z */
+void vpd_cc_db_en_od(enum vpd_gpo val)
+{
+ if (val == GPO_HZ) {
+ gpio_set_flags(GPIO_CC_DB_EN_OD, GPIO_INPUT);
+ } else {
+ if (val == GPO_HIGH)
+ gpio_set_level(GPIO_CC_DB_EN_OD, 1);
+ else
+ gpio_set_level(GPIO_CC_DB_EN_OD, 0);
+
+ gpio_set_flags(GPIO_CC_DB_EN_OD, GPIO_OUTPUT);
+ }
+}
+
+void vpd_cc_rpusb_odh(enum vpd_gpo val)
+{
+ if (val == GPO_HZ) {
+ gpio_set_flags(GPIO_CC_RPUSB_ODH, GPIO_INPUT);
+ } else {
+ gpio_set_level(GPIO_CC_RPUSB_ODH, (val == GPO_HIGH) ? 1 : 0);
+ gpio_set_flags(GPIO_CC_RPUSB_ODH, GPIO_OUTPUT);
+ }
+}
+
+void vpd_cc1_cc2_db_en_l(enum vpd_gpo val)
+{
+ if (val == GPO_HZ) {
+ gpio_set_flags(GPIO_CC1_CC2_DB_EN_L, GPIO_INPUT);
+ } else {
+ gpio_set_level(GPIO_CC1_CC2_DB_EN_L, (val == GPO_HIGH) ? 1 : 0);
+ gpio_set_flags(GPIO_CC1_CC2_DB_EN_L, GPIO_OUTPUT);
+ }
+}
+
+void vpd_vconn_pwr_sel_odl(enum vpd_pwr en)
+{
+ gpio_set_level(GPIO_VCONN_PWR_SEL_ODL, (en == PWR_VBUS) ? 1 : 0);
+}
diff --git a/board/chocodile_vpdmcu/vpd_api.h b/board/chocodile_vpdmcu/vpd_api.h
new file mode 100644
index 0000000000..df50f92006
--- /dev/null
+++ b/board/chocodile_vpdmcu/vpd_api.h
@@ -0,0 +1,276 @@
+/* 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.
+ */
+
+/* Vconn Power Device API module */
+
+#ifndef __CROS_EC_VPD_API_H
+#define __CROS_EC_VPD_API_H
+
+#include "adc.h"
+#include "gpio.h"
+#include "usb_pd.h"
+
+enum vpd_pin {
+ PIN_ADC,
+ PIN_CMP,
+ PIN_GPO
+};
+
+enum vpd_gpo {
+ GPO_HZ,
+ GPO_HIGH,
+ GPO_LOW
+};
+
+enum vpd_pwr {
+ PWR_VCONN,
+ PWR_VBUS,
+};
+
+enum vpd_cc {
+ CT_OPEN,
+ CT_CC1,
+ CT_CC2
+};
+
+enum vpd_billboard {
+ BB_NONE,
+ BB_SRC,
+ BB_SNK
+};
+
+/**
+ * Set Charge-Through Rp or Rd on CC lines
+ *
+ * @param pull Either TYPEC_CC_RP or TYPEC_CC_RD
+ * @param rp_value When pull is RP, set this to
+ * TYPEC_RP_USB or TYPEC_RP_1A5. Ignored
+ * for TYPEC_CC_RD
+ */
+void vpd_ct_set_pull(int pull, int rp_value);
+
+/**
+ * Get the status of the Charge-Through CC lines
+ *
+ * @param cc1 Either TYPEC_CC_VOLT_OPEN,
+ * TYPEC_CC_VOLT_RA,
+ * TYPEC_CC_VOLT_RD,
+ * any other value is considered RP
+ * @param cc2 Either TYPEC_CC_VOLT_OPEN,
+ * TYPEC_CC_VOLT_RA,
+ * TYPEC_CC_VOLT_RD,
+ * any other value is considered RP
+ */
+void vpd_ct_get_cc(int *cc1, int *cc2);
+
+/**
+ * Set Host Rp or Rd on CC lines
+ *
+ * @param pull Either TYPEC_CC_RP or TYPEC_CC_RD
+ * @param rp_value When pull is RP, set this to
+ * TYPEC_RP_USB or TYPEC_RP_1A5. Ignored
+ * for TYPEC_CC_RD
+ */
+void vpd_host_set_pull(int pull, int rp_value);
+
+/**
+ * Get the status of the Host CC line
+ *
+ * @param cc Either TYPEC_CC_VOLT_SNK_DEF, TYPEC_CC_VOLT_SNK_1_5,
+ * TYPEC_CC_VOLT_SNK_3_0, or TYPEC_CC_RD
+ */
+void vpd_host_get_cc(int *cc);
+
+/**
+ * Set RX Enable flag
+ *
+ * @param en 1 for enable, 0 for disable
+ */
+void vpd_rx_enable(int en);
+
+/**
+ * Configure the cc_rp3a0_rd_l pin as ADC, CMP, or GPO
+ *
+ * @param cfg PIN_ADC, PIN_CMP, or PIN_GPO
+ * @param en When cfg is PIN_GPO, 1 sets pin high
+ * and 0 sets pin low. Else ignored
+ */
+void vpd_config_cc_rp3a0_rd_l(enum vpd_pin cfg, int en);
+
+/**
+ * Configure the cc1_rp3a0_rd_l pin as ADC, CMP, or GPO
+ *
+ * @param cfg PIN_ADC, PIN_CMP, or PIN_GPO
+ * @param en When cfg is PIN_GPO, 1 sets pin high
+ * and 0 sets pin low. Else ignored
+ */
+void vpd_config_cc1_rp3a0_rd_l(enum vpd_pin cfg, int en);
+
+/**
+ * Configure the cc2_rp3a0_rd_l pin as ADC, CMP, or GPO
+ *
+ * @param cfg PIN_ADC, PIN_CMP, or PIN_GPO
+ * @param en When cfg is PIN_GPO, 1 sets pin high
+ * and 0 sets pin low. Else ignored
+ */
+void vpd_config_cc2_rp3a0_rd_l(enum vpd_pin cfg, int en);
+
+/**
+ * Configure the cc1_rpusb_odh pin as ADC, CMP, or GPO
+ *
+ * @param cfg PIN_ADC, PIN_CMP, or PIN_GPO
+ * @param en When cfg is PIN_GPO, 1 sets pin high
+ * and 0 sets pin low. Else ignored
+ */
+void vpd_config_cc1_rpusb_odh(enum vpd_pin cfg, int en);
+
+/**
+ * Configure the cc2_rpusb_odh pin as ADC, CMP, or GPO
+ *
+ * @param cfg PIN_ADC, PIN_CMP, or PIN_GPO
+ * @param en When cfg is PIN_GPO, 1 sets pin high
+ * and 0 sets pin low. Else ignored
+ */
+void vpd_config_cc2_rpusb_odh(enum vpd_pin cfg, int en);
+
+/**
+ * Configure the cc_db_en_od pin to High-Impedance, low, or high
+ *
+ * @param val GPO_HZ, GPO_HIGH, GPO_LOW
+ */
+void vpd_cc_db_en_od(enum vpd_gpo val);
+
+/**
+ * Configure the cc_rpusb_odh pin to High-Impedance, low, or high
+ *
+ * @param val GPO_HZ, GPO_HIGH, GPO_LOW
+ */
+void vpd_cc_rpusb_odh(enum vpd_gpo val);
+
+/**
+ * Configure the cc_rp1a5_odh pin to High-Impedance, low, or high
+ *
+ * @param val GPO_HZ, GPO_HIGH, GPO_LOW
+ */
+void vpd_cc_rp1a5_odh(enum vpd_gpo val);
+
+/**
+ * Configure the cc1_cc2_db_en_l pin to High-Impedance, low, or high
+ *
+ * @param val GPO_HZ, GPO_HIGH, GPO_LOW
+ */
+void vpd_cc1_cc2_db_en_l(enum vpd_gpo val);
+
+/**
+ * Get status of host vbus
+ *
+ * @return 1 if host vbus is present, else 0
+ */
+int vpd_is_host_vbus_present(void);
+
+/**
+ * Get status of charge-through vbus
+ *
+ * @return 1 if charge-through vbus is present, else 0
+ */
+int vpd_is_ct_vbus_present(void);
+
+/**
+ * Get status of vconn
+ *
+ * @return 1 if vconn is present, else 0
+ */
+int vpd_is_vconn_present(void);
+
+/**
+ * Read Host VBUS voltage. Range from 22000mV to 3000mV
+ *
+ * @return vbus voltage
+ */
+int vpd_read_host_vbus(void);
+
+/**
+ * Read Host CC voltage.
+ *
+ * @return cc voltage
+ */
+int vpd_read_cc_host(void);
+
+/**
+ * Read voltage on cc_vpdmcu pin
+ *
+ * @return cc_vpdmcu voltage
+ */
+int vpd_read_cc_vpdmcu(void);
+
+/**
+ * Read charge-through VBUS voltage. Range from 22000mV to 3000mV
+ *
+ * @return charge-through vbus voltage
+ */
+int vpd_read_ct_vbus(void);
+
+/**
+ * Read VCONN Voltage. Range from 5500mV to 3000mV
+ *
+ * @return vconn voltage
+ */
+int vpd_read_vconn(void);
+
+/**
+ * Turn ON/OFF Red LED. Should be off when performing power
+ * measurements.
+ *
+ * @param on 0 turns LED off, any other value turns it ON
+ */
+void vpd_red_led(int on);
+
+/**
+ * Turn ON/OFF Green LED. Should be off when performing power
+ * measurements.
+ *
+ * @param on 0 turns LED off, any other value turns it ON
+ */
+void vpd_green_led(int on);
+
+/**
+ * Connects/Disconnects the Host VBUS to the Charge-Through VBUS.
+ *
+ * @param en 0 disconnectes the VBUS, any other value connects VBUS.
+ */
+void vpd_vbus_pass_en(int en);
+
+/**
+ * Preset Billboard device
+ *
+ * @param bb BB_NONE no billboard presented,
+ * BB_SRC source connected but not in charge-through
+ * BB_SNK sink connected
+ */
+void vpd_present_billboard(enum vpd_billboard bb);
+
+/**
+ * Enables the MCU to host cc communication
+ *
+ * @param en 1 enabled, 0 disabled
+ */
+void vpd_mcu_cc_en(int en);
+
+/**
+ * Selects which supply to power the VPD from
+ *
+ * @param en PWR_VCONN or PWR_VBUS
+ */
+void vpd_vconn_pwr_sel_odl(enum vpd_pwr en);
+
+/**
+ * Controls if the Charge-Through's CC1, CC2, or neither is
+ * connected to Host CC
+ *
+ * @param sel CT_OPEN neither, CT_CC1 cc1, CT_CC2 cc2
+ */
+void vpd_ct_cc_sel(enum vpd_cc sel);
+
+#endif /* __CROS_EC_VPD_API_H */