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>
This commit is contained in:
parent
e097feb8b2
commit
0fe6147a9d
|
@ -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 */
|
||||
}
|
|
@ -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 */
|
|
@ -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))
|
|
@ -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)
|
|
@ -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)
|
|
@ -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 */
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
|
@ -40,7 +40,11 @@ static const struct adc_profile_t profile = {
|
|||
/* Sample all channels once using DMA */
|
||||
.cfgr1_reg = STM32_ADC_CFGR1_OVRMOD,
|
||||
.cfgr2_reg = 0,
|
||||
#ifdef CONFIG_ADC_SAMPLE_TIME
|
||||
.smpr_reg = CONFIG_ADC_SAMPLE_TIME,
|
||||
#else
|
||||
.smpr_reg = STM32_ADC_SMPR_13_5_CY,
|
||||
#endif
|
||||
.ier_reg = 0,
|
||||
.dma_option = &dma_single,
|
||||
.dma_buffer_size = 1,
|
||||
|
@ -60,7 +64,11 @@ static const struct adc_profile_t profile = {
|
|||
STM32_ADC_CFGR1_CONT |
|
||||
STM32_ADC_CFGR1_DMACFG,
|
||||
.cfgr2_reg = 0,
|
||||
#ifdef CONFIG_ADC_SAMPLE_TIME
|
||||
.smpr_reg = CONFIG_ADC_SAMPLE_TIME,
|
||||
#else
|
||||
.smpr_reg = STM32_ADC_SMPR_1_5_CY,
|
||||
#endif
|
||||
/* Fire interrupt at end of sequence. */
|
||||
.ier_reg = STM32_ADC_IER_EOSEQIE,
|
||||
.dma_option = &dma_continuous,
|
||||
|
|
|
@ -452,6 +452,16 @@ void pd_rx_handler(void)
|
|||
int next_idx;
|
||||
pending = STM32_EXTI_PR;
|
||||
|
||||
#ifdef CONFIG_USB_TYPEC_CTVPD
|
||||
/* Charge-Through Side detach event */
|
||||
if (pending & EXTI_COMP2_MASK) {
|
||||
task_set_event(PD_PORT_TO_TASK_ID(0), PD_EVENT_SM, 0);
|
||||
/* Clear interrupt */
|
||||
STM32_EXTI_PR = EXTI_COMP2_MASK;
|
||||
pending &= ~EXTI_COMP2_MASK;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) {
|
||||
if (pending & EXTI_COMP_MASK(i)) {
|
||||
rx_edge_ts[i][rx_edge_ts_idx[i]].val = get_time().val;
|
||||
|
@ -648,6 +658,7 @@ void pd_hw_init(int port, int role)
|
|||
phy->tim_tx->ccmr1 = val;
|
||||
else
|
||||
phy->tim_tx->ccmr2 = val;
|
||||
|
||||
phy->tim_tx->ccer = 1 << ((TIM_TX_CCR_IDX(port) - 1) * 4);
|
||||
phy->tim_tx->bdtr = 0x8000;
|
||||
/* set prescaler to /1 */
|
||||
|
|
|
@ -128,7 +128,14 @@ common-$(CONFIG_USB_I2C)+=usb_i2c.o
|
|||
common-$(CONFIG_USB_CHARGER)+=usb_charger.o
|
||||
common-$(CONFIG_USB_PORT_POWER_DUMB)+=usb_port_power_dumb.o
|
||||
common-$(CONFIG_USB_PORT_POWER_SMART)+=usb_port_power_smart.o
|
||||
ifeq ($(CONFIG_USB_SM_FRAMEWORK),)
|
||||
common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o usb_pd_policy.o
|
||||
else
|
||||
common-$(CONFIG_USB_SM_FRAMEWORK)+=usb_sm.o
|
||||
common-$(CONFIG_USB_TYPEC_SM)+=usb_tc_sm.o
|
||||
common-$(CONFIG_USB_PRL_SM)+=usb_prl_sm.o
|
||||
common-$(CONFIG_USB_PE_SM)+=usb_pe_sm.o
|
||||
endif
|
||||
common-$(CONFIG_USB_PD_LOGGING)+=event_log.o pd_log.o
|
||||
common-$(CONFIG_USB_PD_TCPC)+=usb_pd_tcpc.o
|
||||
common-$(CONFIG_USB_UPDATE)+=usb_update.o update_fw.o
|
||||
|
|
|
@ -343,11 +343,19 @@ int prepare_message(int port, uint16_t header, uint8_t cnt,
|
|||
int off, i;
|
||||
/* 64-bit preamble */
|
||||
off = pd_write_preamble(port);
|
||||
#if defined(CONFIG_USB_TYPEC_VPD) || defined(CONFIG_USB_TYPEC_CTVPD)
|
||||
/* Start Of Packet Prime: 2x Sync-1 + 2x Sync-3 */
|
||||
off = pd_write_sym(port, off, BMC(PD_SYNC1));
|
||||
off = pd_write_sym(port, off, BMC(PD_SYNC1));
|
||||
off = pd_write_sym(port, off, BMC(PD_SYNC3));
|
||||
off = pd_write_sym(port, off, BMC(PD_SYNC3));
|
||||
#else
|
||||
/* Start Of Packet: 3x Sync-1 + 1x Sync-2 */
|
||||
off = pd_write_sym(port, off, BMC(PD_SYNC1));
|
||||
off = pd_write_sym(port, off, BMC(PD_SYNC1));
|
||||
off = pd_write_sym(port, off, BMC(PD_SYNC1));
|
||||
off = pd_write_sym(port, off, BMC(PD_SYNC2));
|
||||
#endif
|
||||
/* header */
|
||||
off = encode_short(port, off, header);
|
||||
|
||||
|
@ -682,6 +690,17 @@ int pd_analyze_rx(int port, uint32_t *payload)
|
|||
/* Find the Start Of Packet sequence */
|
||||
while (bit > 0) {
|
||||
bit = pd_dequeue_bits(port, bit, 20, &val);
|
||||
#if defined(CONFIG_USB_TYPEC_VPD) || defined(CONFIG_USB_TYPEC_CTVPD)
|
||||
if (val == PD_SOP_PRIME) {
|
||||
break;
|
||||
} else if (val == PD_SOP) {
|
||||
CPRINTF("SOP\n");
|
||||
return PD_RX_ERR_UNSUPPORTED_SOP;
|
||||
} else if (val == PD_SOP_PRIME_PRIME) {
|
||||
CPRINTF("SOP''\n");
|
||||
return PD_RX_ERR_UNSUPPORTED_SOP;
|
||||
}
|
||||
#else /* CONFIG_USB_TYPEC_VPD || CONFIG_USB_TYPEC_CTVPD */
|
||||
#ifdef CONFIG_USB_PD_DECODE_SOP
|
||||
if (val == PD_SOP || val == PD_SOP_PRIME ||
|
||||
val == PD_SOP_PRIME_PRIME)
|
||||
|
@ -696,7 +715,8 @@ int pd_analyze_rx(int port, uint32_t *payload)
|
|||
CPRINTF("SOP''\n");
|
||||
return PD_RX_ERR_UNSUPPORTED_SOP;
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_USB_PD_DECODE_SOP */
|
||||
#endif /* CONFIG_USB_TYPEC_VPD || CONFIG_USB_TYPEC_CTVPD */
|
||||
}
|
||||
if (bit < 0) {
|
||||
#ifdef CONFIG_USB_PD_DECODE_SOP
|
||||
|
@ -872,7 +892,11 @@ int tcpc_run(int port, int evt)
|
|||
/* outgoing packet ? */
|
||||
if ((evt & PD_EVENT_TX) && pd[port].rx_enabled) {
|
||||
switch (pd[port].tx_type) {
|
||||
#if defined(CONFIG_USB_TYPEC_VPD) || defined(CONFIG_USB_TYPEC_CTVPD)
|
||||
case TCPC_TX_SOP_PRIME:
|
||||
#else
|
||||
case TCPC_TX_SOP:
|
||||
#endif
|
||||
res = send_validate_message(port,
|
||||
pd[port].tx_head,
|
||||
pd[port].tx_data);
|
||||
|
@ -938,7 +962,7 @@ int tcpc_run(int port, int evt)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USB_POWER_DELIVERY
|
||||
#if !defined(CONFIG_USB_POWER_DELIVERY) && !defined(CONFIG_USB_SM_FRAMEWORK)
|
||||
void pd_task(void *u)
|
||||
{
|
||||
int port = TASK_ID_TO_PD_PORT(task_get_current());
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
/* 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 "common.h"
|
||||
|
||||
/* Include USB PD Policy Engine State Machine */
|
||||
#if defined(CONFIG_USB_TYPEC_VPD) || defined(CONFIG_USB_TYPEC_CTVPD)
|
||||
#include "usb_pe_ctvpd_sm.h"
|
||||
#else
|
||||
#error "A USB PD Policy Engine State Machine must be defined."
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,166 @@
|
|||
/* 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 "common.h"
|
||||
#include "task.h"
|
||||
#include "usb_pd.h"
|
||||
#include "usb_sm.h"
|
||||
#include "util.h"
|
||||
#include "console.h"
|
||||
|
||||
void init_state(int port, struct sm_obj *obj, sm_state target)
|
||||
{
|
||||
#if (CONFIG_SM_NESTING_NUM > 0)
|
||||
int i;
|
||||
|
||||
sm_state tmp_super[CONFIG_SM_NESTING_NUM];
|
||||
#endif
|
||||
|
||||
obj->last_state = NULL;
|
||||
obj->task_state = target;
|
||||
|
||||
#if (CONFIG_SM_NESTING_NUM > 0)
|
||||
|
||||
/* Prepare to execute all entry actions of the target's super states */
|
||||
|
||||
/*
|
||||
* Get targets super state. This will be NULL if the target
|
||||
* has no super state
|
||||
*/
|
||||
tmp_super[CONFIG_SM_NESTING_NUM - 1] =
|
||||
(sm_state)(uintptr_t)target(port, SUPER_SIG);
|
||||
|
||||
/* Get all super states of the target */
|
||||
for (i = CONFIG_SM_NESTING_NUM - 1; i > 0; i--) {
|
||||
if (tmp_super[i] != NULL)
|
||||
tmp_super[i - 1] =
|
||||
(sm_state)(uintptr_t)tmp_super[i](port, SUPER_SIG);
|
||||
else
|
||||
tmp_super[i - 1] = NULL;
|
||||
}
|
||||
|
||||
/* Execute all super state entry actions in forward order */
|
||||
for (i = 0; i < CONFIG_SM_NESTING_NUM; i++)
|
||||
if (tmp_super[i] != NULL)
|
||||
tmp_super[i](port, ENTRY_SIG);
|
||||
#endif
|
||||
|
||||
/* Now execute the target entry action */
|
||||
target(port, ENTRY_SIG);
|
||||
}
|
||||
|
||||
int set_state(int port, struct sm_obj *obj, sm_state target)
|
||||
{
|
||||
#if (CONFIG_SM_NESTING_NUM > 0)
|
||||
int i;
|
||||
int no_execute;
|
||||
|
||||
sm_state tmp_super[CONFIG_SM_NESTING_NUM];
|
||||
sm_state target_super;
|
||||
sm_state last_super;
|
||||
sm_state super;
|
||||
|
||||
/* Execute all exit actions is reverse order */
|
||||
|
||||
/* Get target's super state */
|
||||
target_super = (sm_state)(uintptr_t)target(port, SUPER_SIG);
|
||||
tmp_super[0] = obj->task_state;
|
||||
|
||||
do {
|
||||
/* Execute exit action */
|
||||
tmp_super[0](port, EXIT_SIG);
|
||||
|
||||
/* Get super state */
|
||||
tmp_super[0] =
|
||||
(sm_state)(uintptr_t)tmp_super[0](port, SUPER_SIG);
|
||||
/*
|
||||
* No need to execute a super state's exit action that has
|
||||
* shared ancestry with the target.
|
||||
*/
|
||||
super = target_super;
|
||||
while (super != NULL) {
|
||||
if (tmp_super[0] == super) {
|
||||
tmp_super[0] = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get target state next super state if it exists */
|
||||
super = (sm_state)(uintptr_t)super(port, SUPER_SIG);
|
||||
}
|
||||
} while (tmp_super[0] != NULL);
|
||||
|
||||
/* All done executing the exit actions */
|
||||
#else
|
||||
obj->task_state(port, EXIT_SIG);
|
||||
#endif
|
||||
/* update the state variables */
|
||||
obj->last_state = obj->task_state;
|
||||
obj->task_state = target;
|
||||
|
||||
#if (CONFIG_SM_NESTING_NUM > 0)
|
||||
/* Prepare to execute all entry actions of the target's super states */
|
||||
|
||||
tmp_super[CONFIG_SM_NESTING_NUM - 1] =
|
||||
(sm_state)(uintptr_t)target(port, SUPER_SIG);
|
||||
|
||||
/* Get all super states of the target */
|
||||
for (i = CONFIG_SM_NESTING_NUM - 1; i > 0; i--) {
|
||||
if (tmp_super[i] != NULL)
|
||||
tmp_super[i - 1] =
|
||||
(sm_state)(uintptr_t)tmp_super[i](port, SUPER_SIG);
|
||||
else
|
||||
tmp_super[i - 1] = NULL;
|
||||
}
|
||||
|
||||
/* Get super state of last state */
|
||||
last_super = (sm_state)(uintptr_t)obj->last_state(port, SUPER_SIG);
|
||||
|
||||
/* Execute all super state entry actions in forward order */
|
||||
for (i = 0; i < CONFIG_SM_NESTING_NUM; i++) {
|
||||
/* No super state */
|
||||
if (tmp_super[i] == NULL)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We only want to execute the target state's super state entry
|
||||
* action if it doesn't share a super state with the previous
|
||||
* state.
|
||||
*/
|
||||
super = last_super;
|
||||
no_execute = 0;
|
||||
while (super != NULL) {
|
||||
if (tmp_super[i] == super) {
|
||||
no_execute = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get last state's next super state if it exists */
|
||||
super = (sm_state)(uintptr_t)super(port, SUPER_SIG);
|
||||
}
|
||||
|
||||
/* Execute super state's entry */
|
||||
if (!no_execute)
|
||||
tmp_super[i](port, ENTRY_SIG);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now execute the target entry action */
|
||||
target(port, ENTRY_SIG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void exe_state(int port, struct sm_obj *obj, enum signal sig)
|
||||
{
|
||||
#if (CONFIG_SM_NESTING_NUM > 0)
|
||||
sm_state state = obj->task_state;
|
||||
|
||||
do {
|
||||
state = (sm_state)(uintptr_t)state(port, sig);
|
||||
} while (state != NULL);
|
||||
#else
|
||||
obj->task_state(port, sig);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
/* 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 "battery.h"
|
||||
#include "battery_smart.h"
|
||||
#include "board.h"
|
||||
#include "charge_manager.h"
|
||||
#include "charge_state.h"
|
||||
#include "chipset.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "ec_commands.h"
|
||||
#include "gpio.h"
|
||||
#include "hooks.h"
|
||||
#include "host_command.h"
|
||||
#include "registers.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
#include "usb_charge.h"
|
||||
#include "usb_mux.h"
|
||||
#include "usb_pd.h"
|
||||
#include "usb_pd_tcpm.h"
|
||||
#include "usb_prl_sm.h"
|
||||
#include "tcpm.h"
|
||||
#include "usb_pe_sm.h"
|
||||
#include "usb_prl_sm.h"
|
||||
#include "usb_sm.h"
|
||||
#include "usb_tc_sm.h"
|
||||
#include "version.h"
|
||||
|
||||
#ifdef CONFIG_COMMON_RUNTIME
|
||||
#define CPRINTF(format, args...) cprintf(CC_HOOK, format, ## args)
|
||||
#define CPRINTS(format, args...) cprints(CC_HOOK, format, ## args)
|
||||
#else /* CONFIG_COMMON_RUNTIME */
|
||||
#define CPRINTF(format, args...)
|
||||
#define CPRINTS(format, args...)
|
||||
#endif
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
static inline int cc_is_rp(int cc);
|
||||
static inline enum pd_cc_polarity_type get_snk_polarity(int cc1, int cc2);
|
||||
static int tc_restart_tcpc(int port);
|
||||
static void set_polarity(int port, int polarity);
|
||||
|
||||
#ifdef CONFIG_COMMON_RUNTIME
|
||||
static const char * const tc_state_names[] = {
|
||||
"Disabled",
|
||||
"Unattached.SNK",
|
||||
"AttachWait.SNK",
|
||||
"Attached.SNK",
|
||||
#if !defined(CONFIG_USB_TYPEC_VPD)
|
||||
"ErrorRecovery",
|
||||
"Unattached.SRC",
|
||||
"AttachWait.SRC",
|
||||
"Attached.SRC",
|
||||
#endif
|
||||
#if !defined(CONFIG_USB_TYPEC_CTVPD) && !defined(CONFIG_USB_TYPEC_VPD)
|
||||
"AudioAccessory",
|
||||
"OrientedDebugAccessory.SRC",
|
||||
"UnorientedDebugAccessory.SRC",
|
||||
"DebugAccessory.SNK",
|
||||
"Try.SRC",
|
||||
"TryWait.SNK",
|
||||
"CTUnattached.SNK",
|
||||
"CTAttached.SNK",
|
||||
#endif
|
||||
#if defined(CONFIG_USB_TYPEC_CTVPD)
|
||||
"CTTry.SNK",
|
||||
"CTAttached.Unsupported",
|
||||
"CTAttachWait.Unsupported",
|
||||
"CTUnattached.Unsupported",
|
||||
"CTUnattached.VPD",
|
||||
"CTAttachWait.VPD",
|
||||
"CTAttached.VPD",
|
||||
"CTDisabled.VPD",
|
||||
"Try.SNK",
|
||||
"TryWait.SRC"
|
||||
#endif
|
||||
};
|
||||
BUILD_ASSERT(ARRAY_SIZE(tc_state_names) == TC_STATE_COUNT);
|
||||
#endif
|
||||
|
||||
/* Include USB Type-C State Machine */
|
||||
#if defined(CONFIG_USB_TYPEC_CTVPD)
|
||||
#include "usb_tc_ctvpd_sm.h"
|
||||
#elif defined(CONFIG_USB_TYPEC_VPD)
|
||||
#include "usb_tc_vpd_sm.h"
|
||||
#else
|
||||
#error "A USB Type-C State Machine must be defined."
|
||||
#endif
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
int tc_get_power_role(int port)
|
||||
{
|
||||
return tc[port].power_role;
|
||||
}
|
||||
|
||||
int tc_get_data_role(int port)
|
||||
{
|
||||
return tc[port].data_role;
|
||||
}
|
||||
|
||||
void tc_set_timeout(int port, uint64_t timeout)
|
||||
{
|
||||
tc[port].evt_timeout = timeout;
|
||||
}
|
||||
|
||||
enum typec_state_id get_typec_state_id(int port)
|
||||
{
|
||||
return tc[port].state_id;
|
||||
}
|
||||
|
||||
/* Private Functions */
|
||||
|
||||
/**
|
||||
* Returns whether the sink has detected a Rp resistor on the other side.
|
||||
*/
|
||||
static inline int cc_is_rp(int cc)
|
||||
{
|
||||
return (cc == TYPEC_CC_VOLT_RP_DEF) || (cc == TYPEC_CC_VOLT_RP_1_5) ||
|
||||
(cc == TYPEC_CC_VOLT_RP_3_0);
|
||||
}
|
||||
|
||||
/*
|
||||
* CC values for regular sources and Debug sources (aka DTS)
|
||||
*
|
||||
* Source type Mode of Operation CC1 CC2
|
||||
* ---------------------------------------------
|
||||
* Regular Default USB Power RpUSB Open
|
||||
* Regular USB-C @ 1.5 A Rp1A5 Open
|
||||
* Regular USB-C @ 3 A Rp3A0 Open
|
||||
* DTS Default USB Power Rp3A0 Rp1A5
|
||||
* DTS USB-C @ 1.5 A Rp1A5 RpUSB
|
||||
* DTS USB-C @ 3 A Rp3A0 RpUSB
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the polarity of a Sink.
|
||||
*/
|
||||
static inline enum pd_cc_polarity_type get_snk_polarity(int cc1, int cc2)
|
||||
{
|
||||
/* the following assumes:
|
||||
* TYPEC_CC_VOLT_RP_3_0 > TYPEC_CC_VOLT_RP_1_5
|
||||
* TYPEC_CC_VOLT_RP_1_5 > TYPEC_CC_VOLT_RP_DEF
|
||||
* TYPEC_CC_VOLT_RP_DEF > TYPEC_CC_VOLT_OPEN
|
||||
*/
|
||||
return (cc2 > cc1) ? POLARITY_CC2 : POLARITY_CC1;
|
||||
}
|
||||
|
||||
static int tc_restart_tcpc(int port)
|
||||
{
|
||||
return tcpm_init(port);
|
||||
}
|
||||
|
||||
static void set_polarity(int port, int polarity)
|
||||
{
|
||||
tcpm_set_polarity(port, polarity);
|
||||
#ifdef CONFIG_USBC_PPC_POLARITY
|
||||
ppc_set_polarity(port, polarity);
|
||||
#endif /* defined(CONFIG_USBC_PPC_POLARITY) */
|
||||
}
|
||||
|
||||
void pd_task(void *u)
|
||||
{
|
||||
int port = TASK_ID_TO_PD_PORT(task_get_current());
|
||||
|
||||
tc_state_init(port);
|
||||
|
||||
while (1) {
|
||||
/* wait for next event/packet or timeout expiration */
|
||||
tc[port].evt = task_wait_event(tc[port].evt_timeout);
|
||||
|
||||
/* handle events that affect the state machine as a whole */
|
||||
tc_event_check(port, tc[port].evt);
|
||||
|
||||
#ifdef CONFIG_USB_PD_TCPC
|
||||
/*
|
||||
* run port controller task to check CC and/or read incoming
|
||||
* messages
|
||||
*/
|
||||
tcpc_run(port, tc[port].evt);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_PE_SM
|
||||
/* run policy engine state machine */
|
||||
policy_engine(port, tc[port].evt, tc[port].pd_enable);
|
||||
#endif /* CONFIG_USB_PE_SM */
|
||||
|
||||
#ifdef CONFIG_USB_PRL_SM
|
||||
/* run protocol state machine */
|
||||
protocol_layer(port, tc[port].evt, tc[port].pd_enable);
|
||||
#endif /* CONFIG_USB_PRL_SM */
|
||||
|
||||
/* run state machine */
|
||||
exe_state(port, TC_OBJ(port), RUN_SIG);
|
||||
}
|
||||
}
|
|
@ -779,6 +779,33 @@
|
|||
*/
|
||||
#undef CONFIG_CHARGER_INPUT_CURRENT
|
||||
|
||||
/* Define to use Power Delivery State Machine Framework */
|
||||
#undef CONFIG_USB_SM_FRAMEWORK
|
||||
|
||||
/*
|
||||
* This is the maximum number of levels in the hierarchical
|
||||
* state machine framework. Set to 0 for a flat state machine.
|
||||
*/
|
||||
#define CONFIG_SM_NESTING_NUM 3
|
||||
|
||||
/*
|
||||
* Define to enable Type-C State Machine. Must be enabled
|
||||
* with CONFIG_USB_SM_FRAMEWORK
|
||||
*/
|
||||
#define CONFIG_USB_TYPEC_SM
|
||||
|
||||
/*
|
||||
* Define to enable Protocol Layer State Machine. Must be enabled
|
||||
* with CONFIG_USB_SM_FRAMEWORK and CONFIG_USB_TYPEC_SM
|
||||
*/
|
||||
#define CONFIG_USB_PRL_SM
|
||||
|
||||
/*
|
||||
* Define to enable Policy Engine State Machine. Must be enabled
|
||||
* with CONFIG_USB_SM_FRAMEWORK and CONFIG_USB_TYPEC_SM
|
||||
*/
|
||||
#define CONFIG_USB_PE_SM
|
||||
|
||||
/*
|
||||
* Board specific maximum input current limit, in mA.
|
||||
*/
|
||||
|
@ -3500,6 +3527,12 @@
|
|||
/* Use DAC as reference for comparator at 850mV. */
|
||||
#undef CONFIG_PD_USE_DAC_AS_REF
|
||||
|
||||
/* Type-C VCONN Powered Device */
|
||||
#undef CONFIG_USB_TYPEC_VPD
|
||||
|
||||
/* Type-C Charge Through VCONN Powered Device */
|
||||
#undef CONFIG_USB_TYPEC_CTVPD
|
||||
|
||||
/* USB Product ID. */
|
||||
#undef CONFIG_USB_PID
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/* USB Extended message buffer */
|
||||
|
||||
#ifndef __CROS_EC_USB_EBUF_H
|
||||
#define __CROS_EC_USB_EBUF_H
|
||||
|
||||
#define EXTENDED_BUFFER_SIZE 260
|
||||
#define BUFFER_SIZE 28
|
||||
|
||||
struct extended_msg {
|
||||
uint32_t header;
|
||||
uint32_t len;
|
||||
uint8_t buf[EXTENDED_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
/* Defined in usb_prl_sm.c */
|
||||
extern struct extended_msg emsg[CONFIG_USB_PD_PORT_COUNT];
|
||||
|
||||
#endif /* __CROS_EC_USB_EBUF_H */
|
|
@ -49,6 +49,7 @@ enum pd_rx_errors {
|
|||
#define PD_EVENT_DEVICE_ACCESSED (1<<7)
|
||||
#define PD_EVENT_POWER_STATE_CHANGE (1<<8) /* Chipset power state changed */
|
||||
#define PD_EVENT_SEND_HARD_RESET (1<<9) /* Issue a Hard Reset. */
|
||||
#define PD_EVENT_SM (1<<10) /* PD State machine event */
|
||||
|
||||
/* Ensure TCPC is out of low power mode before handling these events. */
|
||||
#define PD_EXIT_LOW_POWER_EVENT_MASK \
|
||||
|
@ -168,6 +169,7 @@ enum pd_rx_errors {
|
|||
#define PD_T_DRP_SNK (40*MSEC) /* toggle time for sink DRP */
|
||||
#define PD_T_DRP_SRC (30*MSEC) /* toggle time for source DRP */
|
||||
#define PD_T_DEBOUNCE (15*MSEC) /* between 10ms and 20ms */
|
||||
#define PD_T_TRY_CC_DEBOUNCE (15*MSEC) /* between 10ms and 20ms */
|
||||
#define PD_T_SINK_ADJ (55*MSEC) /* between PD_T_DEBOUNCE and 60ms */
|
||||
#define PD_T_SRC_RECOVER (760*MSEC) /* between 660ms and 1000ms */
|
||||
#define PD_T_SRC_RECOVER_MAX (1000*MSEC) /* 1000ms */
|
||||
|
@ -181,6 +183,10 @@ enum pd_rx_errors {
|
|||
#define PD_T_TRY_TIMEOUT (550*MSEC) /* between 550ms and 1100ms */
|
||||
#define PD_T_TRY_WAIT (600*MSEC) /* Max time for TryWait.SNK state */
|
||||
#define PD_T_SINK_REQUEST (100*MSEC) /* Wait 100ms before next request */
|
||||
#define PD_T_PD_DEBOUNCE (15*MSEC) /* between 10ms and 20ms */
|
||||
#define PD_T_CHUNK_SENDER_RESPONSE (25*MSEC) /* 25ms */
|
||||
#define PD_T_CHUNK_SENDER_REQUEST (25*MSEC) /* 25ms */
|
||||
#define PD_T_SWAP_SOURCE_START (25*MSEC) /* Min of 20ms */
|
||||
|
||||
/* number of edges and time window to detect CC line is not idle */
|
||||
#define PD_RX_TRANSITION_COUNT 3
|
||||
|
@ -196,6 +202,11 @@ enum pd_rx_errors {
|
|||
#define PD_T_VDM_SNDR_RSP (30*MSEC) /* max of 30ms */
|
||||
#define PD_T_VDM_WAIT_MODE_E (100*MSEC) /* enter/exit the same max */
|
||||
|
||||
/* CTVPD Timers ( USB Type-C ECN Table 4-27 ) */
|
||||
#define PD_T_VPDDETACH (20*MSEC) /* max of 20*MSEC */
|
||||
#define PD_T_VPDCTDD (4*MSEC) /* max of 4ms */
|
||||
#define PD_T_VPDDISABLE (25*MSEC) /* min of 25ms */
|
||||
|
||||
/* function table for entered mode */
|
||||
struct amode_fx {
|
||||
int (*status)(int port, uint32_t *payload);
|
||||
|
@ -391,6 +402,7 @@ struct pd_policy {
|
|||
#define IDH_PTYPE_PCABLE 3
|
||||
#define IDH_PTYPE_ACABLE 4
|
||||
#define IDH_PTYPE_AMA 5
|
||||
#define IDH_PTYPE_VPD 6
|
||||
|
||||
#define VDO_IDH(usbh, usbd, ptype, is_modal, vid) \
|
||||
((usbh) << 31 | (usbd) << 30 | ((ptype) & 0x7) << 27 \
|
||||
|
@ -490,6 +502,34 @@ struct pd_policy {
|
|||
#define AMA_USBSS_U31_GEN2 2
|
||||
#define AMA_USBSS_BBONLY 3
|
||||
|
||||
/*
|
||||
* VPD VDO
|
||||
* ---------
|
||||
* <31:28> :: HW version
|
||||
* <27:24> :: FW version
|
||||
* <23:21> :: VDO version
|
||||
* <20:17> :: SBZ
|
||||
* <16:15> :: Maximum VBUS Voltage
|
||||
* <14:13> :: SBZ
|
||||
* <12:7> :: VBUS Impedance
|
||||
* <6:1> :: Ground Impedance
|
||||
* <0> :: Charge Through Support
|
||||
*/
|
||||
#define VDO_VPD(hw, fw, vbus, vbusz, gndz, cts) \
|
||||
(((hw) & 0xf) << 28 | ((fw) & 0xf) << 24 \
|
||||
| ((vbus) & 0x3) << 15 \
|
||||
| ((vbusz) & 0x3f) << 7 \
|
||||
| ((gndz) & 0x3f) << 1 | (cts))
|
||||
|
||||
#define VPD_MAX_VBUS_20V 0
|
||||
#define VPD_MAX_VBUS_30V 1
|
||||
#define VPD_MAX_VBUS_40V 2
|
||||
#define VPD_MAX_VBUS_50V 3
|
||||
#define VPD_VBUS_IMP(mo) ((mo + 1) >> 1)
|
||||
#define VPD_GND_IMP(mo) (mo)
|
||||
#define VPD_CTS_SUPPORTED 1
|
||||
#define VPD_CTS_NOT_SUPPORTED 0
|
||||
|
||||
/*
|
||||
* SVDM Discover SVIDs request -> response
|
||||
*
|
||||
|
@ -787,6 +827,9 @@ enum pd_states {
|
|||
#define PD_BBRMFLG_DATA_ROLE BIT(2)
|
||||
#define PD_BBRMFLG_VCONN_ROLE BIT(3)
|
||||
|
||||
/* Initial value for CC debounce variable */
|
||||
#define PD_CC_UNSET -1
|
||||
|
||||
enum pd_cc_states {
|
||||
PD_CC_NONE,
|
||||
|
||||
|
@ -912,14 +955,25 @@ enum pd_data_msg_type {
|
|||
PD_DATA_VENDOR_DEF = 15,
|
||||
};
|
||||
|
||||
/* CC Polarity type */
|
||||
enum pd_cc_polarity_type {
|
||||
POLARITY_CC1,
|
||||
POLARITY_CC2
|
||||
};
|
||||
|
||||
/* Protocol revision */
|
||||
#define PD_REV10 0
|
||||
#define PD_REV20 1
|
||||
#define PD_REV30 2
|
||||
enum pd_rev_type {
|
||||
PD_REV10,
|
||||
PD_REV20,
|
||||
PD_REV30
|
||||
};
|
||||
|
||||
/* Power role */
|
||||
#define PD_ROLE_SINK 0
|
||||
#define PD_ROLE_SOURCE 1
|
||||
/* Cable plug */
|
||||
#define PD_PLUG_DFP_UFP 0
|
||||
#define PD_PLUG_CABLE_VPD 1
|
||||
/* Data role */
|
||||
#define PD_ROLE_UFP 0
|
||||
#define PD_ROLE_DFP 1
|
||||
|
@ -998,6 +1052,9 @@ enum pd_data_msg_type {
|
|||
#define PD_EXT_HEADER_REQ_CHUNK(header) (((header) >> 10) & 1)
|
||||
#define PD_EXT_HEADER_DATA_SIZE(header) ((header) & 0x1ff)
|
||||
|
||||
/* Used to get extended header from the first 32-bit word of the message */
|
||||
#define GET_EXT_HEADER(msg) (msg & 0xffff)
|
||||
|
||||
/* K-codes for special symbols */
|
||||
#define PD_SYNC1 0x18
|
||||
#define PD_SYNC2 0x11
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
/* Time to wait for TCPC to complete transmit */
|
||||
#define PD_T_TCPC_TX_TIMEOUT (100*MSEC)
|
||||
|
||||
/* Number of valid Transmit Types */
|
||||
#define NUM_XMIT_TYPES (TCPC_TX_SOP_DEBUG_PRIME_PRIME + 1)
|
||||
|
||||
/* Detected resistor values of port partner */
|
||||
enum tcpc_cc_voltage_status {
|
||||
TYPEC_CC_VOLT_OPEN = 0,
|
||||
|
@ -32,6 +35,7 @@ enum tcpc_cc_pull {
|
|||
TYPEC_CC_RP = 1,
|
||||
TYPEC_CC_RD = 2,
|
||||
TYPEC_CC_OPEN = 3,
|
||||
TYPEC_CC_RA_RD = 4, /* Powered cable with Sink */
|
||||
};
|
||||
|
||||
/* Pull-up values we apply as a SRC to advertise different current limits */
|
||||
|
@ -54,6 +58,7 @@ enum tcpm_transmit_type {
|
|||
};
|
||||
|
||||
enum tcpc_transmit_complete {
|
||||
TCPC_TX_UNSET = -1,
|
||||
TCPC_TX_COMPLETE_SUCCESS = 0,
|
||||
TCPC_TX_COMPLETE_DISCARDED = 1,
|
||||
TCPC_TX_COMPLETE_FAILED = 2,
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
/* 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 "common.h"
|
||||
#include "console.h"
|
||||
#include "task.h"
|
||||
#include "util.h"
|
||||
#include "usb_pd.h"
|
||||
#include "usb_pd_tcpm.h"
|
||||
#include "usb_pe_sm.h"
|
||||
#include "usb_prl_sm.h"
|
||||
#include "usb_tc_sm.h"
|
||||
#include "usb_emsg.h"
|
||||
#include "usb_sm.h"
|
||||
|
||||
/* USB Policy Engine Charge-Through VCONN Powered Device module */
|
||||
|
||||
#ifndef __CROS_EC_USB_PE_CTVPD_H
|
||||
#define __CROS_EC_USB_PE_CTVPD_H
|
||||
|
||||
/* Policy Engine Flags */
|
||||
#define PE_FLAGS_MSG_RECEIVED (1 << 0)
|
||||
|
||||
enum l_state {
|
||||
PE_INIT,
|
||||
PE_RUN,
|
||||
PE_PAUSED
|
||||
};
|
||||
|
||||
static enum l_state local_state = PE_INIT;
|
||||
|
||||
/*
|
||||
* PE_OBJ is a convenience macro to access struct sm_obj, which
|
||||
* must be the first member of struct policy_engine.
|
||||
*/
|
||||
#define PE_OBJ(port) (SM_OBJ(pe[port]))
|
||||
|
||||
/**
|
||||
* This is the PE Port object that contains information needed to
|
||||
* implement a VCONN and Charge-Through VCONN Powered Device.
|
||||
*/
|
||||
static struct policy_engine {
|
||||
/*
|
||||
* struct sm_obj must be first. This is the state machine
|
||||
* object that keeps track of the current and last state
|
||||
* of the state machine.
|
||||
*/
|
||||
struct sm_obj obj;
|
||||
/* port flags, see PE_FLAGS_* */
|
||||
uint32_t flags;
|
||||
} pe[CONFIG_USB_PD_PORT_COUNT];
|
||||
|
||||
static unsigned int pe_request(int port, enum signal sig);
|
||||
static unsigned int pe_request_entry(int port);
|
||||
static unsigned int pe_request_run(int port);
|
||||
|
||||
static unsigned int do_nothing_exit(int port);
|
||||
static unsigned int get_super_state(int port);
|
||||
|
||||
static const state_sig pe_request_sig[] = {
|
||||
pe_request_entry,
|
||||
pe_request_run,
|
||||
do_nothing_exit,
|
||||
get_super_state
|
||||
};
|
||||
|
||||
void pe_init(int port)
|
||||
{
|
||||
pe[port].flags = 0;
|
||||
init_state(port, PE_OBJ(port), pe_request);
|
||||
}
|
||||
|
||||
void policy_engine(int port, int evt, int en)
|
||||
{
|
||||
switch (local_state) {
|
||||
case PE_INIT:
|
||||
pe_init(port);
|
||||
local_state = PE_RUN;
|
||||
/* fall through */
|
||||
case PE_RUN:
|
||||
if (!en) {
|
||||
local_state = PE_PAUSED;
|
||||
break;
|
||||
}
|
||||
|
||||
exe_state(port, PE_OBJ(port), RUN_SIG);
|
||||
break;
|
||||
case PE_PAUSED:
|
||||
if (en)
|
||||
local_state = PE_INIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void pe_pass_up_message(int port)
|
||||
{
|
||||
pe[port].flags |= PE_FLAGS_MSG_RECEIVED;
|
||||
task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
|
||||
}
|
||||
|
||||
void pe_hard_reset_sent(int port)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
void pe_got_hard_reset(int port)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
void pe_report_error(int port, enum pe_error e)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
void pe_got_soft_reset(int port)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
void pe_message_sent(int port)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static unsigned int pe_request(int port, enum signal sig)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = (*pe_request_sig[sig])(port);
|
||||
return SUPER(ret, sig, 0);
|
||||
}
|
||||
|
||||
static unsigned int pe_request_entry(int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int pe_request_run(int port)
|
||||
{
|
||||
uint32_t *payload = (uint32_t *)emsg[port].buf;
|
||||
uint32_t header = emsg[port].header;
|
||||
uint32_t vdo = payload[0];
|
||||
|
||||
if (pe[port].flags & PE_FLAGS_MSG_RECEIVED) {
|
||||
pe[port].flags &= ~PE_FLAGS_MSG_RECEIVED;
|
||||
|
||||
/*
|
||||
* Only support Structured VDM Discovery
|
||||
* Identity message
|
||||
*/
|
||||
|
||||
if (PD_HEADER_TYPE(header) != PD_DATA_VENDOR_DEF)
|
||||
return 0;
|
||||
|
||||
if (PD_HEADER_CNT(header) == 0)
|
||||
return 0;
|
||||
|
||||
if (!PD_VDO_SVDM(vdo))
|
||||
return 0;
|
||||
|
||||
if (PD_VDO_CMD(vdo) != CMD_DISCOVER_IDENT)
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_USB_TYPEC_CTVPD
|
||||
/*
|
||||
* We have a valid DISCOVER IDENTITY message.
|
||||
* Attempt to reset support timer
|
||||
*/
|
||||
tc_reset_support_timer(port);
|
||||
#endif
|
||||
/* Prepare to send ACK */
|
||||
|
||||
/* VDM Header */
|
||||
payload[0] = VDO(
|
||||
USB_VID_GOOGLE,
|
||||
1, /* Structured VDM */
|
||||
VDO_SVDM_VERS(1) |
|
||||
VDO_CMDT(CMDT_RSP_ACK) |
|
||||
CMD_DISCOVER_IDENT);
|
||||
|
||||
/* ID Header VDO */
|
||||
payload[1] = VDO_IDH(
|
||||
0, /* Not a USB Host */
|
||||
1, /* Capable of being enumerated as USB Device */
|
||||
IDH_PTYPE_VPD,
|
||||
0, /* Modal Operation Not Supported */
|
||||
USB_VID_GOOGLE);
|
||||
|
||||
/* Cert State VDO */
|
||||
payload[2] = 0;
|
||||
|
||||
/* Product VDO */
|
||||
payload[3] = VDO_PRODUCT(
|
||||
CONFIG_USB_PID,
|
||||
USB_BCD_DEVICE);
|
||||
|
||||
/* VPD VDO */
|
||||
payload[4] = VDO_VPD(
|
||||
VPD_HW_VERSION,
|
||||
VPD_FW_VERSION,
|
||||
VPD_MAX_VBUS_20V,
|
||||
VPD_VBUS_IMP(VPD_VBUS_IMPEDANCE),
|
||||
VPD_GND_IMP(VPD_GND_IMPEDANCE),
|
||||
#ifdef CONFIG_USB_TYPEC_CTVPD
|
||||
VPD_CTS_SUPPORTED
|
||||
#else
|
||||
VPD_CTS_NOT_SUPPORTED
|
||||
#endif
|
||||
);
|
||||
|
||||
/* 20 bytes, 5 data objects */
|
||||
emsg[port].len = 20;
|
||||
|
||||
/* Set to highest revision supported by both ports. */
|
||||
prl_set_rev(port, (PD_HEADER_REV(header) > PD_REV30) ?
|
||||
PD_REV30 : PD_HEADER_REV(header));
|
||||
|
||||
/* Send the ACK */
|
||||
prl_send_data_msg(port, TCPC_TX_SOP_PRIME,
|
||||
PD_DATA_VENDOR_DEF);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int do_nothing_exit(int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int get_super_state(int port)
|
||||
{
|
||||
return RUN_SUPER;
|
||||
}
|
||||
|
||||
#endif /* __CROS_EC_USB_PE_CTVPD_H */
|
|
@ -0,0 +1,79 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/* USB Policy Engine module */
|
||||
|
||||
#ifndef __CROS_EC_USB_PE_H
|
||||
#define __CROS_EC_USB_PE_H
|
||||
|
||||
enum pe_error {
|
||||
ERR_RCH_CHUNKED,
|
||||
ERR_RCH_MSG_REC,
|
||||
ERR_TCH_CHUNKED,
|
||||
ERR_TCH_XMIT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the Policy Engine State Machine
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void pe_init(int port);
|
||||
|
||||
/**
|
||||
* Runs the Policy Engine State Machine
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param evt system event, ie: PD_EVENT_RX
|
||||
* @param en 0 to disable the machine, 1 to enable the machine
|
||||
*/
|
||||
void policy_engine(int port, int evt, int en);
|
||||
|
||||
/**
|
||||
* Informs the Policy Engine that a message was successfully sent
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void pe_message_sent(int port);
|
||||
|
||||
/**
|
||||
* Informs the Policy Engine of an error.
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @parm e error
|
||||
*/
|
||||
void pe_report_error(int port, enum pe_error e);
|
||||
|
||||
/**
|
||||
* Informs the Policy Engine that a message has been received
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @parm e error
|
||||
*/
|
||||
void pe_pass_up_message(int port);
|
||||
|
||||
/**
|
||||
* Informs the Policy Engine that a hard reset was received.
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void pe_got_hard_reset(int port);
|
||||
|
||||
/**
|
||||
* Informs the Policy Engine that a soft reset was received.
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void pe_got_soft_reset(int port);
|
||||
|
||||
/**
|
||||
* Informs the Policy Engine that a hard reset was sent.
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void pe_hard_reset_sent(int port);
|
||||
|
||||
#endif /* __CROS_EC_USB_PE_H */
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/* USB Protocol Layer module */
|
||||
|
||||
#ifndef __CROS_EC_USB_PRL_H
|
||||
#define __CROS_EC_USB_PRL_H
|
||||
#include "common.h"
|
||||
#include "usb_pd.h"
|
||||
#include "usb_pd_tcpm.h"
|
||||
|
||||
enum prl_tx_state_id {
|
||||
PRL_TX_PHY_LAYER_RESET,
|
||||
PRL_TX_WAIT_FOR_MESSAGE_REQUEST,
|
||||
PRL_TX_LAYER_RESET_FOR_TRANSMIT,
|
||||
PRL_TX_CONSTRUCT_MESSAGE,
|
||||
PRL_TX_WAIT_FOR_PHY_RESPONSE,
|
||||
PRL_TX_MATCH_MESSAGE_ID,
|
||||
PRL_TX_MESSAGE_SENT,
|
||||
PRL_TX_CHECK_RETRY_COUNTER,
|
||||
PRL_TX_TRANSMISSION_ERROR,
|
||||
PRL_TX_DISCARD_MESSAGE,
|
||||
|
||||
PRL_TX_SRC_SINK_TX,
|
||||
PRL_TX_SRC_SOURCE_TX,
|
||||
PRL_TX_SRC_PENDING,
|
||||
|
||||
PRL_TX_SNK_START_OF_AMS,
|
||||
PRL_TX_SNK_PENDING,
|
||||
};
|
||||
|
||||
enum prl_hr_state_id {
|
||||
PRL_HR_WAIT_FOR_REQUEST,
|
||||
PRL_HR_RESET_LAYER,
|
||||
PRL_HR_INDICATE_HARD_RESET,
|
||||
PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE,
|
||||
PRL_HR_PHY_HARD_RESET_REQUESTED,
|
||||
PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE,
|
||||
PRL_HR_PE_HARD_RESET_COMPLETE,
|
||||
};
|
||||
|
||||
enum rch_state_id {
|
||||
RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER,
|
||||
RCH_PASS_UP_MESSAGE,
|
||||
RCH_PROCESSING_EXTENDED_MESSAGE,
|
||||
RCH_REQUESTING_CHUNK,
|
||||
RCH_WAITING_CHUNK,
|
||||
RCH_REPORT_ERROR,
|
||||
};
|
||||
|
||||
enum tch_state_id {
|
||||
TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE,
|
||||
TCH_PASS_DOWN_MESSAGE,
|
||||
TCH_WAIT_FOR_TRANSMISSION_COMPLETE,
|
||||
TCH_MESSAGE_SENT,
|
||||
TCH_PREPARE_TO_SEND_CHUNKED_MESSAGE,
|
||||
TCH_CONSTRUCT_CHUNKED_MESSAGE,
|
||||
TCH_SENDING_CHUNKED_MESSAGE,
|
||||
TCH_WAIT_CHUNK_REQUEST,
|
||||
TCH_MESSAGE_RECEIVED,
|
||||
TCH_REPORT_ERROR,
|
||||
};
|
||||
|
||||
/*
|
||||
* Number of times the Protocol Layer will try to transmit a message
|
||||
* before giving up and signaling an error
|
||||
*/
|
||||
#define N_RETRY_COUNT 2
|
||||
|
||||
/**
|
||||
* Initialize the Protocol Layer State Machine
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void prl_init(int port);
|
||||
|
||||
/**
|
||||
* Resets the Protocol Layer State Machine
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void prl_reset(int port);
|
||||
|
||||
/**
|
||||
* Get Chunked Rx State Machine state id
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @return id
|
||||
*/
|
||||
enum rch_state_id get_rch_state_id(int port);
|
||||
|
||||
/**
|
||||
* Get Chunked Tx State Machine state id
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @return id
|
||||
*/
|
||||
enum tch_state_id get_tch_state_id(int port);
|
||||
|
||||
/**
|
||||
* Get Message Transmission State Machine state id
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @return id
|
||||
*/
|
||||
enum prl_tx_state_id get_prl_tx_state_id(int port);
|
||||
|
||||
/**
|
||||
* Get Hard Reset State Machine state id
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @return id
|
||||
*/
|
||||
enum prl_hr_state_id get_prl_hr_state_id(int port);
|
||||
|
||||
/**
|
||||
* Returns the state of the PRL state machine
|
||||
* @return SM_INIT for initializing
|
||||
* SM_RUN for running
|
||||
* SM_PAUSED for paused
|
||||
*/
|
||||
enum sm_local_state prl_get_local_state(int port);
|
||||
|
||||
/**
|
||||
* Runs the Protocol Layer State Machine
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param evt system event, ie: PD_EVENT_RX
|
||||
* @param en 0 to disable the machine, 1 to enable the machine
|
||||
*/
|
||||
void protocol_layer(int port, int evt, int en);
|
||||
|
||||
/**
|
||||
* Set the PD revision
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param rev revision
|
||||
*/
|
||||
void prl_set_rev(int port, enum pd_rev_type rev);
|
||||
|
||||
/**
|
||||
* Get the PD revision
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @return pd rev
|
||||
*/
|
||||
enum pd_rev_type prl_get_rev(int port);
|
||||
|
||||
/**
|
||||
* Sends a PD control message
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param type Transmit type
|
||||
* @param msg Control message type
|
||||
* @return 0 on EC_SUCCESS, else EC_ERROR_BUSY
|
||||
*/
|
||||
void prl_send_ctrl_msg(int port, enum tcpm_transmit_type type,
|
||||
enum pd_ctrl_msg_type msg);
|
||||
|
||||
/**
|
||||
* Sends a PD data message
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param type Transmit type
|
||||
* @param msg Data message type
|
||||
* @return 0 on EC_SUCCESS, else EC_ERROR_BUSY
|
||||
*/
|
||||
void prl_send_data_msg(int port, enum tcpm_transmit_type type,
|
||||
enum pd_data_msg_type msg);
|
||||
|
||||
/**
|
||||
* Sends a PD extended data message
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param type Transmit type
|
||||
* @param msg Extended data message type
|
||||
* @return 0 on EC_SUCCESS, else EC_ERROR_BUSY
|
||||
*/
|
||||
void prl_send_ext_data_msg(int port, enum tcpm_transmit_type type,
|
||||
enum pd_ext_msg_type msg);
|
||||
|
||||
/**
|
||||
* Informs the Protocol Layer that a hard reset has completed
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void prl_hard_reset_complete(int port);
|
||||
|
||||
/**
|
||||
* Policy Engine calls this function to execute a hard reset.
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void prl_execute_hard_reset(int port);
|
||||
|
||||
/**
|
||||
* Informs the Protocol Layer to start an Atomic Message Sequence
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void prl_start_ams(int port);
|
||||
|
||||
/**
|
||||
* Informs the Protocol Layer to end an Atomic Message Sequence
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void prl_end_ams(int port);
|
||||
|
||||
#endif /* __CROS_EC_USB_PRL_H */
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/* USB State Machine Framework */
|
||||
|
||||
#ifndef __CROS_EC_USB_SM_H
|
||||
#define __CROS_EC_USB_SM_H
|
||||
|
||||
#define SM_OBJ(smo) ((struct sm_obj *)&smo)
|
||||
#define SUPER(r, sig, s) ((((r) == 0) || ((sig) == ENTRY_SIG) || \
|
||||
((sig) == EXIT_SIG)) ? 0 : ((uintptr_t)(s)))
|
||||
#define RUN_SUPER 1
|
||||
|
||||
/* Local state machine states */
|
||||
enum sm_local_state {
|
||||
SM_INIT,
|
||||
SM_RUN,
|
||||
SM_PAUSED
|
||||
};
|
||||
|
||||
/* State Machine signals */
|
||||
enum signal {
|
||||
ENTRY_SIG = 0,
|
||||
RUN_SIG,
|
||||
EXIT_SIG,
|
||||
SUPER_SIG,
|
||||
};
|
||||
|
||||
typedef unsigned int (*state_sig)(int port);
|
||||
typedef unsigned int (*sm_state)(int port, enum signal sig);
|
||||
|
||||
struct sm_obj {
|
||||
sm_state task_state;
|
||||
sm_state last_state;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize a State Machine
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param obj State machine object
|
||||
* @param target Initial state of state machine
|
||||
*/
|
||||
void init_state(int port, struct sm_obj *obj, sm_state target);
|
||||
|
||||
/**
|
||||
* Changes a state machines state
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param obj State machine object
|
||||
* @param target State to transition to
|
||||
* @return 0
|
||||
*/
|
||||
int set_state(int port, struct sm_obj *obj, sm_state target);
|
||||
|
||||
/**
|
||||
* Executes a state machine
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param obj State machine object
|
||||
* @param sig State machine signal
|
||||
*/
|
||||
void exe_state(int port, struct sm_obj *obj, enum signal sig);
|
||||
|
||||
#endif /* __CROS_EC_USB_SM_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,91 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/* USB Type-C module */
|
||||
|
||||
#ifndef __CROS_EC_USB_TC_H
|
||||
#define __CROS_EC_USB_TC_H
|
||||
|
||||
enum typec_state_id {
|
||||
DISABLED,
|
||||
UNATTACHED_SNK,
|
||||
ATTACH_WAIT_SNK,
|
||||
ATTACHED_SNK,
|
||||
#if !defined(CONFIG_USB_TYPEC_VPD)
|
||||
ERROR_RECOVERY,
|
||||
UNATTACHED_SRC,
|
||||
ATTACH_WAIT_SRC,
|
||||
ATTACHED_SRC,
|
||||
#endif
|
||||
#if !defined(CONFIG_USB_TYPEC_CTVPD) && !defined(CONFIG_USB_TYPEC_VPD)
|
||||
AUDIO_ACCESSORY,
|
||||
ORIENTED_DEBUG_ACCESSORY_SRC,
|
||||
UNORIENTED_DEBUG_ACCESSORY_SRC,
|
||||
DEBUG_ACCESSORY_SNK,
|
||||
TRY_SRC,
|
||||
TRY_WAIT_SNK,
|
||||
CTUNATTACHED_SNK,
|
||||
CTATTACHED_SNK,
|
||||
#endif
|
||||
#if defined(CONFIG_USB_TYPEC_CTVPD)
|
||||
CTTRY_SNK,
|
||||
CTATTACHED_UNSUPPORTED,
|
||||
CTATTACH_WAIT_UNSUPPORTED,
|
||||
CTUNATTACHED_UNSUPPORTED,
|
||||
CTUNATTACHED_VPD,
|
||||
CTATTACH_WAIT_VPD,
|
||||
CTATTACHED_VPD,
|
||||
CTDISABLED_VPD,
|
||||
TRY_SNK,
|
||||
TRY_WAIT_SRC,
|
||||
#endif
|
||||
/* Number of states. Not an actual state. */
|
||||
TC_STATE_COUNT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the id of the current Type-C state
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
enum typec_state_id get_typec_state_id(int port);
|
||||
|
||||
/**
|
||||
* Get current data role
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @return 0 for ufp, 1 for dfp, 2 for disconnected
|
||||
*/
|
||||
int tc_get_data_role(int port);
|
||||
|
||||
/**
|
||||
* Get current power role
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @return 0 for sink, 1 for source or vpd
|
||||
*/
|
||||
int tc_get_power_role(int port);
|
||||
|
||||
/**
|
||||
* Set loop timeout value
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @timeout time in ms
|
||||
*/
|
||||
void tc_set_timeout(int port, uint64_t timeout);
|
||||
|
||||
#ifdef CONFIG_USB_TYPEC_CTVPD
|
||||
/**
|
||||
* Resets the charge-through support timer. This can be
|
||||
* called many times but the support timer will only
|
||||
* reset once, while in the Attached.SNK state.
|
||||
*
|
||||
* @param port USB-C port number
|
||||
*/
|
||||
void tc_reset_support_timer(int port);
|
||||
|
||||
#endif /* CONFIG_USB_TYPEC_CTVPD */
|
||||
#endif /* __CROS_EC_USB_TC_H */
|
||||
|
|
@ -0,0 +1,486 @@
|
|||
/* 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 "vpd_api.h"
|
||||
|
||||
/* USB Type-C VCONN Powered Device module */
|
||||
|
||||
#ifndef __CROS_EC_USB_TC_VPD_H
|
||||
#define __CROS_EC_USB_TC_VPD_H
|
||||
|
||||
/* Type-C Layer Flags */
|
||||
#define TC_FLAGS_VCONN_ON BIT(0)
|
||||
|
||||
#undef PD_DEFAULT_STATE
|
||||
/* Port default state at startup */
|
||||
#define PD_DEFAULT_STATE(port) tc_state_unattached_snk
|
||||
|
||||
/*
|
||||
* TC_OBJ is a convenience macro to access struct sm_obj, which
|
||||
* must be the first member of struct type_c.
|
||||
*/
|
||||
#define TC_OBJ(port) (SM_OBJ(tc[port]))
|
||||
|
||||
/**
|
||||
* This is the Type-C Port object that contains information needed to
|
||||
* implement a VCONN Powered Device.
|
||||
*/
|
||||
static struct type_c {
|
||||
/*
|
||||
* struct sm_obj must be first. This is the state machine
|
||||
* object that keeps track of the current and last state
|
||||
* of the state machine.
|
||||
*/
|
||||
struct sm_obj obj;
|
||||
/* state id */
|
||||
enum typec_state_id state_id;
|
||||
/* current port power role (VPD, SOURCE or SINK) */
|
||||
uint8_t power_role;
|
||||
/* current port data role (DFP or UFP) */
|
||||
uint8_t data_role;
|
||||
/* bool: enable power delivery state machines */
|
||||
uint8_t pd_enable;
|
||||
/* event timeout */
|
||||
uint64_t evt_timeout;
|
||||
/* state machine event */
|
||||
int evt;
|
||||
/* port flags, see TC_FLAGS_* */
|
||||
uint32_t flags;
|
||||
/* Time a port shall wait before it can determine it is attached */
|
||||
uint64_t cc_debounce;
|
||||
/* VPD host port cc state */
|
||||
enum pd_cc_states host_cc_state;
|
||||
uint8_t ct_cc;
|
||||
} tc[CONFIG_USB_PD_PORT_COUNT];
|
||||
|
||||
/* Type-C states */
|
||||
static unsigned int tc_state_disabled(int port, enum signal sig);
|
||||
static unsigned int tc_state_disabled_entry(int port);
|
||||
static unsigned int tc_state_disabled_run(int port);
|
||||
static unsigned int tc_state_disabled_exit(int port);
|
||||
|
||||
static unsigned int tc_state_unattached_snk(int port, enum signal sig);
|
||||
static unsigned int tc_state_unattached_snk_entry(int port);
|
||||
static unsigned int tc_state_unattached_snk_run(int port);
|
||||
static unsigned int tc_state_unattached_snk_exit(int port);
|
||||
|
||||
static unsigned int tc_state_attach_wait_snk(int port, enum signal sig);
|
||||
static unsigned int tc_state_attach_wait_snk_entry(int port);
|
||||
static unsigned int tc_state_attach_wait_snk_run(int port);
|
||||
static unsigned int tc_state_attach_wait_snk_exit(int port);
|
||||
|
||||
static unsigned int tc_state_attached_snk(int port, enum signal sig);
|
||||
static unsigned int tc_state_attached_snk_entry(int port);
|
||||
static unsigned int tc_state_attached_snk_run(int port);
|
||||
static unsigned int tc_state_attached_snk_exit(int port);
|
||||
|
||||
/* Super States */
|
||||
static unsigned int tc_state_host_rard(int port, enum signal sig);
|
||||
static unsigned int tc_state_host_rard_entry(int port);
|
||||
static unsigned int tc_state_host_rard_run(int port);
|
||||
static unsigned int tc_state_host_rard_exit(int port);
|
||||
|
||||
static unsigned int tc_state_host_open(int port, enum signal sig);
|
||||
static unsigned int tc_state_host_open_entry(int port);
|
||||
static unsigned int tc_state_host_open_run(int port);
|
||||
static unsigned int tc_state_host_open_exit(int port);
|
||||
|
||||
static unsigned int tc_state_vbus_cc_iso(int port, enum signal sig);
|
||||
static unsigned int tc_state_vbus_cc_iso_entry(int port);
|
||||
static unsigned int tc_state_vbus_cc_iso_run(int port);
|
||||
static unsigned int tc_state_vbus_cc_iso_exit(int port);
|
||||
|
||||
static unsigned int get_super_state(int port);
|
||||
|
||||
static const state_sig tc_state_disabled_sig[] = {
|
||||
tc_state_disabled_entry,
|
||||
tc_state_disabled_run,
|
||||
tc_state_disabled_exit,
|
||||
get_super_state
|
||||
};
|
||||
|
||||
static const state_sig tc_state_unattached_snk_sig[] = {
|
||||
tc_state_unattached_snk_entry,
|
||||
tc_state_unattached_snk_run,
|
||||
tc_state_unattached_snk_exit,
|
||||
get_super_state
|
||||
};
|
||||
|
||||
static const state_sig tc_state_attach_wait_snk_sig[] = {
|
||||
tc_state_attach_wait_snk_entry,
|
||||
tc_state_attach_wait_snk_run,
|
||||
tc_state_attach_wait_snk_exit,
|
||||
get_super_state
|
||||
};
|
||||
|
||||
static const state_sig tc_state_attached_snk_sig[] = {
|
||||
tc_state_attached_snk_entry,
|
||||
tc_state_attached_snk_run,
|
||||
tc_state_attached_snk_exit,
|
||||
get_super_state
|
||||
};
|
||||
|
||||
static const state_sig tc_state_host_rard_sig[] = {
|
||||
tc_state_host_rard_entry,
|
||||
tc_state_host_rard_run,
|
||||
tc_state_host_rard_exit,
|
||||
get_super_state
|
||||
};
|
||||
|
||||
static const state_sig tc_state_host_open_sig[] = {
|
||||
tc_state_host_open_entry,
|
||||
tc_state_host_open_run,
|
||||
tc_state_host_open_exit,
|
||||
get_super_state
|
||||
};
|
||||
|
||||
static const state_sig tc_state_vbus_cc_iso_sig[] = {
|
||||
tc_state_vbus_cc_iso_entry,
|
||||
tc_state_vbus_cc_iso_run,
|
||||
tc_state_vbus_cc_iso_exit,
|
||||
get_super_state
|
||||
};
|
||||
|
||||
static void tc_state_init(int port)
|
||||
{
|
||||
int res = 0;
|
||||
sm_state this_state;
|
||||
|
||||
res = tc_restart_tcpc(port);
|
||||
|
||||
CPRINTS("TCPC p%d init %s", port, res ? "failed" : "ready");
|
||||
this_state = res ? tc_state_disabled : PD_DEFAULT_STATE(port);
|
||||
|
||||
/* Disable TCPC RX until connection is established */
|
||||
tcpm_set_rx_enable(port, 0);
|
||||
|
||||
init_state(port, TC_OBJ(port), this_state);
|
||||
|
||||
/* Disable pd state machines */
|
||||
tc[port].pd_enable = 0;
|
||||
tc[port].evt_timeout = 10*MSEC;
|
||||
tc[port].power_role = PD_PLUG_CABLE_VPD;
|
||||
tc[port].data_role = 0; /* Reserved for VPD */
|
||||
tc[port].flags = 0;
|
||||
}
|
||||
|
||||
static void tc_event_check(int port, int evt)
|
||||
{
|
||||
/* Do Nothing */
|
||||
}
|
||||
|
||||
/**
|
||||
* Disabled
|
||||
*
|
||||
* Super State Entries:
|
||||
* Enable mcu communication
|
||||
* Remove the terminations from Host CC
|
||||
*/
|
||||
static unsigned int tc_state_disabled(int port, enum signal sig)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = (*tc_state_disabled_sig[sig])(port);
|
||||
return SUPER(ret, sig, tc_state_host_open);
|
||||
}
|
||||
|
||||
static unsigned int tc_state_disabled_entry(int port)
|
||||
{
|
||||
tc[port].state_id = DISABLED;
|
||||
CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_disabled_run(int port)
|
||||
{
|
||||
task_wait_event(-1);
|
||||
|
||||
return RUN_SUPER;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_disabled_exit(int port)
|
||||
{
|
||||
#ifndef CONFIG_USB_PD_TCPC
|
||||
if (tc_restart_tcpc(port) != 0) {
|
||||
CPRINTS("TCPC p%d restart failed!", port);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
CPRINTS("TCPC p%d resumed!", port);
|
||||
set_state(port, TC_OBJ(port), tc_state_unattached_snk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unattached.SNK
|
||||
*
|
||||
* Super State Entry:
|
||||
* Enable mcu communication
|
||||
* Place Ra on VCONN and Rd on Host CC
|
||||
*/
|
||||
static unsigned int tc_state_unattached_snk(int port, enum signal sig)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = (*tc_state_unattached_snk_sig[sig])(port);
|
||||
return SUPER(ret, sig, tc_state_host_rard);
|
||||
}
|
||||
|
||||
static unsigned int tc_state_unattached_snk_entry(int port)
|
||||
{
|
||||
tc[port].state_id = UNATTACHED_SNK;
|
||||
CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_unattached_snk_run(int port)
|
||||
{
|
||||
int host_cc;
|
||||
|
||||
/* Check Host CC for connection */
|
||||
vpd_host_get_cc(&host_cc);
|
||||
|
||||
/*
|
||||
* Transition to AttachWait.SNK when a Source connection is
|
||||
* detected, as indicated by the SNK.Rp state on its Host-side
|
||||
* port’s CC pin.
|
||||
*/
|
||||
if (cc_is_rp(host_cc)) {
|
||||
set_state(port, TC_OBJ(port), tc_state_attach_wait_snk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return RUN_SUPER;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_unattached_snk_exit(int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* AttachedWait.SNK
|
||||
*
|
||||
* Super State Entry:
|
||||
* Enable mcu communication
|
||||
* Place Ra on VCONN and Rd on Host CC
|
||||
*/
|
||||
static unsigned int tc_state_attach_wait_snk(int port, enum signal sig)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = (*tc_state_attach_wait_snk_sig[sig])(port);
|
||||
return SUPER(ret, sig, tc_state_host_rard);
|
||||
}
|
||||
|
||||
static unsigned int tc_state_attach_wait_snk_entry(int port)
|
||||
{
|
||||
tc[port].state_id = ATTACH_WAIT_SNK;
|
||||
CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
|
||||
tc[port].host_cc_state = PD_CC_UNSET;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_attach_wait_snk_run(int port)
|
||||
{
|
||||
int host_new_cc_state;
|
||||
int host_cc;
|
||||
|
||||
/* Check Host CC for connection */
|
||||
vpd_host_get_cc(&host_cc);
|
||||
|
||||
if (cc_is_rp(host_cc))
|
||||
host_new_cc_state = PD_CC_DFP_ATTACHED;
|
||||
else
|
||||
host_new_cc_state = PD_CC_NONE;
|
||||
|
||||
/* Debounce the Host CC state */
|
||||
if (tc[port].host_cc_state != host_new_cc_state) {
|
||||
tc[port].host_cc_state = host_new_cc_state;
|
||||
if (host_new_cc_state == PD_CC_DFP_ATTACHED)
|
||||
tc[port].cc_debounce = get_time().val +
|
||||
PD_T_CC_DEBOUNCE;
|
||||
else
|
||||
tc[port].cc_debounce = get_time().val +
|
||||
PD_T_PD_DEBOUNCE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait for Host CC debounce */
|
||||
if (get_time().val < tc[port].cc_debounce)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* A VCONN-Powered USB Device shall transition to
|
||||
* Attached.SNK after the state of the Host-side port’s CC pin is
|
||||
* SNK.Rp for at least tCCDebounce and either host-side VCONN or
|
||||
* VBUS is detected.
|
||||
*
|
||||
* Transition to Unattached.SNK when the state of both the CC1 and
|
||||
* CC2 pins is SNK.Open for at least tPDDebounce.
|
||||
*/
|
||||
if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
|
||||
(vpd_is_vconn_present() || vpd_is_host_vbus_present()))
|
||||
set_state(port, TC_OBJ(port), tc_state_attached_snk);
|
||||
else if (tc[port].host_cc_state == PD_CC_NONE)
|
||||
set_state(port, TC_OBJ(port), tc_state_unattached_snk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_attach_wait_snk_exit(int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attached.SNK
|
||||
*/
|
||||
static unsigned int tc_state_attached_snk(int port, enum signal sig)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = (*tc_state_attached_snk_sig[sig])(port);
|
||||
return SUPER(ret, sig, 0);
|
||||
}
|
||||
|
||||
static unsigned int tc_state_attached_snk_entry(int port)
|
||||
{
|
||||
tc[port].state_id = ATTACHED_SNK;
|
||||
CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
|
||||
|
||||
/* Enable PD */
|
||||
tc[port].pd_enable = 1;
|
||||
set_polarity(port, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_attached_snk_run(int port)
|
||||
{
|
||||
/* Has host vbus and vconn been removed */
|
||||
if (!vpd_is_host_vbus_present() && !vpd_is_vconn_present()) {
|
||||
set_state(port, TC_OBJ(port), tc_state_unattached_snk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vpd_is_vconn_present()) {
|
||||
if (!(tc[port].flags & TC_FLAGS_VCONN_ON)) {
|
||||
/* VCONN detected. Remove RA */
|
||||
vpd_host_set_pull(TYPEC_CC_RD, 0);
|
||||
tc[port].flags |= TC_FLAGS_VCONN_ON;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_attached_snk_exit(int port)
|
||||
{
|
||||
/* Disable PD */
|
||||
tc[port].pd_enable = 0;
|
||||
tc[port].flags &= ~TC_FLAGS_VCONN_ON;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Super State HOST_RARD
|
||||
*/
|
||||
static unsigned int tc_state_host_rard(int port, enum signal sig)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = (*tc_state_host_rard_sig[sig])(port);
|
||||
return SUPER(ret, sig, tc_state_vbus_cc_iso);
|
||||
}
|
||||
|
||||
static unsigned int tc_state_host_rard_entry(int port)
|
||||
{
|
||||
/* Place Ra on VCONN and Rd on Host CC */
|
||||
vpd_host_set_pull(TYPEC_CC_RA_RD, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_host_rard_run(int port)
|
||||
{
|
||||
return RUN_SUPER;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_host_rard_exit(int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Super State HOST_OPEN
|
||||
*/
|
||||
static unsigned int tc_state_host_open(int port, enum signal sig)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = (*tc_state_host_open_sig[sig])(port);
|
||||
return SUPER(ret, sig, tc_state_vbus_cc_iso);
|
||||
}
|
||||
|
||||
static unsigned int tc_state_host_open_entry(int port)
|
||||
{
|
||||
/* Remove the terminations from Host CC */
|
||||
vpd_host_set_pull(TYPEC_CC_OPEN, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_host_open_run(int port)
|
||||
{
|
||||
return RUN_SUPER;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_host_open_exit(int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Super State VBUS_CC_ISO
|
||||
*/
|
||||
static unsigned int tc_state_vbus_cc_iso(int port, enum signal sig)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = (*tc_state_vbus_cc_iso_sig[sig])(port);
|
||||
return SUPER(ret, sig, 0);
|
||||
}
|
||||
|
||||
static unsigned int tc_state_vbus_cc_iso_entry(int port)
|
||||
{
|
||||
/* Enable mcu communication and cc */
|
||||
vpd_mcu_cc_en(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_vbus_cc_iso_run(int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tc_state_vbus_cc_iso_exit(int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int get_super_state(int port)
|
||||
{
|
||||
return RUN_SUPER;
|
||||
}
|
||||
|
||||
#endif /*__CROS_EC_USB_TC_VPD_H */
|
|
@ -65,6 +65,13 @@ test-list-host += timer_dos
|
|||
test-list-host += usb_pd
|
||||
test-list-host += usb_pd_giveback
|
||||
test-list-host += usb_pd_rev30
|
||||
test-list-host += usb_sm_framework_h3
|
||||
test-list-host += usb_sm_framework_h2
|
||||
test-list-host += usb_sm_framework_h1
|
||||
test-list-host += usb_sm_framework_h0
|
||||
test-list-host += usb_typec_vpd
|
||||
test-list-host += usb_typec_ctvpd
|
||||
test-list-host += usb_prl
|
||||
test-list-host += utils
|
||||
test-list-host += utils_str
|
||||
test-list-host += vboot
|
||||
|
@ -127,6 +134,13 @@ timer_dos-y=timer_dos.o
|
|||
usb_pd-y=usb_pd.o
|
||||
usb_pd_giveback-y=usb_pd.o
|
||||
usb_pd_rev30-y=usb_pd.o
|
||||
usb_sm_framework_h3-y=usb_sm_framework_h3.o
|
||||
usb_sm_framework_h2-y=usb_sm_framework_h3.o
|
||||
usb_sm_framework_h1-y=usb_sm_framework_h3.o
|
||||
usb_sm_framework_h0-y=usb_sm_framework_h3.o
|
||||
usb_typec_vpd-y=usb_typec_ctvpd.o vpd_api.o
|
||||
usb_typec_ctvpd-y=usb_typec_ctvpd.o vpd_api.o
|
||||
usb_prl-y=usb_prl.o
|
||||
utils-y=utils.o
|
||||
utils_str-y=utils_str.o
|
||||
vboot-y=vboot.o
|
||||
|
|
|
@ -217,6 +217,93 @@ int ncp15wb_calculate_temp(uint16_t adc);
|
|||
#define CONFIG_ALS_LIGHTBAR_DIMMING 0
|
||||
#endif
|
||||
|
||||
#if defined(TEST_USB_SM_FRAMEWORK_H3)
|
||||
#define CONFIG_USB_PD_PORT_COUNT 1
|
||||
#undef CONFIG_USB_PRL_SM
|
||||
#undef CONFIG_USB_PE_SM
|
||||
#undef CONFIG_USB_TYPEC_SM
|
||||
#undef CONFIG_SM_NESTING_NUM
|
||||
#define CONFIG_SM_NESTING_NUM 3
|
||||
#define CONFIG_USB_SM_FRAMEWORK
|
||||
#endif
|
||||
|
||||
#if defined(TEST_USB_SM_FRAMEWORK_H2)
|
||||
#define CONFIG_USB_PD_PORT_COUNT 1
|
||||
#undef CONFIG_USB_PRL_SM
|
||||
#undef CONFIG_USB_PE_SM
|
||||
#undef CONFIG_USB_TYPEC_SM
|
||||
#undef CONFIG_SM_NESTING_NUM
|
||||
#define CONFIG_SM_NESTING_NUM 2
|
||||
#define CONFIG_USB_SM_FRAMEWORK
|
||||
#endif
|
||||
|
||||
#if defined(TEST_USB_SM_FRAMEWORK_H1)
|
||||
#define CONFIG_USB_PD_PORT_COUNT 1
|
||||
#undef CONFIG_USB_PRL_SM
|
||||
#undef CONFIG_USB_PE_SM
|
||||
#undef CONFIG_USB_TYPEC_SM
|
||||
#undef CONFIG_SM_NESTING_NUM
|
||||
#define CONFIG_SM_NESTING_NUM 1
|
||||
#define CONFIG_USB_SM_FRAMEWORK
|
||||
#endif
|
||||
|
||||
#if defined(TEST_USB_SM_FRAMEWORK_H0)
|
||||
#define CONFIG_USB_PD_PORT_COUNT 1
|
||||
#undef CONFIG_USB_PRL_SM
|
||||
#undef CONFIG_USB_PE_SM
|
||||
#undef CONFIG_USB_TYPEC_SM
|
||||
#undef CONFIG_SM_NESTING_NUM
|
||||
#define CONFIG_SM_NESTING_NUM 0
|
||||
#define CONFIG_USB_SM_FRAMEWORK
|
||||
#endif
|
||||
|
||||
#if defined(TEST_USB_PRL)
|
||||
#undef CONFIG_SM_NESTING_NUM
|
||||
#define CONFIG_SM_NESTING_NUM 3
|
||||
#define CONFIG_USB_PD_PORT_COUNT 2
|
||||
#define CONFIG_USB_SM_FRAMEWORK
|
||||
#undef CONFIG_USB_PE_SM
|
||||
#undef CONFIG_USB_TYPEC_SM
|
||||
#define CONFIG_USB_PRL_SM
|
||||
#define CONFIG_USB_PD_TCPC
|
||||
#define CONFIG_USB_PD_TCPM_STUB
|
||||
#define CONFIG_USB_POWER_DELIVERY
|
||||
#define CONFIG_SHA256
|
||||
#define CONFIG_SW_CRC
|
||||
#endif
|
||||
|
||||
#if defined(TEST_USB_TYPEC_VPD) || defined(TEST_USB_TYPEC_CTVPD)
|
||||
#if defined(TEST_USB_TYPEC_VPD)
|
||||
#define CONFIG_USB_TYPEC_VPD
|
||||
#else
|
||||
#define CONFIG_USB_TYPEC_CTVPD
|
||||
#endif
|
||||
#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
|
||||
#define USB_BCD_DEVICE 0
|
||||
|
||||
/* Vbus impedance in milliohms */
|
||||
#define VPD_VBUS_IMPEDANCE 65
|
||||
|
||||
/* GND impedance in milliohms */
|
||||
#define VPD_GND_IMPEDANCE 33
|
||||
|
||||
#define CONFIG_USB_PD_PORT_COUNT 1
|
||||
#define CONFIG_USB_SM_FRAMEWORK
|
||||
#define CONFIG_USB_PE_SM
|
||||
#define CONFIG_USB_PRL_SM
|
||||
#define CONFIG_USB_TYPEC_SM
|
||||
#define CONFIG_USB_PD_TCPC
|
||||
#define CONFIG_USB_PD_TCPM_STUB
|
||||
#define CONFIG_USB_POWER_DELIVERY
|
||||
#define CONFIG_SHA256
|
||||
#define CONFIG_SW_CRC
|
||||
#endif /* TEST_USB_TYPEC_VPD or TEST_USB_TYPEC_CTVPD */
|
||||
|
||||
#if defined(TEST_USB_PD) || defined(TEST_USB_PD_GIVEBACK) || \
|
||||
defined(TEST_USB_PD_REV30)
|
||||
#define CONFIG_USB_POWER_DELIVERY
|
||||
|
|
|
@ -13,6 +13,7 @@ void pd_test_rx_set_preamble(int port, int has_preamble);
|
|||
void pd_test_rx_msg_append_bits(int port, uint32_t bits, int nb);
|
||||
void pd_test_rx_msg_append_kcode(int port, uint8_t kcode);
|
||||
void pd_test_rx_msg_append_sop(int port);
|
||||
void pd_test_rx_msg_append_sop_prime(int port);
|
||||
void pd_test_rx_msg_append_eop(int port);
|
||||
void pd_test_rx_msg_append_last_edge(int port);
|
||||
void pd_test_rx_msg_append_4b(int port, uint8_t val);
|
||||
|
@ -23,6 +24,7 @@ void pd_simulate_rx(int port);
|
|||
/* Verify Tx message */
|
||||
int pd_test_tx_msg_verify_kcode(int port, uint8_t kcode);
|
||||
int pd_test_tx_msg_verify_sop(int port);
|
||||
int pd_test_tx_msg_verify_sop_prime(int port);
|
||||
int pd_test_tx_msg_verify_eop(int port);
|
||||
int pd_test_tx_msg_verify_4b5b(int port, uint8_t b4);
|
||||
int pd_test_tx_msg_verify_short(int port, uint16_t val);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,19 @@
|
|||
/* Copyright (c) 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_TEST(n, r, d, s) 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_TEST_TASK_LIST \
|
||||
TASK_TEST(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \
|
||||
TASK_TEST(PD_C1, pd_task, NULL, LARGER_TASK_STACK_SIZE)
|
|
@ -0,0 +1 @@
|
|||
usb_sm_framework_h3.tasklist
|
|
@ -0,0 +1 @@
|
|||
usb_sm_framework_h3.tasklist
|
|
@ -0,0 +1 @@
|
|||
usb_sm_framework_h3.tasklist
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,18 @@
|
|||
/* Copyright (c) 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_TEST(n, r, d, s) 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_TEST_TASK_LIST \
|
||||
TASK_TEST(TEST, test_task, NULL, LARGER_TASK_STACK_SIZE)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,18 @@
|
|||
/* Copyright (c) 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_TEST(n, r, d, s) 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_TEST_TASK_LIST \
|
||||
TASK_TEST(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE)
|
|
@ -0,0 +1 @@
|
|||
usb_typec_ctvpd.tasklist
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,333 @@
|
|||
/* 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"
|
||||
|
||||
/*
|
||||
* 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_DEFAULT_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 */
|
||||
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
struct mock_pin {
|
||||
enum vpd_pin cfg;
|
||||
int value;
|
||||
int value2;
|
||||
};
|
||||
|
||||
enum vpd_pwr mock_get_vconn_pwr_source(void);
|
||||
enum vpd_gpo mock_get_ct_rd(void);
|
||||
enum vpd_gpo mock_get_cc_rp1a5_odh(void);
|
||||
enum vpd_gpo mock_get_cc_rpusb_odh(void);
|
||||
enum vpd_gpo mock_get_cc_db_en_od(void);
|
||||
enum vpd_cc moch_get_ct_cl_sel(void);
|
||||
int mock_get_mcu_cc_en(void);
|
||||
enum vpd_billboard mock_get_present_billboard(void);
|
||||
int mock_get_red_led(void);
|
||||
int mock_get_green_led(void);
|
||||
int mock_get_vbus_pass_en(void);
|
||||
int mock_set_cc_vpdmcu(int v);
|
||||
void mock_set_host_vbus(int v);
|
||||
void mock_set_ct_vbus(int v);
|
||||
void mock_set_vconn(int v);
|
||||
int mock_get_cfg_cc2_rpusb_odh(void);
|
||||
int mock_set_cc2_rpusb_odh(int v);
|
||||
int mock_get_cfg_cc2_rp3a0_rd_l(void);
|
||||
int mock_set_cc2_rp3a0_rd_l(int v);
|
||||
int mock_get_cfg_cc1_rpusb_odh(void);
|
||||
int mock_set_cc1_rpusb_odh(int v);
|
||||
int mock_get_cfg_cc_vpdmcu(void);
|
||||
int mock_get_cc_vpdmcu(int v);
|
||||
enum vpd_pin mock_get_cfg_cc_rp3a0_rd_l(void);
|
||||
int mock_get_cc_rp3a0_rd_l(void);
|
||||
int mock_get_cfg_cc1_rp3a0_rd_l(void);
|
||||
int mock_set_cc1_rp3a0_rd_l(int v);
|
||||
void mock_set_host_cc_sink_voltage(int v);
|
||||
void mock_set_host_cc_source_voltage(int v);
|
||||
int mock_get_ct_cc1_rpusb(void);
|
||||
int mock_get_ct_cc2_rpusb(void);
|
||||
|
||||
/**
|
||||
* 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_vpdmcu 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_vpdmcu(enum vpd_pin cfg, 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 */
|
Loading…
Reference in New Issue