From 954770373c95ba3a92fc8d13e31c99b29d2866d0 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 11 Jun 2020 18:50:36 +1000 Subject: [PATCH 01/53] Starting the roughout --- .../TS100/Core/Drivers/FUSB302/FUSB302.hpp | 40 ++++ .../Core/Drivers/FUSB302/FUSB302_includes.h | 204 ++++++++++++++++++ 2 files changed, 244 insertions(+) create mode 100644 workspace/TS100/Core/Drivers/FUSB302/FUSB302.hpp create mode 100644 workspace/TS100/Core/Drivers/FUSB302/FUSB302_includes.h diff --git a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.hpp b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.hpp new file mode 100644 index 00000000..30f1f304 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.hpp @@ -0,0 +1,40 @@ +/* + * FUSB302.hpp + * + * Created on: 11-06-2020 + * Author: Ralim + */ + +#ifndef FUSB302_H_ +#define FUSB302_H_ +#include "BSP.h" +#include "FUSB302_includes.h" +#include "I2C_Wrapper.hpp" +//While the ST4500 is nice, the FUSB302 is _cheap_ so its what is used in the TS80P for example + +class FUSB302 { +public: + //Returns true if the FUSB302 is detected on the I2C bus + bool detect(); + +private: + // Bring up out of reset and clear fifo's + void fusb302_reset(); + void flush_rx_fifo(); + void flush_tx_fifo(); + void enable_auto_good_crc(); + int set_rp_value(int rp); + int set_cc(int pull); + struct fusb302_chip_state { + int cc_polarity; + int vconn_enabled; + /* 1 = pulling up (DFP) 0 = pulling down (UFP) */ + int pulling_up; + int rx_enable; + uint8_t mdac_vnc; + uint8_t mdac_rd; + }; + fusb302_chip_state state; +}; + +#endif /* LIS2DH12_HPP_ */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/FUSB302_includes.h b/workspace/TS100/Core/Drivers/FUSB302/FUSB302_includes.h new file mode 100644 index 00000000..ff9c2cd9 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/FUSB302_includes.h @@ -0,0 +1,204 @@ +#ifndef FUSB302_INCLUDES_H_ +#define FUSB302_INCLUDES_H_ + +/* Whole bunch of includes to make working with the FUSB302 easier*/ + +/* Chip Device ID - 302A or 302B */ +#define fusb302_DEVID_302A 0x08 +#define fusb302_DEVID_302B 0x09 + +/* I2C slave address varies by part number */ +/* FUSB302BUCX / FUSB302BMPX */ +#define fusb302_I2C_SLAVE_ADDR 0x22 // 7-bit address for Arduino +/* FUSB302B01MPX */ +#define fusb302_I2C_SLAVE_ADDR_B01 0x23 +/* FUSB302B10MPX */ +#define fusb302_I2C_SLAVE_ADDR_B10 0x24 +/* FUSB302B11MPX */ +#define fusb302_I2C_SLAVE_ADDR_B11 0x25 + +/* Default retry count for transmitting */ +#define PD_RETRY_COUNT 3 + +/* Time to wait for TCPC to complete transmit */ +#define PD_T_TCPC_TX_TIMEOUT (100 * MSEC) + +#define TCPC_REG_DEVICE_ID 0x01 + +#define TCPC_REG_SWITCHES0 0x02 +#define TCPC_REG_SWITCHES0_CC2_PU_EN (1 << 7) +#define TCPC_REG_SWITCHES0_CC1_PU_EN (1 << 6) +#define TCPC_REG_SWITCHES0_VCONN_CC2 (1 << 5) +#define TCPC_REG_SWITCHES0_VCONN_CC1 (1 << 4) +#define TCPC_REG_SWITCHES0_MEAS_CC2 (1 << 3) +#define TCPC_REG_SWITCHES0_MEAS_CC1 (1 << 2) +#define TCPC_REG_SWITCHES0_CC2_PD_EN (1 << 1) +#define TCPC_REG_SWITCHES0_CC1_PD_EN (1 << 0) + +#define TCPC_REG_SWITCHES1 0x03 +#define TCPC_REG_SWITCHES1_POWERROLE (1 << 7) +#define TCPC_REG_SWITCHES1_SPECREV1 (1 << 6) +#define TCPC_REG_SWITCHES1_SPECREV0 (1 << 5) +#define TCPC_REG_SWITCHES1_DATAROLE (1 << 4) +#define TCPC_REG_SWITCHES1_AUTO_GCRC (1 << 2) +#define TCPC_REG_SWITCHES1_TXCC2_EN (1 << 1) +#define TCPC_REG_SWITCHES1_TXCC1_EN (1 << 0) + +#define TCPC_REG_MEASURE 0x04 +#define TCPC_REG_MEASURE_VBUS (1 << 6) +#define TCPC_REG_MEASURE_MDAC_MV(mv) (((mv) / 42) & 0x3f) + +#define TCPC_REG_CONTROL0 0x06 +#define TCPC_REG_CONTROL0_TX_FLUSH (1 << 6) +#define TCPC_REG_CONTROL0_INT_MASK (1 << 5) +#define TCPC_REG_CONTROL0_HOST_CUR_MASK (3 << 2) +#define TCPC_REG_CONTROL0_HOST_CUR_3A0 (3 << 2) +#define TCPC_REG_CONTROL0_HOST_CUR_1A5 (2 << 2) +#define TCPC_REG_CONTROL0_HOST_CUR_USB (1 << 2) +#define TCPC_REG_CONTROL0_TX_START (1 << 0) + +#define TCPC_REG_CONTROL1 0x07 +#define TCPC_REG_CONTROL1_ENSOP2DB (1 << 6) +#define TCPC_REG_CONTROL1_ENSOP1DB (1 << 5) +#define TCPC_REG_CONTROL1_BIST_MODE2 (1 << 4) +#define TCPC_REG_CONTROL1_RX_FLUSH (1 << 2) +#define TCPC_REG_CONTROL1_ENSOP2 (1 << 1) +#define TCPC_REG_CONTROL1_ENSOP1 (1 << 0) + +#define TCPC_REG_CONTROL2 0x08 +/* two-bit field, valid values below */ +#define TCPC_REG_CONTROL2_MODE (1 << 1) +#define TCPC_REG_CONTROL2_MODE_DFP (0x3) +#define TCPC_REG_CONTROL2_MODE_UFP (0x2) +#define TCPC_REG_CONTROL2_MODE_DRP (0x1) +#define TCPC_REG_CONTROL2_MODE_POS (1) +#define TCPC_REG_CONTROL2_TOGGLE (1 << 0) + +#define TCPC_REG_CONTROL3 0x09 +#define TCPC_REG_CONTROL3_SEND_HARDRESET (1 << 6) +#define TCPC_REG_CONTROL3_BIST_TMODE (1 << 5) /* 302B Only */ +#define TCPC_REG_CONTROL3_AUTO_HARDRESET (1 << 4) +#define TCPC_REG_CONTROL3_AUTO_SOFTRESET (1 << 3) +/* two-bit field */ +#define TCPC_REG_CONTROL3_N_RETRIES (1 << 1) +#define TCPC_REG_CONTROL3_N_RETRIES_POS (1) +#define TCPC_REG_CONTROL3_N_RETRIES_SIZE (2) +#define TCPC_REG_CONTROL3_AUTO_RETRY (1 << 0) + +#define TCPC_REG_MASK 0x0A +#define TCPC_REG_MASK_VBUSOK (1 << 7) +#define TCPC_REG_MASK_ACTIVITY (1 << 6) +#define TCPC_REG_MASK_COMP_CHNG (1 << 5) +#define TCPC_REG_MASK_CRC_CHK (1 << 4) +#define TCPC_REG_MASK_ALERT (1 << 3) +#define TCPC_REG_MASK_WAKE (1 << 2) +#define TCPC_REG_MASK_COLLISION (1 << 1) +#define TCPC_REG_MASK_BC_LVL (1 << 0) + +#define TCPC_REG_POWER 0x0B +#define TCPC_REG_POWER_PWR (1 << 0) /* four-bit field */ +#define TCPC_REG_POWER_PWR_LOW 0x1 /* Bandgap + Wake circuitry */ +#define TCPC_REG_POWER_PWR_MEDIUM 0x3 /* LOW + Receiver + Current refs */ +#define TCPC_REG_POWER_PWR_HIGH 0x7 /* MEDIUM + Measure block */ +#define TCPC_REG_POWER_PWR_ALL 0xF /* HIGH + Internal Oscillator */ + +#define TCPC_REG_RESET 0x0C +#define TCPC_REG_RESET_PD_RESET (1 << 1) +#define TCPC_REG_RESET_SW_RESET (1 << 0) + +#define TCPC_REG_MASKA 0x0E +#define TCPC_REG_MASKA_OCP_TEMP (1 << 7) +#define TCPC_REG_MASKA_TOGDONE (1 << 6) +#define TCPC_REG_MASKA_SOFTFAIL (1 << 5) +#define TCPC_REG_MASKA_RETRYFAIL (1 << 4) +#define TCPC_REG_MASKA_HARDSENT (1 << 3) +#define TCPC_REG_MASKA_TX_SUCCESS (1 << 2) +#define TCPC_REG_MASKA_SOFTRESET (1 << 1) +#define TCPC_REG_MASKA_HARDRESET (1 << 0) + +#define TCPC_REG_MASKB 0x0F +#define TCPC_REG_MASKB_GCRCSENT (1 << 0) + +#define TCPC_REG_STATUS0A 0x3C +#define TCPC_REG_STATUS0A_SOFTFAIL (1 << 5) +#define TCPC_REG_STATUS0A_RETRYFAIL (1 << 4) +#define TCPC_REG_STATUS0A_POWER (1 << 2) /* two-bit field */ +#define TCPC_REG_STATUS0A_RX_SOFT_RESET (1 << 1) +#define TCPC_REG_STATUS0A_RX_HARD_RESET (1 << 0) + +#define TCPC_REG_STATUS1A 0x3D +/* three-bit field, valid values below */ +#define TCPC_REG_STATUS1A_TOGSS (1 << 3) +#define TCPC_REG_STATUS1A_TOGSS_RUNNING 0x0 +#define TCPC_REG_STATUS1A_TOGSS_SRC1 0x1 +#define TCPC_REG_STATUS1A_TOGSS_SRC2 0x2 +#define TCPC_REG_STATUS1A_TOGSS_SNK1 0x5 +#define TCPC_REG_STATUS1A_TOGSS_SNK2 0x6 +#define TCPC_REG_STATUS1A_TOGSS_AA 0x7 +#define TCPC_REG_STATUS1A_TOGSS_POS (3) +#define TCPC_REG_STATUS1A_TOGSS_MASK (0x7) + +#define TCPC_REG_STATUS1A_RXSOP2DB (1 << 2) +#define TCPC_REG_STATUS1A_RXSOP1DB (1 << 1) +#define TCPC_REG_STATUS1A_RXSOP (1 << 0) + +#define TCPC_REG_INTERRUPTA 0x3E +#define TCPC_REG_INTERRUPTA_OCP_TEMP (1 << 7) +#define TCPC_REG_INTERRUPTA_TOGDONE (1 << 6) +#define TCPC_REG_INTERRUPTA_SOFTFAIL (1 << 5) +#define TCPC_REG_INTERRUPTA_RETRYFAIL (1 << 4) +#define TCPC_REG_INTERRUPTA_HARDSENT (1 << 3) +#define TCPC_REG_INTERRUPTA_TX_SUCCESS (1 << 2) +#define TCPC_REG_INTERRUPTA_SOFTRESET (1 << 1) +#define TCPC_REG_INTERRUPTA_HARDRESET (1 << 0) + +#define TCPC_REG_INTERRUPTB 0x3F +#define TCPC_REG_INTERRUPTB_GCRCSENT (1 << 0) + +#define TCPC_REG_STATUS0 0x40 +#define TCPC_REG_STATUS0_VBUSOK (1 << 7) +#define TCPC_REG_STATUS0_ACTIVITY (1 << 6) +#define TCPC_REG_STATUS0_COMP (1 << 5) +#define TCPC_REG_STATUS0_CRC_CHK (1 << 4) +#define TCPC_REG_STATUS0_ALERT (1 << 3) +#define TCPC_REG_STATUS0_WAKE (1 << 2) +#define TCPC_REG_STATUS0_BC_LVL1 (1 << 1) /* two-bit field */ +#define TCPC_REG_STATUS0_BC_LVL0 (1 << 0) /* two-bit field */ + +#define TCPC_REG_STATUS1 0x41 +#define TCPC_REG_STATUS1_RXSOP2 (1 << 7) +#define TCPC_REG_STATUS1_RXSOP1 (1 << 6) +#define TCPC_REG_STATUS1_RX_EMPTY (1 << 5) +#define TCPC_REG_STATUS1_RX_FULL (1 << 4) +#define TCPC_REG_STATUS1_TX_EMPTY (1 << 3) +#define TCPC_REG_STATUS1_TX_FULL (1 << 2) + +#define TCPC_REG_INTERRUPT 0x42 +#define TCPC_REG_INTERRUPT_VBUSOK (1 << 7) +#define TCPC_REG_INTERRUPT_ACTIVITY (1 << 6) +#define TCPC_REG_INTERRUPT_COMP_CHNG (1 << 5) +#define TCPC_REG_INTERRUPT_CRC_CHK (1 << 4) +#define TCPC_REG_INTERRUPT_ALERT (1 << 3) +#define TCPC_REG_INTERRUPT_WAKE (1 << 2) +#define TCPC_REG_INTERRUPT_COLLISION (1 << 1) +#define TCPC_REG_INTERRUPT_BC_LVL (1 << 0) + +#define TCPC_REG_FIFOS 0x43 + +/* Tokens defined for the FUSB302 TX FIFO */ +enum fusb302_txfifo_tokens { + fusb302_TKN_TXON = 0xA1, + fusb302_TKN_SYNC1 = 0x12, + fusb302_TKN_SYNC2 = 0x13, + fusb302_TKN_SYNC3 = 0x1B, + fusb302_TKN_RST1 = 0x15, + fusb302_TKN_RST2 = 0x16, + fusb302_TKN_PACKSYM = 0x80, + fusb302_TKN_JAMCRC = 0xFF, + fusb302_TKN_EOP = 0x14, + fusb302_TKN_TXOFF = 0xFE, +}; + +#define PACKET_IS_GOOD_CRC(head) (PD_HEADER_TYPE(head) == PD_CTRL_GOOD_CRC && \ + PD_HEADER_CNT(head) == 0) +#endif \ No newline at end of file From 450ce17935029c9cc09cfe73118c0987aca6c012 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 11 Jun 2020 23:30:06 +1000 Subject: [PATCH 02/53] Import existing FUSB302 library --- .../TS100/Core/Drivers/FUSB302/FUSB302.c | 952 ++++ .../TS100/Core/Drivers/FUSB302/FUSB302.h | 250 + .../TS100/Core/Drivers/FUSB302/FUSB302.hpp | 40 - .../Core/Drivers/FUSB302/FUSB302_includes.h | 204 - .../Core/Drivers/FUSB302/USBC_PD/usb_pd.h | 1799 +++++++ .../Drivers/FUSB302/USBC_PD/usb_pd_policy.c | 1019 ++++ .../Drivers/FUSB302/USBC_PD/usb_pd_protocol.c | 4276 +++++++++++++++++ .../Core/Drivers/FUSB302/USBC_TCPM/tcpm.h | 276 ++ .../Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h | 354 ++ .../Core/Drivers/FUSB302/tcpm_driver.cpp | 69 + .../TS100/Core/Drivers/FUSB302/tcpm_driver.h | 22 + .../Core/Drivers/FUSB302/usb_pd_driver.cpp | 414 ++ .../Core/Drivers/FUSB302/usb_pd_driver.h | 104 + .../TS100/Core/Drivers/FUSB302/usb_pd_tcpm.h | 354 ++ workspace/TS100/Core/Drivers/I2C_Wrapper.hpp | 3 + 15 files changed, 9892 insertions(+), 244 deletions(-) create mode 100644 workspace/TS100/Core/Drivers/FUSB302/FUSB302.c create mode 100644 workspace/TS100/Core/Drivers/FUSB302/FUSB302.h delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/FUSB302.hpp delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/FUSB302_includes.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.c create mode 100644 workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.c create mode 100644 workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp create mode 100644 workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp create mode 100644 workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/usb_pd_tcpm.h diff --git a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.c b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.c new file mode 100644 index 00000000..2d9a0c3a --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.c @@ -0,0 +1,952 @@ +/* + FUSB302.c - Library for interacting with the FUSB302B chip. + Copyright 2015 The Chromium OS Authors + Copyright 2017 Jason Cerundolo + Released under an MIT license. See LICENSE file. + */ + +#include "FUSB302.h" +#include "usb_pd_tcpm.h" +#include "USBC_TCPM/tcpm.h" +#include "USBC_PD/usb_pd.h" + +#define PACKET_IS_GOOD_CRC(head) (PD_HEADER_TYPE(head) == PD_CTRL_GOOD_CRC && \ + PD_HEADER_CNT(head) == 0) + +static struct fusb302_chip_state { + int cc_polarity; + int vconn_enabled; + /* 1 = pulling up (DFP) 0 = pulling down (UFP) */ + int pulling_up; + int rx_enable; + uint8_t mdac_vnc; + uint8_t mdac_rd; +} state[CONFIG_USB_PD_PORT_COUNT]; + +/* + * Bring the FUSB302 out of reset after Hard Reset signaling. This will + * automatically flush both the Rx and Tx FIFOs. + */ +static void fusb302_pd_reset(int port) { + + tcpc_write(port, TCPC_REG_RESET, TCPC_REG_RESET_PD_RESET); + +} + +/* + * Flush our Rx FIFO. To prevent packet framing issues, this function should + * only be called when Rx is disabled. + */ +static void fusb302_flush_rx_fifo(int port) { + /* + * other bits in the register _should_ be 0 + * until the day we support other SOP* types... + * then we'll have to keep a shadow of what this register + * value should be so we don't clobber it here! + */ + i2c_master_lock(tcpc_config[port].i2c_host_port); + tcpc_write(port, TCPC_REG_CONTROL1, TCPC_REG_CONTROL1_RX_FLUSH); + +} + +static void fusb302_flush_tx_fifo(int port) { + int reg; + + i2c_master_lock(tcpc_config[port].i2c_host_port); + tcpc_read(port, TCPC_REG_CONTROL0, ®); + reg |= TCPC_REG_CONTROL0_TX_FLUSH; + tcpc_write(port, TCPC_REG_CONTROL0, reg); + +} + +static void fusb302_auto_goodcrc_enable(int port, int enable) { + int reg; + + i2c_master_lock(tcpc_config[port].i2c_host_port); + tcpc_read(port, TCPC_REG_SWITCHES1, ®); + + if (enable) + reg |= TCPC_REG_SWITCHES1_AUTO_GCRC; + else + reg &= ~TCPC_REG_SWITCHES1_AUTO_GCRC; + + tcpc_write(port, TCPC_REG_SWITCHES1, reg); + +} + +/* Convert BC LVL values (in FUSB302) to Type-C CC Voltage Status */ +static int convert_bc_lvl(int port, int bc_lvl) { + /* assume OPEN unless one of the following conditions is true... */ + int ret = TYPEC_CC_VOLT_OPEN; + + if (state[port].pulling_up) { + if (bc_lvl == 0x00) + ret = TYPEC_CC_VOLT_RA; + else if (bc_lvl < 0x3) + ret = TYPEC_CC_VOLT_RD; + } else { + if (bc_lvl == 0x1) + ret = TYPEC_CC_VOLT_SNK_DEF; + else if (bc_lvl == 0x2) + ret = TYPEC_CC_VOLT_SNK_1_5; + else if (bc_lvl == 0x3) + ret = TYPEC_CC_VOLT_SNK_3_0; + } + + return ret; +} + +static int measure_cc_pin_source(int port, int cc_measure) { + int switches0_reg; + int reg; + int cc_lvl; + + i2c_master_lock(tcpc_config[port].i2c_host_port); + + /* Read status register */ + tcpc_read(port, TCPC_REG_SWITCHES0, ®); + /* Save current value */ + switches0_reg = reg; + /* Clear pull-up register settings and measure bits */ + reg &= ~(TCPC_REG_SWITCHES0_MEAS_CC1 | TCPC_REG_SWITCHES0_MEAS_CC2); + /* Set desired pullup register bit */ + if (cc_measure == TCPC_REG_SWITCHES0_MEAS_CC1) + reg |= TCPC_REG_SWITCHES0_CC1_PU_EN; + else + reg |= TCPC_REG_SWITCHES0_CC2_PU_EN; + /* Set CC measure bit */ + reg |= cc_measure; + + /* Set measurement switch */ + tcpc_write(port, TCPC_REG_SWITCHES0, reg); + + /* Set MDAC for Open vs Rd/Ra comparison */ + tcpc_write(port, TCPC_REG_MEASURE, state[port].mdac_vnc); + + /* Wait on measurement */ + usleep(250); + + /* Read status register */ + tcpc_read(port, TCPC_REG_STATUS0, ®); + + /* Assume open */ + cc_lvl = TYPEC_CC_VOLT_OPEN; + + /* CC level is below the 'no connect' threshold (vOpen) */ + if ((reg & TCPC_REG_STATUS0_COMP) == 0) { + /* Set MDAC for Rd vs Ra comparison */ + tcpc_write(port, TCPC_REG_MEASURE, state[port].mdac_rd); + + /* Wait on measurement */ + usleep(250); + + /* Read status register */ + tcpc_read(port, TCPC_REG_STATUS0, ®); + + cc_lvl = + (reg & TCPC_REG_STATUS0_COMP) ? + TYPEC_CC_VOLT_RD : TYPEC_CC_VOLT_RA; + } + + /* Restore SWITCHES0 register to its value prior */ + tcpc_write(port, TCPC_REG_SWITCHES0, switches0_reg); + + return cc_lvl; +} + +/* Determine cc pin state for source when in manual detect mode */ +static void detect_cc_pin_source_manual(int port, int *cc1_lvl, int *cc2_lvl) { + int cc1_measure = TCPC_REG_SWITCHES0_MEAS_CC1; + int cc2_measure = TCPC_REG_SWITCHES0_MEAS_CC2; + + if (state[port].vconn_enabled) { + /* If VCONN enabled, measure cc_pin that matches polarity */ + if (state[port].cc_polarity) + *cc2_lvl = measure_cc_pin_source(port, cc2_measure); + else + *cc1_lvl = measure_cc_pin_source(port, cc1_measure); + } else { + /* If VCONN not enabled, measure both cc1 and cc2 */ + *cc1_lvl = measure_cc_pin_source(port, cc1_measure); + *cc2_lvl = measure_cc_pin_source(port, cc2_measure); + } + +} + +/* Determine cc pin state for sink */ +static void detect_cc_pin_sink(int port, int *cc1, int *cc2) { + int reg; + int orig_meas_cc1; + int orig_meas_cc2; + int bc_lvl_cc1; + int bc_lvl_cc2; + + i2c_master_lock(tcpc_config[port].i2c_host_port); + + /* + * Measure CC1 first. + */ + tcpc_read(port, TCPC_REG_SWITCHES0, ®); + + /* save original state to be returned to later... */ + if (reg & TCPC_REG_SWITCHES0_MEAS_CC1) + orig_meas_cc1 = 1; + else + orig_meas_cc1 = 0; + + if (reg & TCPC_REG_SWITCHES0_MEAS_CC2) + orig_meas_cc2 = 1; + else + orig_meas_cc2 = 0; + + /* Disable CC2 measurement switch, enable CC1 measurement switch */ + reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; + reg |= TCPC_REG_SWITCHES0_MEAS_CC1; + + tcpc_write(port, TCPC_REG_SWITCHES0, reg); + + /* CC1 is now being measured by FUSB302. */ + + /* Wait on measurement */ + usleep(250); + + tcpc_read(port, TCPC_REG_STATUS0, &bc_lvl_cc1); + + /* mask away unwanted bits */ + bc_lvl_cc1 &= (TCPC_REG_STATUS0_BC_LVL0 | TCPC_REG_STATUS0_BC_LVL1); + + /* + * Measure CC2 next. + */ + + tcpc_read(port, TCPC_REG_SWITCHES0, ®); + + /* Disable CC1 measurement switch, enable CC2 measurement switch */ + reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1; + reg |= TCPC_REG_SWITCHES0_MEAS_CC2; + + tcpc_write(port, TCPC_REG_SWITCHES0, reg); + + /* CC2 is now being measured by FUSB302. */ + + /* Wait on measurement */ + usleep(250); + + tcpc_read(port, TCPC_REG_STATUS0, &bc_lvl_cc2); + + /* mask away unwanted bits */ + bc_lvl_cc2 &= (TCPC_REG_STATUS0_BC_LVL0 | TCPC_REG_STATUS0_BC_LVL1); + + *cc1 = convert_bc_lvl(port, bc_lvl_cc1); + *cc2 = convert_bc_lvl(port, bc_lvl_cc2); + + /* return MEAS_CC1/2 switches to original state */ + tcpc_read(port, TCPC_REG_SWITCHES0, ®); + if (orig_meas_cc1) + reg |= TCPC_REG_SWITCHES0_MEAS_CC1; + else + reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1; + if (orig_meas_cc2) + reg |= TCPC_REG_SWITCHES0_MEAS_CC2; + else + reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; + + tcpc_write(port, TCPC_REG_SWITCHES0, reg); + +} + +/* Parse header bytes for the size of packet */ +static int get_num_bytes(uint16_t header) { + int rv; + + /* Grab the Number of Data Objects field.*/ + rv = PD_HEADER_CNT(header); + + /* Multiply by four to go from 32-bit words -> bytes */ + rv *= 4; + + /* Plus 2 for header */ + rv += 2; + + return rv; +} + +static int fusb302_send_message(int port, uint16_t header, const uint32_t *data, + uint8_t *buf, int buf_pos) { + int rv; + int reg; + int len; + + len = get_num_bytes(header); + + /* + * packsym tells the TXFIFO that the next X bytes are payload, + * and should not be interpreted as special tokens. + * The 5 LSBs represent X, the number of bytes. + */ + reg = fusb302_TKN_PACKSYM; + reg |= (len & 0x1F); + + buf[buf_pos++] = reg; + + /* write in the header */ + reg = header; + buf[buf_pos++] = reg & 0xFF; + + reg >>= 8; + buf[buf_pos++] = reg & 0xFF; + + /* header is done, subtract from length to make this for-loop simpler */ + len -= 2; + + /* write data objects, if present */ + memcpy(&buf[buf_pos], data, len); + buf_pos += len; + + /* put in the CRC */ + buf[buf_pos++] = fusb302_TKN_JAMCRC; + + /* put in EOP */ + buf[buf_pos++] = fusb302_TKN_EOP; + + /* Turn transmitter off after sending message */ + buf[buf_pos++] = fusb302_TKN_TXOFF; + + /* Start transmission */ + reg = fusb302_TKN_TXON; + buf[buf_pos++] = fusb302_TKN_TXON; + + /* burst write for speed! */ + i2c_master_lock(tcpc_config[port].i2c_host_port); + rv = tcpc_xfer(port, buf, buf_pos, 0, 0, I2C_XFER_SINGLE); + + return rv; +} + +static int fusb302_tcpm_select_rp_value(int port, int rp) { + int reg; + int rv; + uint8_t vnc, rd; + + i2c_master_lock(tcpc_config[port].i2c_host_port); + + rv = tcpc_read(port, TCPC_REG_CONTROL0, ®); + if (rv) + return rv; + + /* Set the current source for Rp value */ + reg &= ~TCPC_REG_CONTROL0_HOST_CUR_MASK; + switch (rp) { + case TYPEC_RP_1A5: + reg |= TCPC_REG_CONTROL0_HOST_CUR_1A5; + vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_1_5_VNC_MV); + rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_1_5_RD_THRESH_MV); + break; + case TYPEC_RP_3A0: + reg |= TCPC_REG_CONTROL0_HOST_CUR_3A0; + vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_3_0_VNC_MV); + rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_3_0_RD_THRESH_MV); + break; + case TYPEC_RP_USB: + default: + reg |= TCPC_REG_CONTROL0_HOST_CUR_USB; + vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_VNC_MV); + rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_RD_THRESH_MV); + } + state[port].mdac_vnc = vnc; + state[port].mdac_rd = rd; + rv = tcpc_write(port, TCPC_REG_CONTROL0, reg); + + return rv; +} + +static int fusb302_tcpm_init(int port) { + int reg; + + /* set default */ + state[port].cc_polarity = -1; + + /* set the voltage threshold for no connect detection (vOpen) */ + state[port].mdac_vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_VNC_MV); + /* set the voltage threshold for Rd vs Ra detection */ + state[port].mdac_rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_RD_THRESH_MV); + + /* all other variables assumed to default to 0 */ + + i2c_master_lock(tcpc_config[port].i2c_host_port); + + /* Restore default settings */ + tcpc_write(port, TCPC_REG_RESET, TCPC_REG_RESET_SW_RESET); + + /* Turn on retries and set number of retries */ + tcpc_read(port, TCPC_REG_CONTROL3, ®); + reg |= TCPC_REG_CONTROL3_AUTO_RETRY; + reg |= (PD_RETRY_COUNT & 0x3) << + TCPC_REG_CONTROL3_N_RETRIES_POS; + tcpc_write(port, TCPC_REG_CONTROL3, reg); + + /* Create interrupt masks */ + reg = 0xFF; + /* CC level changes */ + reg &= ~TCPC_REG_MASK_BC_LVL; + /* collisions */ + reg &= ~TCPC_REG_MASK_COLLISION; + /* misc alert */ + reg &= ~TCPC_REG_MASK_ALERT; + /* packet received with correct CRC */ + reg &= ~TCPC_REG_MASK_CRC_CHK; + tcpc_write(port, TCPC_REG_MASK, reg); + + reg = 0xFF; + /* when all pd message retries fail... */ + reg &= ~TCPC_REG_MASKA_RETRYFAIL; + /* when fusb302 send a hard reset. */ + reg &= ~TCPC_REG_MASKA_HARDSENT; + /* when fusb302 receives GoodCRC ack for a pd message */ + reg &= ~TCPC_REG_MASKA_TX_SUCCESS; + /* when fusb302 receives a hard reset */ + reg &= ~TCPC_REG_MASKA_HARDRESET; + tcpc_write(port, TCPC_REG_MASKA, reg); + + reg = 0xFF; + /* when fusb302 sends GoodCRC to ack a pd message */ + reg &= ~TCPC_REG_MASKB_GCRCSENT; + tcpc_write(port, TCPC_REG_MASKB, reg); + + /* Interrupt Enable */ + tcpc_read(port, TCPC_REG_CONTROL0, ®); + reg &= ~TCPC_REG_CONTROL0_INT_MASK; + tcpc_write(port, TCPC_REG_CONTROL0, reg); + + /* Set VCONN switch defaults */ + tcpm_set_polarity(port, 0); + tcpm_set_vconn(port, 0); + + /* Turn on the power! */ + /* TODO: Reduce power consumption */ + tcpc_write(port, TCPC_REG_POWER, TCPC_REG_POWER_PWR_ALL); + + return 0; +} + +static int fusb302_tcpm_release(int port) { + return EC_ERROR_UNIMPLEMENTED; +} + +static int fusb302_tcpm_get_cc(int port, int *cc1, int *cc2) { + if (state[port].pulling_up) { + /* Source mode? */ + detect_cc_pin_source_manual(port, cc1, cc2); + } else { + /* Sink mode? */ + detect_cc_pin_sink(port, cc1, cc2); + } + + return 0; +} + +static int fusb302_tcpm_set_cc(int port, int pull) { + int reg; + + i2c_master_lock(tcpc_config[port].i2c_host_port); + + /* NOTE: FUSB302 toggles a single pull-up between CC1 and CC2 */ + /* NOTE: FUSB302 Does not support Ra. */ + switch (pull) { + case TYPEC_CC_RP: + /* enable the pull-up we know to be necessary */ + tcpc_read(port, TCPC_REG_SWITCHES0, ®); + + reg &= ~(TCPC_REG_SWITCHES0_CC2_PU_EN | + TCPC_REG_SWITCHES0_CC1_PU_EN | + TCPC_REG_SWITCHES0_CC1_PD_EN | + TCPC_REG_SWITCHES0_CC2_PD_EN | + TCPC_REG_SWITCHES0_VCONN_CC1 | + TCPC_REG_SWITCHES0_VCONN_CC2); + + reg |= TCPC_REG_SWITCHES0_CC1_PU_EN | + TCPC_REG_SWITCHES0_CC2_PU_EN; + + if (state[port].vconn_enabled) + reg |= state[port].cc_polarity ? + TCPC_REG_SWITCHES0_VCONN_CC1 : + TCPC_REG_SWITCHES0_VCONN_CC2; + + tcpc_write(port, TCPC_REG_SWITCHES0, reg); + + state[port].pulling_up = 1; + break; + case TYPEC_CC_RD: + /* Enable UFP Mode */ + + /* turn off toggle */ + tcpc_read(port, TCPC_REG_CONTROL2, ®); + reg &= ~TCPC_REG_CONTROL2_TOGGLE; + tcpc_write(port, TCPC_REG_CONTROL2, reg); + + /* enable pull-downs, disable pullups */ + tcpc_read(port, TCPC_REG_SWITCHES0, ®); + + reg &= ~(TCPC_REG_SWITCHES0_CC2_PU_EN); + reg &= ~(TCPC_REG_SWITCHES0_CC1_PU_EN); + reg |= (TCPC_REG_SWITCHES0_CC1_PD_EN); + reg |= (TCPC_REG_SWITCHES0_CC2_PD_EN); + tcpc_write(port, TCPC_REG_SWITCHES0, reg); + + state[port].pulling_up = 0; + break; + case TYPEC_CC_OPEN: + /* Disable toggling */ + tcpc_read(port, TCPC_REG_CONTROL2, ®); + reg &= ~TCPC_REG_CONTROL2_TOGGLE; + tcpc_write(port, TCPC_REG_CONTROL2, reg); + + /* Ensure manual switches are opened */ + tcpc_read(port, TCPC_REG_SWITCHES0, ®); + reg &= ~TCPC_REG_SWITCHES0_CC1_PU_EN; + reg &= ~TCPC_REG_SWITCHES0_CC2_PU_EN; + reg &= ~TCPC_REG_SWITCHES0_CC1_PD_EN; + reg &= ~TCPC_REG_SWITCHES0_CC2_PD_EN; + tcpc_write(port, TCPC_REG_SWITCHES0, reg); + + state[port].pulling_up = 0; + break; + default: + /* Unsupported... */ + return EC_ERROR_UNIMPLEMENTED; + } + + return 0; +} + +static int fusb302_tcpm_set_polarity(int port, int polarity) { + /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */ + int reg; + + i2c_master_lock(tcpc_config[port].i2c_host_port); + + tcpc_read(port, TCPC_REG_SWITCHES0, ®); + + /* clear VCONN switch bits */ + reg &= ~TCPC_REG_SWITCHES0_VCONN_CC1; + reg &= ~TCPC_REG_SWITCHES0_VCONN_CC2; + + if (state[port].vconn_enabled) { + /* set VCONN switch to be non-CC line */ + if (polarity) + reg |= TCPC_REG_SWITCHES0_VCONN_CC1; + else + reg |= TCPC_REG_SWITCHES0_VCONN_CC2; + } + + /* clear meas_cc bits (RX line select) */ + reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1; + reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; + + /* set rx polarity */ + if (polarity) + reg |= TCPC_REG_SWITCHES0_MEAS_CC2; + else + reg |= TCPC_REG_SWITCHES0_MEAS_CC1; + + tcpc_write(port, TCPC_REG_SWITCHES0, reg); + + tcpc_read(port, TCPC_REG_SWITCHES1, ®); + + /* clear tx_cc bits */ + reg &= ~TCPC_REG_SWITCHES1_TXCC1_EN; + reg &= ~TCPC_REG_SWITCHES1_TXCC2_EN; + + /* set tx polarity */ + if (polarity) + reg |= TCPC_REG_SWITCHES1_TXCC2_EN; + else + reg |= TCPC_REG_SWITCHES1_TXCC1_EN; + + tcpc_write(port, TCPC_REG_SWITCHES1, reg); + + /* Save the polarity for later */ + state[port].cc_polarity = polarity; + + return 0; +} + +static int fusb302_tcpm_set_vconn(int port, int enable) { + /* + * FUSB302 does not have dedicated VCONN Enable switch. + * We'll get through this by disabling both of the + * VCONN - CC* switches to disable, and enabling the + * saved polarity when enabling. + * Therefore at startup, tcpm_set_polarity should be called first, + * or else live with the default put into tcpm_init. + */ + int reg; + + /* save enable state for later use */ + state[port].vconn_enabled = enable; + + if (enable) { + /* set to saved polarity */ + tcpm_set_polarity(port, state[port].cc_polarity); + } else { + + i2c_master_lock(tcpc_config[port].i2c_host_port); + + tcpc_read(port, TCPC_REG_SWITCHES0, ®); + + /* clear VCONN switch bits */ + reg &= ~TCPC_REG_SWITCHES0_VCONN_CC1; + reg &= ~TCPC_REG_SWITCHES0_VCONN_CC2; + + tcpc_write(port, TCPC_REG_SWITCHES0, reg); + + } + + return 0; +} + +static int fusb302_tcpm_set_msg_header(int port, int power_role, int data_role) { + int reg; + + tcpc_read(port, TCPC_REG_SWITCHES1, ®); + + reg &= ~TCPC_REG_SWITCHES1_POWERROLE; + reg &= ~TCPC_REG_SWITCHES1_DATAROLE; + + if (power_role) + reg |= TCPC_REG_SWITCHES1_POWERROLE; + if (data_role) + reg |= TCPC_REG_SWITCHES1_DATAROLE; + + tcpc_write(port, TCPC_REG_SWITCHES1, reg); + + return 0; +} + +static int fusb302_tcpm_set_rx_enable(int port, int enable) { + int reg; + + state[port].rx_enable = enable; + + i2c_master_lock(tcpc_config[port].i2c_host_port); + + /* Get current switch state */ + tcpc_read(port, TCPC_REG_SWITCHES0, ®); + + /* Clear CC1/CC2 measure bits */ + reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1; + reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; + + if (enable) { + switch (state[port].cc_polarity) { + /* if CC polarity hasnt been determined, can't enable */ + case -1: + return EC_ERROR_UNKNOWN; + case 0: + reg |= TCPC_REG_SWITCHES0_MEAS_CC1; + break; + case 1: + reg |= TCPC_REG_SWITCHES0_MEAS_CC2; + break; + default: + /* "shouldn't get here" */ + return EC_ERROR_UNKNOWN; + } + tcpc_write(port, TCPC_REG_SWITCHES0, reg); + + /* Disable BC_LVL interrupt when enabling PD comm */ + if (!tcpc_read(port, TCPC_REG_MASK, ®)) + tcpc_write(port, TCPC_REG_MASK, reg | TCPC_REG_MASK_BC_LVL); + + /* flush rx fifo in case messages have been coming our way */ + fusb302_flush_rx_fifo(port); + + } else { + tcpc_write(port, TCPC_REG_SWITCHES0, reg); + + /* Enable BC_LVL interrupt when disabling PD comm */ + if (!tcpc_read(port, TCPC_REG_MASK, ®)) + tcpc_write(port, TCPC_REG_MASK, reg & ~TCPC_REG_MASK_BC_LVL); + } + + fusb302_auto_goodcrc_enable(port, enable); + + return 0; +} + +/* Return true if our Rx FIFO is empty */ +static int fusb302_rx_fifo_is_empty(int port) { + int reg, ret; + + i2c_master_lock(tcpc_config[port].i2c_host_port); + + ret = (!tcpc_read(port, TCPC_REG_STATUS1, ®)) + && (reg & TCPC_REG_STATUS1_RX_EMPTY); + + return ret; +} + +static int fusb302_tcpm_get_message(int port, uint32_t *payload, int *head) { + /* + * This is the buffer that will get the burst-read data + * from the fusb302. + * + * It's re-used in a couple different spots, the worst of which + * is the PD packet (not header) and CRC. + * maximum size necessary = 28 + 4 = 32 + */ + uint8_t buf[32]; + int rv, len; + + /* If our FIFO is empty then we have no packet */ + if (fusb302_rx_fifo_is_empty(port)) + return EC_ERROR_UNKNOWN; + + /* Read until we have a non-GoodCRC packet or an empty FIFO */ + do { + buf[0] = TCPC_REG_FIFOS; + i2c_master_lock(tcpc_config[port].i2c_host_port); + + /* + * PART 1 OF BURST READ: Write in register address. + * Issue a START, no STOP. + */ + rv = tcpc_xfer(port, buf, 1, 0, 0, I2C_XFER_START); + + /* + * PART 2 OF BURST READ: Read up to the header. + * Issue a repeated START, no STOP. + * only grab three bytes so we can get the header + * and determine how many more bytes we need to read. + * TODO: Check token to ensure valid packet. + */ + rv |= tcpc_xfer(port, 0, 0, buf, 3, I2C_XFER_START); + + /* Grab the header */ + *head = (buf[1] & 0xFF); + *head |= ((buf[2] << 8) & 0xFF00); + + /* figure out packet length, subtract header bytes */ + len = get_num_bytes(*head) - 2; + + /* + * PART 3 OF BURST READ: Read everything else. + * No START, but do issue a STOP at the end. + * add 4 to len to read CRC out + */ + rv |= tcpc_xfer(port, 0, 0, buf, len + 4, I2C_XFER_STOP); + + } while (!rv && PACKET_IS_GOOD_CRC(*head) && !fusb302_rx_fifo_is_empty(port)); + + if (!rv) { + /* Discard GoodCRC packets */ + if (PACKET_IS_GOOD_CRC(*head)) + rv = EC_ERROR_UNKNOWN; + else + memcpy(payload, buf, len); + } + + /* + * If our FIFO is non-empty then we may have a packet, we may get + * fewer interrupts than packets due to interrupt latency. + */ + //if (!fusb302_rx_fifo_is_empty(port)) + // task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_RX, 0); + return rv; +} + +static int fusb302_tcpm_transmit(int port, enum tcpm_transmit_type type, + uint16_t header, const uint32_t *data) { + /* + * this is the buffer that will be burst-written into the fusb302 + * maximum size necessary = + * 1: FIFO register address + * 4: SOP* tokens + * 1: Token that signifies "next X bytes are not tokens" + * 30: 2 for header and up to 7*4 = 28 for rest of message + * 1: "Insert CRC" Token + * 1: EOP Token + * 1: "Turn transmitter off" token + * 1: "Star Transmission" Command + * - + * 40: 40 bytes worst-case + */ + uint8_t buf[40]; + int buf_pos = 0; + + int reg; + + /* Flush the TXFIFO */ + fusb302_flush_tx_fifo(port); + + switch (type) { + case TCPC_TX_SOP: + + /* put register address first for of burst tcpc write */ + buf[buf_pos++] = TCPC_REG_FIFOS; + + /* Write the SOP Ordered Set into TX FIFO */ + buf[buf_pos++] = fusb302_TKN_SYNC1; + buf[buf_pos++] = fusb302_TKN_SYNC1; + buf[buf_pos++] = fusb302_TKN_SYNC1; + buf[buf_pos++] = fusb302_TKN_SYNC2; + + fusb302_send_message(port, header, data, buf, buf_pos); + // wait for the GoodCRC to come back before we let the rest + // of the code do stuff like change polarity and miss it + delay_us(600); + return; + case TCPC_TX_HARD_RESET: + i2c_master_lock(tcpc_config[port].i2c_host_port); + /* Simply hit the SEND_HARD_RESET bit */ + tcpc_read(port, TCPC_REG_CONTROL3, ®); + reg |= TCPC_REG_CONTROL3_SEND_HARDRESET; + tcpc_write(port, TCPC_REG_CONTROL3, reg); + + break; + case TCPC_TX_BIST_MODE_2: + i2c_master_lock(tcpc_config[port].i2c_host_port); + /* Hit the BIST_MODE2 bit and start TX */ + tcpc_read(port, TCPC_REG_CONTROL1, ®); + reg |= TCPC_REG_CONTROL1_BIST_MODE2; + tcpc_write(port, TCPC_REG_CONTROL1, reg); + + tcpc_read(port, TCPC_REG_CONTROL0, ®); + reg |= TCPC_REG_CONTROL0_TX_START; + tcpc_write(port, TCPC_REG_CONTROL0, reg); + + //task_wait_event(PD_T_BIST_TRANSMIT); + + /* Clear BIST mode bit, TX_START is self-clearing */ + tcpc_read(port, TCPC_REG_CONTROL1, ®); + reg &= ~TCPC_REG_CONTROL1_BIST_MODE2; + tcpc_write(port, TCPC_REG_CONTROL1, reg); + + break; + default: + return EC_ERROR_UNIMPLEMENTED; + } + + return 0; +} + +#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC +static int fusb302_tcpm_get_vbus_level(int port) +{ + int reg; + + /* Read status register */ + i2c_master_lock(tcpc_config[port].i2c_host_port); + tcpc_read(port, TCPC_REG_STATUS0, ®); + + + return (reg & TCPC_REG_STATUS0_VBUSOK) ? 1 : 0; +} +#endif + +void fusb302_tcpc_alert(int port) { + /* interrupt has been received */ + int interrupt; + int interrupta; + int interruptb; + + /* reading interrupt registers clears them */ + + i2c_master_lock(tcpc_config[port].i2c_host_port); + tcpc_read(port, TCPC_REG_INTERRUPT, &interrupt); + tcpc_read(port, TCPC_REG_INTERRUPTA, &interrupta); + tcpc_read(port, TCPC_REG_INTERRUPTB, &interruptb); + + /* + * Ignore BC_LVL changes when transmitting / receiving PD, + * since CC level will constantly change. + */ + if (state[port].rx_enable) + interrupt &= ~TCPC_REG_INTERRUPT_BC_LVL; + + if (interrupt & TCPC_REG_INTERRUPT_BC_LVL) { + /* CC Status change */ + //task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0); + } + + if (interrupt & TCPC_REG_INTERRUPT_COLLISION) { + /* packet sending collided */ + pd_transmit_complete(port, TCPC_TX_COMPLETE_FAILED); + } + + /* GoodCRC was received, our FIFO is now non-empty */ + if (interrupta & TCPC_REG_INTERRUPTA_TX_SUCCESS) { + //task_set_event(PD_PORT_TO_TASK_ID(port), + // PD_EVENT_RX, 0); + + pd_transmit_complete(port, TCPC_TX_COMPLETE_SUCCESS); + } + + if (interrupta & TCPC_REG_INTERRUPTA_RETRYFAIL) { + /* all retries have failed to get a GoodCRC */ + pd_transmit_complete(port, TCPC_TX_COMPLETE_FAILED); + } + + if (interrupta & TCPC_REG_INTERRUPTA_HARDSENT) { + /* hard reset has been sent */ + + /* bring FUSB302 out of reset */ + fusb302_pd_reset(port); + + pd_transmit_complete(port, TCPC_TX_COMPLETE_SUCCESS); + } + + if (interrupta & TCPC_REG_INTERRUPTA_HARDRESET) { + /* hard reset has been received */ + + /* bring FUSB302 out of reset */ + fusb302_pd_reset(port); + + pd_execute_hard_reset(port); + + //task_wake(PD_PORT_TO_TASK_ID(port)); + } + + if (interruptb & TCPC_REG_INTERRUPTB_GCRCSENT) { + /* Packet received and GoodCRC sent */ + /* (this interrupt fires after the GoodCRC finishes) */ + if (state[port].rx_enable) { + //task_set_event(PD_PORT_TO_TASK_ID(port), + // PD_EVENT_RX, 0); + } else { + /* flush rx fifo if rx isn't enabled */ + fusb302_flush_rx_fifo(port); + } + } +} + +/* For BIST receiving */ +void tcpm_set_bist_test_data(int port) { + int reg; + + i2c_master_lock(tcpc_config[port].i2c_host_port); + + /* Read control3 register */ + tcpc_read(port, TCPC_REG_CONTROL3, ®); + + /* Set the BIST_TMODE bit (Clears on Hard Reset) */ + reg |= TCPC_REG_CONTROL3_BIST_TMODE; + + /* Write the updated value */ + tcpc_write(port, TCPC_REG_CONTROL3, reg); + +} + +const struct tcpm_drv fusb302_tcpm_drv = { .init = &fusb302_tcpm_init, + .release = &fusb302_tcpm_release, .get_cc = &fusb302_tcpm_get_cc, +#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC + .get_vbus_level = &fusb302_tcpm_get_vbus_level, +#endif + .select_rp_value = &fusb302_tcpm_select_rp_value, .set_cc = + &fusb302_tcpm_set_cc, + .set_polarity = &fusb302_tcpm_set_polarity, .set_vconn = + &fusb302_tcpm_set_vconn, .set_msg_header = + &fusb302_tcpm_set_msg_header, .set_rx_enable = + &fusb302_tcpm_set_rx_enable, .get_message = + &fusb302_tcpm_get_message, .transmit = &fusb302_tcpm_transmit, + .tcpc_alert = &fusb302_tcpc_alert, }; diff --git a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.h b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.h new file mode 100644 index 00000000..b6404659 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.h @@ -0,0 +1,250 @@ +/* + FUSB302.h - Library for interacting with the FUSB302B chip. + Copyright 2010 The Chromium OS Authors + Copyright 2017 Jason Cerundolo + Released under an MIT license. See LICENSE file. +*/ + +#ifndef fusb302_H +#define fusb302_H + +#include +#include "usb_pd_tcpm.h" +#include "USBC_PD/usb_pd.h" + +/* Chip Device ID - 302A or 302B */ +#define fusb302_DEVID_302A 0x08 +#define fusb302_DEVID_302B 0x09 + +/* I2C slave address varies by part number */ +/* FUSB302BUCX / FUSB302BMPX */ +#define fusb302_I2C_SLAVE_ADDR 0x22 // 7-bit address for Arduino +/* FUSB302B01MPX */ +#define fusb302_I2C_SLAVE_ADDR_B01 0x23 +/* FUSB302B10MPX */ +#define fusb302_I2C_SLAVE_ADDR_B10 0x24 +/* FUSB302B11MPX */ +#define fusb302_I2C_SLAVE_ADDR_B11 0x25 + +/* Default retry count for transmitting */ +#define PD_RETRY_COUNT 3 + +/* Time to wait for TCPC to complete transmit */ +#define PD_T_TCPC_TX_TIMEOUT (100*MSEC) + +#define TCPC_REG_DEVICE_ID 0x01 + +#define TCPC_REG_SWITCHES0 0x02 +#define TCPC_REG_SWITCHES0_CC2_PU_EN (1<<7) +#define TCPC_REG_SWITCHES0_CC1_PU_EN (1<<6) +#define TCPC_REG_SWITCHES0_VCONN_CC2 (1<<5) +#define TCPC_REG_SWITCHES0_VCONN_CC1 (1<<4) +#define TCPC_REG_SWITCHES0_MEAS_CC2 (1<<3) +#define TCPC_REG_SWITCHES0_MEAS_CC1 (1<<2) +#define TCPC_REG_SWITCHES0_CC2_PD_EN (1<<1) +#define TCPC_REG_SWITCHES0_CC1_PD_EN (1<<0) + +#define TCPC_REG_SWITCHES1 0x03 +#define TCPC_REG_SWITCHES1_POWERROLE (1<<7) +#define TCPC_REG_SWITCHES1_SPECREV1 (1<<6) +#define TCPC_REG_SWITCHES1_SPECREV0 (1<<5) +#define TCPC_REG_SWITCHES1_DATAROLE (1<<4) +#define TCPC_REG_SWITCHES1_AUTO_GCRC (1<<2) +#define TCPC_REG_SWITCHES1_TXCC2_EN (1<<1) +#define TCPC_REG_SWITCHES1_TXCC1_EN (1<<0) + +#define TCPC_REG_MEASURE 0x04 +#define TCPC_REG_MEASURE_VBUS (1<<6) +#define TCPC_REG_MEASURE_MDAC_MV(mv) (((mv)/42) & 0x3f) + +#define TCPC_REG_CONTROL0 0x06 +#define TCPC_REG_CONTROL0_TX_FLUSH (1<<6) +#define TCPC_REG_CONTROL0_INT_MASK (1<<5) +#define TCPC_REG_CONTROL0_HOST_CUR_MASK (3<<2) +#define TCPC_REG_CONTROL0_HOST_CUR_3A0 (3<<2) +#define TCPC_REG_CONTROL0_HOST_CUR_1A5 (2<<2) +#define TCPC_REG_CONTROL0_HOST_CUR_USB (1<<2) +#define TCPC_REG_CONTROL0_TX_START (1<<0) + +#define TCPC_REG_CONTROL1 0x07 +#define TCPC_REG_CONTROL1_ENSOP2DB (1<<6) +#define TCPC_REG_CONTROL1_ENSOP1DB (1<<5) +#define TCPC_REG_CONTROL1_BIST_MODE2 (1<<4) +#define TCPC_REG_CONTROL1_RX_FLUSH (1<<2) +#define TCPC_REG_CONTROL1_ENSOP2 (1<<1) +#define TCPC_REG_CONTROL1_ENSOP1 (1<<0) + +#define TCPC_REG_CONTROL2 0x08 +/* two-bit field, valid values below */ +#define TCPC_REG_CONTROL2_MODE (1<<1) +#define TCPC_REG_CONTROL2_MODE_DFP (0x3) +#define TCPC_REG_CONTROL2_MODE_UFP (0x2) +#define TCPC_REG_CONTROL2_MODE_DRP (0x1) +#define TCPC_REG_CONTROL2_MODE_POS (1) +#define TCPC_REG_CONTROL2_TOGGLE (1<<0) + +#define TCPC_REG_CONTROL3 0x09 +#define TCPC_REG_CONTROL3_SEND_HARDRESET (1<<6) +#define TCPC_REG_CONTROL3_BIST_TMODE (1<<5) /* 302B Only */ +#define TCPC_REG_CONTROL3_AUTO_HARDRESET (1<<4) +#define TCPC_REG_CONTROL3_AUTO_SOFTRESET (1<<3) +/* two-bit field */ +#define TCPC_REG_CONTROL3_N_RETRIES (1<<1) +#define TCPC_REG_CONTROL3_N_RETRIES_POS (1) +#define TCPC_REG_CONTROL3_N_RETRIES_SIZE (2) +#define TCPC_REG_CONTROL3_AUTO_RETRY (1<<0) + +#define TCPC_REG_MASK 0x0A +#define TCPC_REG_MASK_VBUSOK (1<<7) +#define TCPC_REG_MASK_ACTIVITY (1<<6) +#define TCPC_REG_MASK_COMP_CHNG (1<<5) +#define TCPC_REG_MASK_CRC_CHK (1<<4) +#define TCPC_REG_MASK_ALERT (1<<3) +#define TCPC_REG_MASK_WAKE (1<<2) +#define TCPC_REG_MASK_COLLISION (1<<1) +#define TCPC_REG_MASK_BC_LVL (1<<0) + +#define TCPC_REG_POWER 0x0B +#define TCPC_REG_POWER_PWR (1<<0) /* four-bit field */ +#define TCPC_REG_POWER_PWR_LOW 0x1 /* Bandgap + Wake circuitry */ +#define TCPC_REG_POWER_PWR_MEDIUM 0x3 /* LOW + Receiver + Current refs */ +#define TCPC_REG_POWER_PWR_HIGH 0x7 /* MEDIUM + Measure block */ +#define TCPC_REG_POWER_PWR_ALL 0xF /* HIGH + Internal Oscillator */ + +#define TCPC_REG_RESET 0x0C +#define TCPC_REG_RESET_PD_RESET (1<<1) +#define TCPC_REG_RESET_SW_RESET (1<<0) + +#define TCPC_REG_MASKA 0x0E +#define TCPC_REG_MASKA_OCP_TEMP (1<<7) +#define TCPC_REG_MASKA_TOGDONE (1<<6) +#define TCPC_REG_MASKA_SOFTFAIL (1<<5) +#define TCPC_REG_MASKA_RETRYFAIL (1<<4) +#define TCPC_REG_MASKA_HARDSENT (1<<3) +#define TCPC_REG_MASKA_TX_SUCCESS (1<<2) +#define TCPC_REG_MASKA_SOFTRESET (1<<1) +#define TCPC_REG_MASKA_HARDRESET (1<<0) + +#define TCPC_REG_MASKB 0x0F +#define TCPC_REG_MASKB_GCRCSENT (1<<0) + +#define TCPC_REG_STATUS0A 0x3C +#define TCPC_REG_STATUS0A_SOFTFAIL (1<<5) +#define TCPC_REG_STATUS0A_RETRYFAIL (1<<4) +#define TCPC_REG_STATUS0A_POWER (1<<2) /* two-bit field */ +#define TCPC_REG_STATUS0A_RX_SOFT_RESET (1<<1) +#define TCPC_REG_STATUS0A_RX_HARD_RESET (1<<0) + +#define TCPC_REG_STATUS1A 0x3D +/* three-bit field, valid values below */ +#define TCPC_REG_STATUS1A_TOGSS (1<<3) +#define TCPC_REG_STATUS1A_TOGSS_RUNNING 0x0 +#define TCPC_REG_STATUS1A_TOGSS_SRC1 0x1 +#define TCPC_REG_STATUS1A_TOGSS_SRC2 0x2 +#define TCPC_REG_STATUS1A_TOGSS_SNK1 0x5 +#define TCPC_REG_STATUS1A_TOGSS_SNK2 0x6 +#define TCPC_REG_STATUS1A_TOGSS_AA 0x7 +#define TCPC_REG_STATUS1A_TOGSS_POS (3) +#define TCPC_REG_STATUS1A_TOGSS_MASK (0x7) + +#define TCPC_REG_STATUS1A_RXSOP2DB (1<<2) +#define TCPC_REG_STATUS1A_RXSOP1DB (1<<1) +#define TCPC_REG_STATUS1A_RXSOP (1<<0) + +#define TCPC_REG_INTERRUPTA 0x3E +#define TCPC_REG_INTERRUPTA_OCP_TEMP (1<<7) +#define TCPC_REG_INTERRUPTA_TOGDONE (1<<6) +#define TCPC_REG_INTERRUPTA_SOFTFAIL (1<<5) +#define TCPC_REG_INTERRUPTA_RETRYFAIL (1<<4) +#define TCPC_REG_INTERRUPTA_HARDSENT (1<<3) +#define TCPC_REG_INTERRUPTA_TX_SUCCESS (1<<2) +#define TCPC_REG_INTERRUPTA_SOFTRESET (1<<1) +#define TCPC_REG_INTERRUPTA_HARDRESET (1<<0) + +#define TCPC_REG_INTERRUPTB 0x3F +#define TCPC_REG_INTERRUPTB_GCRCSENT (1<<0) + +#define TCPC_REG_STATUS0 0x40 +#define TCPC_REG_STATUS0_VBUSOK (1<<7) +#define TCPC_REG_STATUS0_ACTIVITY (1<<6) +#define TCPC_REG_STATUS0_COMP (1<<5) +#define TCPC_REG_STATUS0_CRC_CHK (1<<4) +#define TCPC_REG_STATUS0_ALERT (1<<3) +#define TCPC_REG_STATUS0_WAKE (1<<2) +#define TCPC_REG_STATUS0_BC_LVL1 (1<<1) /* two-bit field */ +#define TCPC_REG_STATUS0_BC_LVL0 (1<<0) /* two-bit field */ + +#define TCPC_REG_STATUS1 0x41 +#define TCPC_REG_STATUS1_RXSOP2 (1<<7) +#define TCPC_REG_STATUS1_RXSOP1 (1<<6) +#define TCPC_REG_STATUS1_RX_EMPTY (1<<5) +#define TCPC_REG_STATUS1_RX_FULL (1<<4) +#define TCPC_REG_STATUS1_TX_EMPTY (1<<3) +#define TCPC_REG_STATUS1_TX_FULL (1<<2) + +#define TCPC_REG_INTERRUPT 0x42 +#define TCPC_REG_INTERRUPT_VBUSOK (1<<7) +#define TCPC_REG_INTERRUPT_ACTIVITY (1<<6) +#define TCPC_REG_INTERRUPT_COMP_CHNG (1<<5) +#define TCPC_REG_INTERRUPT_CRC_CHK (1<<4) +#define TCPC_REG_INTERRUPT_ALERT (1<<3) +#define TCPC_REG_INTERRUPT_WAKE (1<<2) +#define TCPC_REG_INTERRUPT_COLLISION (1<<1) +#define TCPC_REG_INTERRUPT_BC_LVL (1<<0) + +#define TCPC_REG_FIFOS 0x43 + +/* Tokens defined for the FUSB302 TX FIFO */ +enum fusb302_txfifo_tokens { + fusb302_TKN_TXON = 0xA1, + fusb302_TKN_SYNC1 = 0x12, + fusb302_TKN_SYNC2 = 0x13, + fusb302_TKN_SYNC3 = 0x1B, + fusb302_TKN_RST1 = 0x15, + fusb302_TKN_RST2 = 0x16, + fusb302_TKN_PACKSYM = 0x80, + fusb302_TKN_JAMCRC = 0xFF, + fusb302_TKN_EOP = 0x14, + fusb302_TKN_TXOFF = 0xFE, +}; + +extern const struct tcpm_drv fusb302_tcpm_drv; + +/* +// Common methods for TCPM implementations +int fusb302_init(void); +int fusb302_get_cc(int *cc1, int *cc2); +int fusb302_get_vbus_level(void); +int fusb302_select_rp_value(int rp); +int fusb302_set_cc(int pull); +int fusb302_set_polarity(int polarity); +int fusb302_set_vconn(int enable); +int fusb302_set_msg_header(int power_role, int data_role); +int fusb302_set_rx_enable(int enable); +int fusb302_get_message(uint32_t *payload, int *head); +int fusb302_transmit(enum tcpm_transmit_type type, + uint16_t header, const uint32_t *data); +//int alert(void); +void fusb302_pd_reset(int port); +void fusb302_auto_goodcrc_enable(int enable); +int fusb302_convert_bc_lvl(int bc_lvl); +void fusb302_detect_cc_pin_source_manual(int *cc1_lvl, int *cc2_lvl); +int fusb302_measure_cc_pin_source(int cc_measure); +void fusb302_detect_cc_pin_sink(int *cc1, int *cc2); +int fusb302_send_message(uint16_t header, const uint32_t *data, + uint8_t *buf, int buf_pos); +void fusb302_flush_rx_fifo(int port); +void fusb302_flush_tx_fifo(int port); +void fusb302_clear_int_pin(void); +void fusb302_set_bist_test_data(void); +int fusb302_get_chip_id(int *id); +uint32_t fusb302_get_interrupt_reason(void); +int fusb302_tcpc_write(int reg, int val); +int fusb302_tcpc_read(int reg, int *val); +int fusb302_tcpc_xfer(const uint8_t *out, + int out_size, uint8_t *in, + int in_size, int flags); +*/ + +#endif /* fusb302_H */ + diff --git a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.hpp b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.hpp deleted file mode 100644 index 30f1f304..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * FUSB302.hpp - * - * Created on: 11-06-2020 - * Author: Ralim - */ - -#ifndef FUSB302_H_ -#define FUSB302_H_ -#include "BSP.h" -#include "FUSB302_includes.h" -#include "I2C_Wrapper.hpp" -//While the ST4500 is nice, the FUSB302 is _cheap_ so its what is used in the TS80P for example - -class FUSB302 { -public: - //Returns true if the FUSB302 is detected on the I2C bus - bool detect(); - -private: - // Bring up out of reset and clear fifo's - void fusb302_reset(); - void flush_rx_fifo(); - void flush_tx_fifo(); - void enable_auto_good_crc(); - int set_rp_value(int rp); - int set_cc(int pull); - struct fusb302_chip_state { - int cc_polarity; - int vconn_enabled; - /* 1 = pulling up (DFP) 0 = pulling down (UFP) */ - int pulling_up; - int rx_enable; - uint8_t mdac_vnc; - uint8_t mdac_rd; - }; - fusb302_chip_state state; -}; - -#endif /* LIS2DH12_HPP_ */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/FUSB302_includes.h b/workspace/TS100/Core/Drivers/FUSB302/FUSB302_includes.h deleted file mode 100644 index ff9c2cd9..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/FUSB302_includes.h +++ /dev/null @@ -1,204 +0,0 @@ -#ifndef FUSB302_INCLUDES_H_ -#define FUSB302_INCLUDES_H_ - -/* Whole bunch of includes to make working with the FUSB302 easier*/ - -/* Chip Device ID - 302A or 302B */ -#define fusb302_DEVID_302A 0x08 -#define fusb302_DEVID_302B 0x09 - -/* I2C slave address varies by part number */ -/* FUSB302BUCX / FUSB302BMPX */ -#define fusb302_I2C_SLAVE_ADDR 0x22 // 7-bit address for Arduino -/* FUSB302B01MPX */ -#define fusb302_I2C_SLAVE_ADDR_B01 0x23 -/* FUSB302B10MPX */ -#define fusb302_I2C_SLAVE_ADDR_B10 0x24 -/* FUSB302B11MPX */ -#define fusb302_I2C_SLAVE_ADDR_B11 0x25 - -/* Default retry count for transmitting */ -#define PD_RETRY_COUNT 3 - -/* Time to wait for TCPC to complete transmit */ -#define PD_T_TCPC_TX_TIMEOUT (100 * MSEC) - -#define TCPC_REG_DEVICE_ID 0x01 - -#define TCPC_REG_SWITCHES0 0x02 -#define TCPC_REG_SWITCHES0_CC2_PU_EN (1 << 7) -#define TCPC_REG_SWITCHES0_CC1_PU_EN (1 << 6) -#define TCPC_REG_SWITCHES0_VCONN_CC2 (1 << 5) -#define TCPC_REG_SWITCHES0_VCONN_CC1 (1 << 4) -#define TCPC_REG_SWITCHES0_MEAS_CC2 (1 << 3) -#define TCPC_REG_SWITCHES0_MEAS_CC1 (1 << 2) -#define TCPC_REG_SWITCHES0_CC2_PD_EN (1 << 1) -#define TCPC_REG_SWITCHES0_CC1_PD_EN (1 << 0) - -#define TCPC_REG_SWITCHES1 0x03 -#define TCPC_REG_SWITCHES1_POWERROLE (1 << 7) -#define TCPC_REG_SWITCHES1_SPECREV1 (1 << 6) -#define TCPC_REG_SWITCHES1_SPECREV0 (1 << 5) -#define TCPC_REG_SWITCHES1_DATAROLE (1 << 4) -#define TCPC_REG_SWITCHES1_AUTO_GCRC (1 << 2) -#define TCPC_REG_SWITCHES1_TXCC2_EN (1 << 1) -#define TCPC_REG_SWITCHES1_TXCC1_EN (1 << 0) - -#define TCPC_REG_MEASURE 0x04 -#define TCPC_REG_MEASURE_VBUS (1 << 6) -#define TCPC_REG_MEASURE_MDAC_MV(mv) (((mv) / 42) & 0x3f) - -#define TCPC_REG_CONTROL0 0x06 -#define TCPC_REG_CONTROL0_TX_FLUSH (1 << 6) -#define TCPC_REG_CONTROL0_INT_MASK (1 << 5) -#define TCPC_REG_CONTROL0_HOST_CUR_MASK (3 << 2) -#define TCPC_REG_CONTROL0_HOST_CUR_3A0 (3 << 2) -#define TCPC_REG_CONTROL0_HOST_CUR_1A5 (2 << 2) -#define TCPC_REG_CONTROL0_HOST_CUR_USB (1 << 2) -#define TCPC_REG_CONTROL0_TX_START (1 << 0) - -#define TCPC_REG_CONTROL1 0x07 -#define TCPC_REG_CONTROL1_ENSOP2DB (1 << 6) -#define TCPC_REG_CONTROL1_ENSOP1DB (1 << 5) -#define TCPC_REG_CONTROL1_BIST_MODE2 (1 << 4) -#define TCPC_REG_CONTROL1_RX_FLUSH (1 << 2) -#define TCPC_REG_CONTROL1_ENSOP2 (1 << 1) -#define TCPC_REG_CONTROL1_ENSOP1 (1 << 0) - -#define TCPC_REG_CONTROL2 0x08 -/* two-bit field, valid values below */ -#define TCPC_REG_CONTROL2_MODE (1 << 1) -#define TCPC_REG_CONTROL2_MODE_DFP (0x3) -#define TCPC_REG_CONTROL2_MODE_UFP (0x2) -#define TCPC_REG_CONTROL2_MODE_DRP (0x1) -#define TCPC_REG_CONTROL2_MODE_POS (1) -#define TCPC_REG_CONTROL2_TOGGLE (1 << 0) - -#define TCPC_REG_CONTROL3 0x09 -#define TCPC_REG_CONTROL3_SEND_HARDRESET (1 << 6) -#define TCPC_REG_CONTROL3_BIST_TMODE (1 << 5) /* 302B Only */ -#define TCPC_REG_CONTROL3_AUTO_HARDRESET (1 << 4) -#define TCPC_REG_CONTROL3_AUTO_SOFTRESET (1 << 3) -/* two-bit field */ -#define TCPC_REG_CONTROL3_N_RETRIES (1 << 1) -#define TCPC_REG_CONTROL3_N_RETRIES_POS (1) -#define TCPC_REG_CONTROL3_N_RETRIES_SIZE (2) -#define TCPC_REG_CONTROL3_AUTO_RETRY (1 << 0) - -#define TCPC_REG_MASK 0x0A -#define TCPC_REG_MASK_VBUSOK (1 << 7) -#define TCPC_REG_MASK_ACTIVITY (1 << 6) -#define TCPC_REG_MASK_COMP_CHNG (1 << 5) -#define TCPC_REG_MASK_CRC_CHK (1 << 4) -#define TCPC_REG_MASK_ALERT (1 << 3) -#define TCPC_REG_MASK_WAKE (1 << 2) -#define TCPC_REG_MASK_COLLISION (1 << 1) -#define TCPC_REG_MASK_BC_LVL (1 << 0) - -#define TCPC_REG_POWER 0x0B -#define TCPC_REG_POWER_PWR (1 << 0) /* four-bit field */ -#define TCPC_REG_POWER_PWR_LOW 0x1 /* Bandgap + Wake circuitry */ -#define TCPC_REG_POWER_PWR_MEDIUM 0x3 /* LOW + Receiver + Current refs */ -#define TCPC_REG_POWER_PWR_HIGH 0x7 /* MEDIUM + Measure block */ -#define TCPC_REG_POWER_PWR_ALL 0xF /* HIGH + Internal Oscillator */ - -#define TCPC_REG_RESET 0x0C -#define TCPC_REG_RESET_PD_RESET (1 << 1) -#define TCPC_REG_RESET_SW_RESET (1 << 0) - -#define TCPC_REG_MASKA 0x0E -#define TCPC_REG_MASKA_OCP_TEMP (1 << 7) -#define TCPC_REG_MASKA_TOGDONE (1 << 6) -#define TCPC_REG_MASKA_SOFTFAIL (1 << 5) -#define TCPC_REG_MASKA_RETRYFAIL (1 << 4) -#define TCPC_REG_MASKA_HARDSENT (1 << 3) -#define TCPC_REG_MASKA_TX_SUCCESS (1 << 2) -#define TCPC_REG_MASKA_SOFTRESET (1 << 1) -#define TCPC_REG_MASKA_HARDRESET (1 << 0) - -#define TCPC_REG_MASKB 0x0F -#define TCPC_REG_MASKB_GCRCSENT (1 << 0) - -#define TCPC_REG_STATUS0A 0x3C -#define TCPC_REG_STATUS0A_SOFTFAIL (1 << 5) -#define TCPC_REG_STATUS0A_RETRYFAIL (1 << 4) -#define TCPC_REG_STATUS0A_POWER (1 << 2) /* two-bit field */ -#define TCPC_REG_STATUS0A_RX_SOFT_RESET (1 << 1) -#define TCPC_REG_STATUS0A_RX_HARD_RESET (1 << 0) - -#define TCPC_REG_STATUS1A 0x3D -/* three-bit field, valid values below */ -#define TCPC_REG_STATUS1A_TOGSS (1 << 3) -#define TCPC_REG_STATUS1A_TOGSS_RUNNING 0x0 -#define TCPC_REG_STATUS1A_TOGSS_SRC1 0x1 -#define TCPC_REG_STATUS1A_TOGSS_SRC2 0x2 -#define TCPC_REG_STATUS1A_TOGSS_SNK1 0x5 -#define TCPC_REG_STATUS1A_TOGSS_SNK2 0x6 -#define TCPC_REG_STATUS1A_TOGSS_AA 0x7 -#define TCPC_REG_STATUS1A_TOGSS_POS (3) -#define TCPC_REG_STATUS1A_TOGSS_MASK (0x7) - -#define TCPC_REG_STATUS1A_RXSOP2DB (1 << 2) -#define TCPC_REG_STATUS1A_RXSOP1DB (1 << 1) -#define TCPC_REG_STATUS1A_RXSOP (1 << 0) - -#define TCPC_REG_INTERRUPTA 0x3E -#define TCPC_REG_INTERRUPTA_OCP_TEMP (1 << 7) -#define TCPC_REG_INTERRUPTA_TOGDONE (1 << 6) -#define TCPC_REG_INTERRUPTA_SOFTFAIL (1 << 5) -#define TCPC_REG_INTERRUPTA_RETRYFAIL (1 << 4) -#define TCPC_REG_INTERRUPTA_HARDSENT (1 << 3) -#define TCPC_REG_INTERRUPTA_TX_SUCCESS (1 << 2) -#define TCPC_REG_INTERRUPTA_SOFTRESET (1 << 1) -#define TCPC_REG_INTERRUPTA_HARDRESET (1 << 0) - -#define TCPC_REG_INTERRUPTB 0x3F -#define TCPC_REG_INTERRUPTB_GCRCSENT (1 << 0) - -#define TCPC_REG_STATUS0 0x40 -#define TCPC_REG_STATUS0_VBUSOK (1 << 7) -#define TCPC_REG_STATUS0_ACTIVITY (1 << 6) -#define TCPC_REG_STATUS0_COMP (1 << 5) -#define TCPC_REG_STATUS0_CRC_CHK (1 << 4) -#define TCPC_REG_STATUS0_ALERT (1 << 3) -#define TCPC_REG_STATUS0_WAKE (1 << 2) -#define TCPC_REG_STATUS0_BC_LVL1 (1 << 1) /* two-bit field */ -#define TCPC_REG_STATUS0_BC_LVL0 (1 << 0) /* two-bit field */ - -#define TCPC_REG_STATUS1 0x41 -#define TCPC_REG_STATUS1_RXSOP2 (1 << 7) -#define TCPC_REG_STATUS1_RXSOP1 (1 << 6) -#define TCPC_REG_STATUS1_RX_EMPTY (1 << 5) -#define TCPC_REG_STATUS1_RX_FULL (1 << 4) -#define TCPC_REG_STATUS1_TX_EMPTY (1 << 3) -#define TCPC_REG_STATUS1_TX_FULL (1 << 2) - -#define TCPC_REG_INTERRUPT 0x42 -#define TCPC_REG_INTERRUPT_VBUSOK (1 << 7) -#define TCPC_REG_INTERRUPT_ACTIVITY (1 << 6) -#define TCPC_REG_INTERRUPT_COMP_CHNG (1 << 5) -#define TCPC_REG_INTERRUPT_CRC_CHK (1 << 4) -#define TCPC_REG_INTERRUPT_ALERT (1 << 3) -#define TCPC_REG_INTERRUPT_WAKE (1 << 2) -#define TCPC_REG_INTERRUPT_COLLISION (1 << 1) -#define TCPC_REG_INTERRUPT_BC_LVL (1 << 0) - -#define TCPC_REG_FIFOS 0x43 - -/* Tokens defined for the FUSB302 TX FIFO */ -enum fusb302_txfifo_tokens { - fusb302_TKN_TXON = 0xA1, - fusb302_TKN_SYNC1 = 0x12, - fusb302_TKN_SYNC2 = 0x13, - fusb302_TKN_SYNC3 = 0x1B, - fusb302_TKN_RST1 = 0x15, - fusb302_TKN_RST2 = 0x16, - fusb302_TKN_PACKSYM = 0x80, - fusb302_TKN_JAMCRC = 0xFF, - fusb302_TKN_EOP = 0x14, - fusb302_TKN_TXOFF = 0xFE, -}; - -#define PACKET_IS_GOOD_CRC(head) (PD_HEADER_TYPE(head) == PD_CTRL_GOOD_CRC && \ - PD_HEADER_CNT(head) == 0) -#endif \ No newline at end of file diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h new file mode 100644 index 00000000..cd520d3e --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h @@ -0,0 +1,1799 @@ +/* Copyright (c) 2014 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 Power delivery module */ + +#ifndef __USB_PD_H +#define __USB_PD_H + +#include "tcpm_driver.h" +#include "usb_pd_driver.h" + +/* Time units in microseconds */ +#define MSEC (1000) +#define SECOND (1000000) +#define MINUTE (60000000) +#define HOUR (3600000000ull) /* Too big to fit in a signed int */ + +/* PD Host command timeout */ +#define PD_HOST_COMMAND_TIMEOUT_US SECOND + +#ifdef CONFIG_USB_PD_PORT_COUNT +/* + * Define PD_PORT_TO_TASK_ID() and TASK_ID_TO_PD_PORT() macros to + * go between PD port number and task ID. Assume that TASK_ID_PD_C0 is the + * lowest task ID and IDs are on a continuous range. + */ +#ifdef HAS_TASK_PD_C0 +#define PD_PORT_TO_TASK_ID(port) (TASK_ID_PD_C0 + (port)) +#define TASK_ID_TO_PD_PORT(id) ((id) - TASK_ID_PD_C0) +#else +#define PD_PORT_TO_TASK_ID(port) -1 /* dummy task ID */ +#define TASK_ID_TO_PD_PORT(id) 0 +#endif /* CONFIG_COMMON_RUNTIME */ +#endif /* CONFIG_USB_PD_PORT_COUNT */ + +enum pd_rx_errors { + PD_RX_ERR_INVAL = -1, /* Invalid packet */ + PD_RX_ERR_HARD_RESET = -2, /* Got a Hard-Reset packet */ + PD_RX_ERR_CRC = -3, /* CRC mismatch */ + PD_RX_ERR_ID = -4, /* Invalid ID number */ + PD_RX_ERR_UNSUPPORTED_SOP = -5, /* Unsupported SOP */ + PD_RX_ERR_CABLE_RESET = -6 /* Got a Cable-Reset packet */ +}; + +/* Events for USB PD task */ +#define PD_EVENT_RX (1<<2) /* Incoming packet event */ +#define PD_EVENT_TX (1<<3) /* Outgoing packet event */ +#define PD_EVENT_CC (1<<4) /* CC line change event */ +#define PD_EVENT_TCPC_RESET (1<<5) /* TCPC has reset */ +#define PD_EVENT_UPDATE_DUAL_ROLE (1<<6) /* DRP state has changed */ + +/* --- PD data message helpers --- */ +#define PDO_MAX_OBJECTS 7 +#define PDO_MODES (PDO_MAX_OBJECTS - 1) + +/* PDO : Power Data Object */ +/* + * 1. The vSafe5V Fixed Supply Object shall always be the first object. + * 2. The remaining Fixed Supply Objects, + * if present, shall be sent in voltage order; lowest to highest. + * 3. The Battery Supply Objects, + * if present shall be sent in Minimum Voltage order; lowest to highest. + * 4. The Variable Supply (non battery) Objects, + * if present, shall be sent in Minimum Voltage order; lowest to highest. + * 5. (PD3.0) The Augmented PDO is defined to allow extension beyond the 4 PDOs + * above by examining bits <29:28> to determine the additional PDO function. + */ +#define PDO_TYPE_FIXED (0 << 30) +#define PDO_TYPE_BATTERY (1 << 30) +#define PDO_TYPE_VARIABLE (2 << 30) +#define PDO_TYPE_AUGMENTED (3 << 30) +#define PDO_TYPE_MASK (3 << 30) + +#define PDO_FIXED_DUAL_ROLE (1 << 29) /* Dual role device */ +#define PDO_FIXED_SUSPEND (1 << 28) /* USB Suspend supported */ +#define PDO_FIXED_EXTERNAL (1 << 27) /* Externally powered */ +#define PDO_FIXED_COMM_CAP (1 << 26) /* USB Communications Capable */ +#define PDO_FIXED_DATA_SWAP (1 << 25) /* Data role swap command supported */ +#define PDO_FIXED_PEAK_CURR () /* [21..20] Peak current */ +#define PDO_FIXED_VOLT(mv) (((mv)/50) << 10) /* Voltage in 50mV units */ +#define PDO_FIXED_CURR(ma) (((ma)/10) << 0) /* Max current in 10mA units */ + +#define PDO_FIXED(mv, ma, flags) (PDO_FIXED_VOLT(mv) |\ + PDO_FIXED_CURR(ma) | (flags)) + +#define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20) +#define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10) +#define PDO_VAR_OP_CURR(ma) ((((ma) / 10) & 0x3FF) << 0) + +#define PDO_VAR(min_mv, max_mv, op_ma) \ + (PDO_VAR_MIN_VOLT(min_mv) | \ + PDO_VAR_MAX_VOLT(max_mv) | \ + PDO_VAR_OP_CURR(op_ma) | \ + PDO_TYPE_VARIABLE) + +#define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20) +#define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10) +#define PDO_BATT_OP_POWER(mw) ((((mw) / 250) & 0x3FF) << 0) + +#define PDO_BATT(min_mv, max_mv, op_mw) \ + (PDO_BATT_MIN_VOLT(min_mv) | \ + PDO_BATT_MAX_VOLT(max_mv) | \ + PDO_BATT_OP_POWER(op_mw) | \ + PDO_TYPE_BATTERY) + +/* RDO : Request Data Object */ +#define RDO_OBJ_POS(n) (((n) & 0x7) << 28) +#define RDO_POS(rdo) (((rdo) >> 28) & 0x7) +#define RDO_GIVE_BACK (1 << 27) +#define RDO_CAP_MISMATCH (1 << 26) +#define RDO_COMM_CAP (1 << 25) +#define RDO_NO_SUSPEND (1 << 24) +#define RDO_FIXED_VAR_OP_CURR(ma) ((((ma) / 10) & 0x3FF) << 10) +#define RDO_FIXED_VAR_MAX_CURR(ma) ((((ma) / 10) & 0x3FF) << 0) + +#define RDO_BATT_OP_POWER(mw) ((((mw) / 250) & 0x3FF) << 10) +#define RDO_BATT_MAX_POWER(mw) ((((mw) / 250) & 0x3FF) << 10) + +#define RDO_FIXED(n, op_ma, max_ma, flags) \ + (RDO_OBJ_POS(n) | (flags) | \ + RDO_FIXED_VAR_OP_CURR(op_ma) | \ + RDO_FIXED_VAR_MAX_CURR(max_ma)) + + +#define RDO_BATT(n, op_mw, max_mw, flags) \ + (RDO_OBJ_POS(n) | (flags) | \ + RDO_BATT_OP_POWER(op_mw) | \ + RDO_BATT_MAX_POWER(max_mw)) + +/* BDO : BIST Data Object */ +#define BDO_MODE_RECV (0 << 28) +#define BDO_MODE_TRANSMIT (1 << 28) +#define BDO_MODE_COUNTERS (2 << 28) +#define BDO_MODE_CARRIER0 (3 << 28) +#define BDO_MODE_CARRIER1 (4 << 28) +#define BDO_MODE_CARRIER2 (5 << 28) +#define BDO_MODE_CARRIER3 (6 << 28) +#define BDO_MODE_EYE (7 << 28) + +#define BDO(mode, cnt) ((mode) | ((cnt) & 0xFFFF)) + +#define SVID_DISCOVERY_MAX 16 + +/* Timers */ +#define PD_T_SINK_TX (18*MSEC) /* between 16ms and 20 */ +#define PD_T_CHUNK_SENDER_RSP (24*MSEC) /* between 24ms and 30ms */ +#define PD_T_CHUNK_SENDER_REQ (24*MSEC) /* between 24ms and 30ms */ +#define PD_T_SEND_SOURCE_CAP (100*MSEC) /* between 100ms and 200ms */ +#define PD_T_SINK_WAIT_CAP (600*MSEC) /* between 310ms and 620ms */ +#define PD_T_SINK_TRANSITION (35*MSEC) /* between 20ms and 35ms */ +#define PD_T_SOURCE_ACTIVITY (45*MSEC) /* between 40ms and 50ms */ +//#define PD_T_SENDER_RESPONSE (30*MSEC) /* between 24ms and 30ms */ +#define PD_T_SENDER_RESPONSE (100*MSEC) /* between 24ms and 30ms */ +#define PD_T_PS_TRANSITION (500*MSEC) /* between 450ms and 550ms */ +#define PD_T_PS_SOURCE_ON (480*MSEC) /* between 390ms and 480ms */ +#define PD_T_PS_SOURCE_OFF (920*MSEC) /* between 750ms and 920ms */ +#define PD_T_PS_HARD_RESET (25*MSEC) /* between 25ms and 35ms */ +#define PD_T_ERROR_RECOVERY (25*MSEC) /* 25ms */ +#define PD_T_CC_DEBOUNCE (100*MSEC) /* between 100ms and 200ms */ +/* DRP_SNK + DRP_SRC must be between 50ms and 100ms with 30%-70% duty cycle */ +#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_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 */ +#define PD_T_SRC_TURN_ON (275*MSEC) /* 275ms */ +#define PD_T_SAFE_0V (650*MSEC) /* 650ms */ +#define PD_T_NO_RESPONSE (5500*MSEC) /* between 4.5s and 5.5s */ +#define PD_T_BIST_TRANSMIT (50*MSEC) /* 50ms (used for task_wait arg) */ +#define PD_T_BIST_RECEIVE (60*MSEC) /* 60ms (max time to process bist) */ +#define PD_T_VCONN_SOURCE_ON (100*MSEC) /* 100ms */ +#define PD_T_TRY_SRC (125*MSEC) /* Max time for Try.SRC state */ +#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 */ + +/* number of edges and time window to detect CC line is not idle */ +#define PD_RX_TRANSITION_COUNT 3 +#define PD_RX_TRANSITION_WINDOW 20 /* between 12us and 20us */ + +/* from USB Type-C Specification Table 5-1 */ +#define PD_T_AME (1*SECOND) /* timeout from UFP attach to Alt Mode Entry */ + +/* VDM Timers ( USB PD Spec Rev2.0 Table 6-30 )*/ +#define PD_T_VDM_BUSY (100*MSEC) /* at least 100ms */ +#define PD_T_VDM_E_MODE (25*MSEC) /* enter/exit the same max */ +#define PD_T_VDM_RCVR_RSP (15*MSEC) /* max of 15ms */ +#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 */ + +/* function table for entered mode */ +struct amode_fx { + int (*status)(int port, uint32_t *payload); + int (*config)(int port, uint32_t *payload); +}; + +/* function table for alternate mode capable responders */ +struct svdm_response { + int (*identity)(int port, uint32_t *payload); + int (*svids)(int port, uint32_t *payload); + int (*modes)(int port, uint32_t *payload); + int (*enter_mode)(int port, uint32_t *payload); + int (*exit_mode)(int port, uint32_t *payload); + struct amode_fx *amode; +}; + +struct svdm_svid_data { + uint16_t svid; + int mode_cnt; + uint32_t mode_vdo[PDO_MODES]; +}; + +struct svdm_amode_fx { + uint16_t svid; + int (*enter)(int port, uint32_t mode_caps); + int (*status)(int port, uint32_t *payload); + int (*config)(int port, uint32_t *payload); + void (*post_config)(int port); + int (*attention)(int port, uint32_t *payload); + void (*exit)(int port); +}; + +/* defined in /usb_pd_policy.c */ +/* All UFP_U should have */ +extern const struct svdm_response svdm_rsp; +/* All DFP_U should have */ +extern const struct svdm_amode_fx supported_modes[]; +extern const int supported_modes_cnt; + +/* DFP data needed to support alternate mode entry and exit */ +struct svdm_amode_data { + const struct svdm_amode_fx *fx; + /* VDM object position */ + int opos; + /* mode capabilities specific to SVID amode. */ + struct svdm_svid_data *data; +}; + +enum hpd_event { + hpd_none, + hpd_low, + hpd_high, + hpd_irq, +}; + +/* DisplayPort flags */ +#define DP_FLAGS_DP_ON (1 << 0) /* Display port mode is on */ +#define DP_FLAGS_HPD_HI_PENDING (1 << 1) /* Pending HPD_HI */ + +/* supported alternate modes */ +enum pd_alternate_modes { + PD_AMODE_GOOGLE, + PD_AMODE_DISPLAYPORT, + /* not a real mode */ + PD_AMODE_COUNT, +}; + +/* Policy structure for driving alternate mode */ +struct pd_policy { + /* index of svid currently being operated on */ + int svid_idx; + /* count of svids discovered */ + int svid_cnt; + /* SVDM identity info (Id, Cert Stat, 0-4 Typec specific) */ + uint32_t identity[PDO_MAX_OBJECTS - 1]; + /* supported svids & corresponding vdo mode data */ + struct svdm_svid_data svids[SVID_DISCOVERY_MAX]; + /* active modes */ + struct svdm_amode_data amodes[PD_AMODE_COUNT]; + /* Next index to insert DFP alternate mode into amodes */ + int amode_idx; +}; + +/* + * VDO : Vendor Defined Message Object + * VDM object is minimum of VDM header + 6 additional data objects. + */ + +#define VDO_MAX_SIZE 7 + +#define VDM_VER10 0 +#define VDM_VER20 1 + +/* + * VDM header + * ---------- + * <31:16> :: SVID + * <15> :: VDM type ( 1b == structured, 0b == unstructured ) + * <14:13> :: Structured VDM version (00b == Rev 2.0, 01b == Rev 3.0 ) + * <12:11> :: reserved + * <10:8> :: object position (1-7 valid ... used for enter/exit mode only) + * <7:6> :: command type (SVDM only?) + * <5> :: reserved (SVDM), command type (UVDM) + * <4:0> :: command + */ +#define VDO(vid, type, custom) \ + (((vid) << 16) | \ + ((type) << 15) | \ + ((custom) & 0x7FFF)) + +#define VDO_SVDM_TYPE (1 << 15) +#define VDO_SVDM_VERS(x) (x << 13) +#define VDO_OPOS(x) (x << 8) +#define VDO_CMDT(x) (x << 6) +#define VDO_OPOS_MASK VDO_OPOS(0x7) +#define VDO_CMDT_MASK VDO_CMDT(0x3) + +#define CMDT_INIT 0 +#define CMDT_RSP_ACK 1 +#define CMDT_RSP_NAK 2 +#define CMDT_RSP_BUSY 3 + + +/* reserved for SVDM ... for Google UVDM */ +#define VDO_SRC_INITIATOR (0 << 5) +#define VDO_SRC_RESPONDER (1 << 5) + +#define CMD_DISCOVER_IDENT 1 +#define CMD_DISCOVER_SVID 2 +#define CMD_DISCOVER_MODES 3 +#define CMD_ENTER_MODE 4 +#define CMD_EXIT_MODE 5 +#define CMD_ATTENTION 6 +#define CMD_DP_STATUS 16 +#define CMD_DP_CONFIG 17 + +#define VDO_CMD_VENDOR(x) (((10 + (x)) & 0x1f)) + +/* ChromeOS specific commands */ +#define VDO_CMD_VERSION VDO_CMD_VENDOR(0) +#define VDO_CMD_SEND_INFO VDO_CMD_VENDOR(1) +#define VDO_CMD_READ_INFO VDO_CMD_VENDOR(2) +#define VDO_CMD_REBOOT VDO_CMD_VENDOR(5) +#define VDO_CMD_FLASH_ERASE VDO_CMD_VENDOR(6) +#define VDO_CMD_FLASH_WRITE VDO_CMD_VENDOR(7) +#define VDO_CMD_ERASE_SIG VDO_CMD_VENDOR(8) +#define VDO_CMD_PING_ENABLE VDO_CMD_VENDOR(10) +#define VDO_CMD_CURRENT VDO_CMD_VENDOR(11) +#define VDO_CMD_FLIP VDO_CMD_VENDOR(12) +#define VDO_CMD_GET_LOG VDO_CMD_VENDOR(13) +#define VDO_CMD_CCD_EN VDO_CMD_VENDOR(14) + +#define PD_VDO_VID(vdo) ((vdo) >> 16) +#define PD_VDO_SVDM(vdo) (((vdo) >> 15) & 1) +#define PD_VDO_OPOS(vdo) (((vdo) >> 8) & 0x7) +#define PD_VDO_CMD(vdo) ((vdo) & 0x1f) +#define PD_VDO_CMDT(vdo) (((vdo) >> 6) & 0x3) + +/* + * SVDM Identity request -> response + * + * Request is simply properly formatted SVDM header + * + * Response is 4 data objects: + * [0] :: SVDM header + * [1] :: Identitiy header + * [2] :: Cert Stat VDO + * [3] :: (Product | Cable) VDO + * [4] :: AMA VDO + * + */ +#define VDO_INDEX_HDR 0 +#define VDO_INDEX_IDH 1 +#define VDO_INDEX_CSTAT 2 +#define VDO_INDEX_CABLE 3 +#define VDO_INDEX_PRODUCT 3 +#define VDO_INDEX_AMA 4 +#define VDO_I(name) VDO_INDEX_##name + +/* + * SVDM Identity Header + * -------------------- + * <31> :: data capable as a USB host + * <30> :: data capable as a USB device + * <29:27> :: product type + * <26> :: modal operation supported (1b == yes) + * <25:16> :: SBZ + * <15:0> :: USB-IF assigned VID for this cable vendor + */ +#define IDH_PTYPE_UNDEF 0 +#define IDH_PTYPE_HUB 1 +#define IDH_PTYPE_PERIPH 2 +#define IDH_PTYPE_PCABLE 3 +#define IDH_PTYPE_ACABLE 4 +#define IDH_PTYPE_AMA 5 + +#define VDO_IDH(usbh, usbd, ptype, is_modal, vid) \ + ((usbh) << 31 | (usbd) << 30 | ((ptype) & 0x7) << 27 \ + | (is_modal) << 26 | ((vid) & 0xffff)) + +#define PD_IDH_PTYPE(vdo) (((vdo) >> 27) & 0x7) +#define PD_IDH_VID(vdo) ((vdo) & 0xffff) + +/* + * Cert Stat VDO + * ------------- + * <31:20> : SBZ + * <19:0> : USB-IF assigned TID for this cable + */ +#define VDO_CSTAT(tid) ((tid) & 0xfffff) +#define PD_CSTAT_TID(vdo) ((vdo) & 0xfffff) + +/* + * Product VDO + * ----------- + * <31:16> : USB Product ID + * <15:0> : USB bcdDevice + */ +#define VDO_PRODUCT(pid, bcd) (((pid) & 0xffff) << 16 | ((bcd) & 0xffff)) +#define PD_PRODUCT_PID(vdo) (((vdo) >> 16) & 0xffff) + +/* + * Cable VDO + * --------- + * <31:28> :: Cable HW version + * <27:24> :: Cable FW version + * <23:20> :: SBZ + * <19:18> :: type-C to Type-A/B/C (00b == A, 01 == B, 10 == C) + * <17> :: Type-C to Plug/Receptacle (0b == plug, 1b == receptacle) + * <16:13> :: cable latency (0001 == <10ns(~1m length)) + * <12:11> :: cable termination type (11b == both ends active VCONN req) + * <10> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable) + * <9> :: SSTX2 Directionality support + * <8> :: SSRX1 Directionality support + * <7> :: SSRX2 Directionality support + * <6:5> :: Vbus current handling capability + * <4> :: Vbus through cable (0b == no, 1b == yes) + * <3> :: SOP" controller present? (0b == no, 1b == yes) + * <2:0> :: USB SS Signaling support + */ +#define CABLE_ATYPE 0 +#define CABLE_BTYPE 1 +#define CABLE_CTYPE 2 +#define CABLE_PLUG 0 +#define CABLE_RECEPTACLE 1 +#define CABLE_CURR_1A5 0 +#define CABLE_CURR_3A 1 +#define CABLE_CURR_5A 2 +#define CABLE_USBSS_U2_ONLY 0 +#define CABLE_USBSS_U31_GEN1 1 +#define CABLE_USBSS_U31_GEN2 2 +#define VDO_CABLE(hw, fw, cbl, gdr, lat, term, tx1d, tx2d, rx1d, rx2d, cur, vps, sopp, usbss) \ + (((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 | ((cbl) & 0x3) << 18 \ + | (gdr) << 17 | ((lat) & 0x7) << 13 | ((term) & 0x3) << 11 \ + | (tx1d) << 10 | (tx2d) << 9 | (rx1d) << 8 | (rx2d) << 7 \ + | ((cur) & 0x3) << 5 | (vps) << 4 | (sopp) << 3 \ + | ((usbss) & 0x7)) + +/* + * AMA VDO + * --------- + * <31:28> :: Cable HW version + * <27:24> :: Cable FW version + * <23:12> :: SBZ + * <11> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable) + * <10> :: SSTX2 Directionality support + * <9> :: SSRX1 Directionality support + * <8> :: SSRX2 Directionality support + * <7:5> :: Vconn power + * <4> :: Vconn power required + * <3> :: Vbus power required + * <2:0> :: USB SS Signaling support + */ +#define VDO_AMA(hw, fw, tx1d, tx2d, rx1d, rx2d, vcpwr, vcr, vbr, usbss) \ + (((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 \ + | (tx1d) << 11 | (tx2d) << 10 | (rx1d) << 9 | (rx2d) << 8 \ + | ((vcpwr) & 0x3) << 5 | (vcr) << 4 | (vbr) << 3 \ + | ((usbss) & 0x7)) + +#define PD_VDO_AMA_VCONN_REQ(vdo) (((vdo) >> 4) & 1) +#define PD_VDO_AMA_VBUS_REQ(vdo) (((vdo) >> 3) & 1) + +#define AMA_VCONN_PWR_1W 0 +#define AMA_VCONN_PWR_1W5 1 +#define AMA_VCONN_PWR_2W 2 +#define AMA_VCONN_PWR_3W 3 +#define AMA_VCONN_PWR_4W 4 +#define AMA_VCONN_PWR_5W 5 +#define AMA_VCONN_PWR_6W 6 +#define AMA_USBSS_U2_ONLY 0 +#define AMA_USBSS_U31_GEN1 1 +#define AMA_USBSS_U31_GEN2 2 +#define AMA_USBSS_BBONLY 3 + +/* + * SVDM Discover SVIDs request -> response + * + * Request is properly formatted VDM Header with discover SVIDs command. + * Response is a set of SVIDs of all all supported SVIDs with all zero's to + * mark the end of SVIDs. If more than 12 SVIDs are supported command SHOULD be + * repeated. + */ +#define VDO_SVID(svid0, svid1) (((svid0) & 0xffff) << 16 | ((svid1) & 0xffff)) +#define PD_VDO_SVID_SVID0(vdo) ((vdo) >> 16) +#define PD_VDO_SVID_SVID1(vdo) ((vdo) & 0xffff) + +/* + * Google modes capabilities + * <31:8> : reserved + * <7:0> : mode + */ +#define VDO_MODE_GOOGLE(mode) (mode & 0xff) + +#define MODE_GOOGLE_FU 1 /* Firmware Update mode */ + +/* + * Mode Capabilities + * + * Number of VDOs supplied is SID dependent (but <= 6 VDOS?) + */ +#define VDO_MODE_CNT_DISPLAYPORT 1 + +/* + * DisplayPort modes capabilities + * ------------------------------- + * <31:24> : SBZ + * <23:16> : UFP_D pin assignment supported + * <15:8> : DFP_D pin assignment supported + * <7> : USB 2.0 signaling (0b=yes, 1b=no) + * <6> : Plug | Receptacle (0b == plug, 1b == receptacle) + * <5:2> : xxx1: Supports DPv1.3, xx1x Supports USB Gen 2 signaling + * Other bits are reserved. + * <1:0> : signal direction ( 00b=rsv, 01b=sink, 10b=src 11b=both ) + */ +#define VDO_MODE_DP(snkp, srcp, usb, gdr, sign, sdir) \ + (((snkp) & 0xff) << 16 | ((srcp) & 0xff) << 8 \ + | ((usb) & 1) << 7 | ((gdr) & 1) << 6 | ((sign) & 0xF) << 2 \ + | ((sdir) & 0x3)) +#define PD_DP_PIN_CAPS(x) ((((x) >> 6) & 0x1) ? (((x) >> 16) & 0x3f) \ + : (((x) >> 8) & 0x3f)) + +#define MODE_DP_PIN_A 0x01 +#define MODE_DP_PIN_B 0x02 +#define MODE_DP_PIN_C 0x04 +#define MODE_DP_PIN_D 0x08 +#define MODE_DP_PIN_E 0x10 +#define MODE_DP_PIN_F 0x20 + +/* Pin configs B/D/F support multi-function */ +#define MODE_DP_PIN_MF_MASK 0x2a +/* Pin configs A/B support BR2 signaling levels */ +#define MODE_DP_PIN_BR2_MASK 0x3 +/* Pin configs C/D/E/F support DP signaling levels */ +#define MODE_DP_PIN_DP_MASK 0x3c + +#define MODE_DP_V13 0x1 +#define MODE_DP_GEN2 0x2 + +#define MODE_DP_SNK 0x1 +#define MODE_DP_SRC 0x2 +#define MODE_DP_BOTH 0x3 + +/* + * DisplayPort Status VDO + * ---------------------- + * <31:9> : SBZ + * <8> : IRQ_HPD : 1 == irq arrived since last message otherwise 0. + * <7> : HPD state : 0 = HPD_LOW, 1 == HPD_HIGH + * <6> : Exit DP Alt mode: 0 == maintain, 1 == exit + * <5> : USB config : 0 == maintain current, 1 == switch to USB from DP + * <4> : Multi-function preference : 0 == no pref, 1 == MF preferred. + * <3> : enabled : is DPout on/off. + * <2> : power low : 0 == normal or LPM disabled, 1 == DP disabled for LPM + * <1:0> : connect status : 00b == no (DFP|UFP)_D is connected or disabled. + * 01b == DFP_D connected, 10b == UFP_D connected, 11b == both. + */ +#define VDO_DP_STATUS(irq, lvl, amode, usbc, mf, en, lp, conn) \ + (((irq) & 1) << 8 | ((lvl) & 1) << 7 | ((amode) & 1) << 6 \ + | ((usbc) & 1) << 5 | ((mf) & 1) << 4 | ((en) & 1) << 3 \ + | ((lp) & 1) << 2 | ((conn & 0x3) << 0)) + +#define PD_VDO_DPSTS_HPD_IRQ(x) (((x) >> 8) & 1) +#define PD_VDO_DPSTS_HPD_LVL(x) (((x) >> 7) & 1) +#define PD_VDO_DPSTS_MF_PREF(x) (((x) >> 4) & 1) + +/* Per DisplayPort Spec v1.3 Section 3.3 */ +#define HPD_USTREAM_DEBOUNCE_LVL (2*MSEC) +#define HPD_USTREAM_DEBOUNCE_IRQ (250) +#define HPD_DSTREAM_DEBOUNCE_IRQ (500) /* between 500-1000us */ + +/* + * DisplayPort Configure VDO + * ------------------------- + * <31:24> : SBZ + * <23:16> : SBZ + * <15:8> : Pin assignment requested. Choose one from mode caps. + * <7:6> : SBZ + * <5:2> : signalling : 1h == DP v1.3, 2h == Gen 2 + * Oh is only for USB, remaining values are reserved + * <1:0> : cfg : 00 == USB, 01 == DFP_D, 10 == UFP_D, 11 == reserved + */ +#define VDO_DP_CFG(pin, sig, cfg) \ + (((pin) & 0xff) << 8 | ((sig) & 0xf) << 2 | ((cfg) & 0x3)) + +#define PD_DP_CFG_DPON(x) (((x & 0x3) == 1) || ((x & 0x3) == 2)) +/* + * Get the pin assignment mask + * for backward compatibility, if it is null, + * get the former sink pin assignment we used to be in <23:16>. + */ +#define PD_DP_CFG_PIN(x) ((((x) >> 8) & 0xff) ? (((x) >> 8) & 0xff) \ + : (((x) >> 16) & 0xff)) +/* + * ChromeOS specific PD device Hardware IDs. Used to identify unique + * products and used in VDO_INFO. Note this field is 10 bits. + */ +#define USB_PD_HW_DEV_ID_RESERVED 0 +#define USB_PD_HW_DEV_ID_ZINGER 1 +#define USB_PD_HW_DEV_ID_MINIMUFFIN 2 +#define USB_PD_HW_DEV_ID_DINGDONG 3 +#define USB_PD_HW_DEV_ID_HOHO 4 +#define USB_PD_HW_DEV_ID_HONEYBUNS 5 + +/* + * ChromeOS specific VDO_CMD_READ_INFO responds with device info including: + * RW Hash: First 20 bytes of SHA-256 of RW (20 bytes) + * HW Device ID: unique descriptor for each ChromeOS model (2 bytes) + * top 6 bits are minor revision, bottom 10 bits are major + * SW Debug Version: Software version useful for debugging (15 bits) + * IS RW: True if currently in RW, False otherwise (1 bit) + */ +#define VDO_INFO(id, id_minor, ver, is_rw) ((id_minor) << 26 \ + | ((id) & 0x3ff) << 16 \ + | ((ver) & 0x7fff) << 1 \ + | ((is_rw) & 1)) +#define VDO_INFO_HW_DEV_ID(x) ((x) >> 16) +#define VDO_INFO_SW_DBG_VER(x) (((x) >> 1) & 0x7fff) +#define VDO_INFO_IS_RW(x) ((x) & 1) + +#define HW_DEV_ID_MAJ(x) (x & 0x3ff) +#define HW_DEV_ID_MIN(x) ((x) >> 10) + +/* USB-IF SIDs */ +#define USB_SID_PD 0xff00 /* power delivery */ +#define USB_SID_DISPLAYPORT 0xff01 + +#define USB_GOOGLE_TYPEC_URL "http://www.google.com/chrome/devices/typec" +/* USB Vendor ID assigned to Google Inc. */ +#define USB_VID_GOOGLE 0x18d1 + +/* Other Vendor IDs */ +#define USB_VID_APPLE 0x05ac + +/* Timeout for message receive in microseconds */ +#define USB_PD_RX_TMOUT_US 1800 + +/* --- Protocol layer functions --- */ + +enum pd_states { + PD_STATE_DISABLED, + PD_STATE_SUSPENDED, +#ifdef CONFIG_USB_PD_DUAL_ROLE + PD_STATE_SNK_DISCONNECTED, + PD_STATE_SNK_DISCONNECTED_DEBOUNCE, + PD_STATE_SNK_HARD_RESET_RECOVER, + PD_STATE_SNK_DISCOVERY, + PD_STATE_SNK_REQUESTED, + PD_STATE_SNK_TRANSITION, + PD_STATE_SNK_READY, + + PD_STATE_SNK_SWAP_INIT, + PD_STATE_SNK_SWAP_SNK_DISABLE, + PD_STATE_SNK_SWAP_SRC_DISABLE, + PD_STATE_SNK_SWAP_STANDBY, + PD_STATE_SNK_SWAP_COMPLETE, +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + + PD_STATE_SRC_DISCONNECTED, + PD_STATE_SRC_DISCONNECTED_DEBOUNCE, + PD_STATE_SRC_HARD_RESET_RECOVER, + PD_STATE_SRC_STARTUP, + PD_STATE_SRC_DISCOVERY, + PD_STATE_SRC_NEGOCIATE, + PD_STATE_SRC_ACCEPTED, + PD_STATE_SRC_POWERED, + PD_STATE_SRC_TRANSITION, + PD_STATE_SRC_READY, + PD_STATE_SRC_GET_SINK_CAP, + PD_STATE_DR_SWAP, + +#ifdef CONFIG_USB_PD_DUAL_ROLE + PD_STATE_SRC_SWAP_INIT, + PD_STATE_SRC_SWAP_SNK_DISABLE, + PD_STATE_SRC_SWAP_SRC_DISABLE, + PD_STATE_SRC_SWAP_STANDBY, + +#ifdef CONFIG_USBC_VCONN_SWAP + PD_STATE_VCONN_SWAP_SEND, + PD_STATE_VCONN_SWAP_INIT, + PD_STATE_VCONN_SWAP_READY, +#endif /* CONFIG_USBC_VCONN_SWAP */ +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + + PD_STATE_SOFT_RESET, + PD_STATE_HARD_RESET_SEND, + PD_STATE_HARD_RESET_EXECUTE, +#ifdef CONFIG_COMMON_RUNTIME + PD_STATE_BIST_RX, + PD_STATE_BIST_TX, +#endif + +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE + PD_STATE_DRP_AUTO_TOGGLE, +#endif + /* Number of states. Not an actual state. */ + PD_STATE_COUNT, +}; + +#define PD_FLAGS_PING_ENABLED (1 << 0) /* SRC_READY pings enabled */ +#define PD_FLAGS_PARTNER_DR_POWER (1 << 1) /* port partner is dualrole power */ +#define PD_FLAGS_PARTNER_DR_DATA (1 << 2) /* port partner is dualrole data */ +#define PD_FLAGS_CHECK_IDENTITY (1 << 3) /* discover identity in READY */ +#define PD_FLAGS_SNK_CAP_RECVD (1 << 4) /* sink capabilities received */ +#define PD_FLAGS_TCPC_DRP_TOGGLE (1 << 5) /* TCPC-controlled DRP toggling */ +#define PD_FLAGS_EXPLICIT_CONTRACT (1 << 6) /* explicit pwr contract in place */ +#define PD_FLAGS_VBUS_NEVER_LOW (1 << 7) /* VBUS input has never been low */ +#define PD_FLAGS_PREVIOUS_PD_CONN (1 << 8) /* previously PD connected */ +#define PD_FLAGS_CHECK_PR_ROLE (1 << 9) /* check power role in READY */ +#define PD_FLAGS_CHECK_DR_ROLE (1 << 10)/* check data role in READY */ +#define PD_FLAGS_PARTNER_EXTPOWER (1 << 11)/* port partner has external pwr */ +#define PD_FLAGS_VCONN_ON (1 << 12)/* vconn is being sourced */ +#define PD_FLAGS_TRY_SRC (1 << 13)/* Try.SRC states are active */ +#define PD_FLAGS_PARTNER_USB_COMM (1 << 14)/* port partner is USB comms */ +#define PD_FLAGS_UPDATE_SRC_CAPS (1 << 15)/* send new source capabilities */ +#define PD_FLAGS_TS_DTS_PARTNER (1 << 16)/* partner has rp/rp or rd/rd */ +/* Flags to clear on a disconnect */ +#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \ + PD_FLAGS_PARTNER_DR_DATA | \ + PD_FLAGS_CHECK_IDENTITY | \ + PD_FLAGS_SNK_CAP_RECVD | \ + PD_FLAGS_TCPC_DRP_TOGGLE | \ + PD_FLAGS_EXPLICIT_CONTRACT | \ + PD_FLAGS_PREVIOUS_PD_CONN | \ + PD_FLAGS_CHECK_PR_ROLE | \ + PD_FLAGS_CHECK_DR_ROLE | \ + PD_FLAGS_PARTNER_EXTPOWER | \ + PD_FLAGS_VCONN_ON | \ + PD_FLAGS_TRY_SRC | \ + PD_FLAGS_PARTNER_USB_COMM | \ + PD_FLAGS_UPDATE_SRC_CAPS | \ + PD_FLAGS_TS_DTS_PARTNER) + +enum pd_cc_states { + PD_CC_NONE, + + /* From DFP perspective */ + PD_CC_NO_UFP, + PD_CC_AUDIO_ACC, + PD_CC_DEBUG_ACC, + PD_CC_UFP_ATTACHED, + + /* From UFP perspective */ + PD_CC_DFP_ATTACHED +}; + +#ifdef CONFIG_USB_PD_DUAL_ROLE +enum pd_dual_role_states { + /* While disconnected, toggle between src and sink */ + PD_DRP_TOGGLE_ON, + /* Stay in src until disconnect, then stay in sink forever */ + PD_DRP_TOGGLE_OFF, + /* Stay in current power role, don't switch. No auto-toggle support */ + PD_DRP_FREEZE, + /* Switch to sink */ + PD_DRP_FORCE_SINK, + /* Switch to source */ + PD_DRP_FORCE_SOURCE, +}; +/** + * Get dual role state + * + * @return Current dual-role state, from enum pd_dual_role_states + */ +enum pd_dual_role_states pd_get_dual_role(void); +/** + * Set dual role state, from among enum pd_dual_role_states + * + * @param state New state of dual-role port, selected from + * enum pd_dual_role_states + */ +void pd_set_dual_role(enum pd_dual_role_states state); + +/** + * Get role, from among PD_ROLE_SINK and PD_ROLE_SOURCE + * + * @param port Port number from which to get role + */ +int pd_get_role(int port); + +#endif + +/* Control Message type */ +enum pd_ctrl_msg_type { + /* 0 Reserved */ + PD_CTRL_GOOD_CRC = 1, + PD_CTRL_GOTO_MIN = 2, + PD_CTRL_ACCEPT = 3, + PD_CTRL_REJECT = 4, + PD_CTRL_PING = 5, + PD_CTRL_PS_RDY = 6, + PD_CTRL_GET_SOURCE_CAP = 7, + PD_CTRL_GET_SINK_CAP = 8, + PD_CTRL_DR_SWAP = 9, + PD_CTRL_PR_SWAP = 10, + PD_CTRL_VCONN_SWAP = 11, + PD_CTRL_WAIT = 12, + PD_CTRL_SOFT_RESET = 13, + /* 14-15 Reserved */ + + /* Used for REV 3.0 */ + PD_CTRL_NOT_SUPPORTED = 16, + PD_CTRL_GET_SOURCE_CAP_EXT = 17, + PD_CTRL_GET_STATUS = 18, + PD_CTRL_FR_SWAP = 19, + PD_CTRL_GET_PPS_STATUS = 20, + PD_CTRL_GET_COUNTRY_CODES = 21, + /* 22-31 Reserved */ +}; + +/* Battery Status Data Object fields for REV 3.0 */ +#define BSDO_CAP_UNKNOWN 0xffff +#define BSDO_CAP(n) (((n) & 0xffff) << 16) +#define BSDO_INVALID (1 << 8) +#define BSDO_PRESENT (1 << 9) +#define BSDO_DISCHARGING (1 << 10) +#define BSDO_IDLE (1 << 11) + +/* Get Battery Cap Message fields for REV 3.0 */ +#define BATT_CAP_REF(n) (((n) >> 16) & 0xff) + +/* Extended message type for REV 3.0 */ +enum pd_ext_msg_type { + /* 0 Reserved */ + PD_EXT_SOURCE_CAP = 1, + PD_EXT_STATUS = 2, + PD_EXT_GET_BATTERY_CAP = 3, + PD_EXT_GET_BATTERY_STATUS = 4, + PD_EXT_BATTERY_CAP = 5, + PD_EXT_GET_MANUFACTURER_INFO = 6, + PD_EXT_MANUFACTURER_INFO = 7, + PD_EXT_SECURITY_REQUEST = 8, + PD_EXT_SECURITY_RESPONSE = 9, + PD_EXT_FIRMWARE_UPDATE_REQUEST = 10, + PD_EXT_FIRMWARE_UPDATE_RESPONSE = 11, + PD_EXT_PPS_STATUS = 12, + PD_EXT_COUNTRY_INFO = 13, + PD_EXT_COUNTRY_CODES = 14, + /* 15-31 Reserved */ +}; + +/* Data message type */ +enum pd_data_msg_type { + /* 0 Reserved */ + PD_DATA_SOURCE_CAP = 1, + PD_DATA_REQUEST = 2, + PD_DATA_BIST = 3, + PD_DATA_SINK_CAP = 4, + /* 5-14 Reserved for REV 2.0 */ + PD_DATA_BATTERY_STATUS = 5, + PD_DATA_ALERT = 6, + PD_DATA_GET_COUNTRY_INFO = 7, + /* 8-14 Reserved for REV 3.0 */ + PD_DATA_VENDOR_DEF = 15, +}; + +/* Protocol revision */ +#define PD_REV10 0 +#define PD_REV20 1 +#define PD_REV30 2 + +/* Power role */ +#define PD_ROLE_SINK 0 +#define PD_ROLE_SOURCE 1 +/* Data role */ +#define PD_ROLE_UFP 0 +#define PD_ROLE_DFP 1 +/* Vconn role */ +#define PD_ROLE_VCONN_OFF 0 +#define PD_ROLE_VCONN_ON 1 + +/* chunk is a request or response in REV 3.0 */ +#define CHUNK_RESPONSE 0 +#define CHUNK_REQUEST 1 + +/* collision avoidance Rp values in REV 3.0 */ +#define SINK_TX_OK TYPEC_RP_3A0 +#define SINK_TX_NG TYPEC_RP_1A5 + +/* Port role at startup */ +#ifndef PD_ROLE_DEFAULT +#ifdef CONFIG_USB_PD_DUAL_ROLE +#define PD_ROLE_DEFAULT(port) PD_ROLE_SINK +#else +#define PD_ROLE_DEFAULT(port) PD_ROLE_SOURCE +#endif +#endif + +/* Port default state at startup */ +#ifdef CONFIG_USB_PD_DUAL_ROLE +#define PD_DEFAULT_STATE(port) ((PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE) ? \ + PD_STATE_SRC_DISCONNECTED : \ + PD_STATE_SNK_DISCONNECTED) +#else +#define PD_DEFAULT_STATE(port) PD_STATE_SRC_DISCONNECTED +#endif + +/* build extended message header */ +/* All extended messages are chunked, so set bit 15 */ +#define PD_EXT_HEADER(cnum, rchk, dsize) \ + ((1 << 15) | ((cnum) << 11) | \ + ((rchk) << 10) | (dsize)) + +/* build message header */ +#define PD_HEADER(type, prole, drole, id, cnt, rev, ext) \ + ((type) | ((rev) << 6) | \ + ((drole) << 5) | ((prole) << 8) | \ + ((id) << 9) | ((cnt) << 12) | ((ext) << 15)) + +/* Used for processing pd header */ +#define PD_HEADER_EXT(header) (((header) >> 15) & 1) +#define PD_HEADER_CNT(header) (((header) >> 12) & 7) +#define PD_HEADER_TYPE(header) ((header) & 0xF) +#define PD_HEADER_ID(header) (((header) >> 9) & 7) +#define PD_HEADER_REV(header) (((header) >> 6) & 3) + +/* Used for processing pd extended header */ +#define PD_EXT_HEADER_CHUNKED(header) (((header) >> 15) & 1) +#define PD_EXT_HEADER_CHUNK_NUM(header) (((header) >> 11) & 0xf) +#define PD_EXT_HEADER_REQ_CHUNK(header) (((header) >> 10) & 1) +#define PD_EXT_HEADER_DATA_SIZE(header) ((header) & 0x1ff) + +/* K-codes for special symbols */ +#define PD_SYNC1 0x18 +#define PD_SYNC2 0x11 +#define PD_SYNC3 0x06 +#define PD_RST1 0x07 +#define PD_RST2 0x19 +#define PD_EOP 0x0D + +/* Minimum PD supply current (mA) */ +#define PD_MIN_MA 500 + +/* Minimum PD voltage (mV) */ +#define PD_MIN_MV 5000 + +/* No connect voltage threshold for sources based on Rp */ +#define PD_SRC_DEF_VNC_MV 1600 +#define PD_SRC_1_5_VNC_MV 1600 +#define PD_SRC_3_0_VNC_MV 2600 + +/* Rd voltage threshold for sources based on Rp */ +#define PD_SRC_DEF_RD_THRESH_MV 200 +#define PD_SRC_1_5_RD_THRESH_MV 400 +#define PD_SRC_3_0_RD_THRESH_MV 800 + +/* Voltage threshold to detect connection when presenting Rd */ +#define PD_SNK_VA_MV 250 + +/* --- Policy layer functions --- */ + +/* Request types for pd_build_request() */ +enum pd_request_type { + PD_REQUEST_VSAFE5V, + PD_REQUEST_MAX, +}; + +#ifdef CONFIG_USB_PD_REV30 +/** + * Get current PD Revision + * + * @param port USB-C port number + * @return 0 for PD_REV1.0, 1 for PD_REV2.0, 2 for PD_REV3.0 + */ +int pd_get_rev(int port); + +/** + * Get current PD VDO Version + * + * @param port USB-C port number + * @return 0 for PD_REV1.0, 1 for PD_REV2.0 + */ +int pd_get_vdo_ver(int port); +#else +#define pd_get_rev(n) PD_REV20 +#define pd_get_vdo_ver(n) VDM_VER10 +#endif +/** + * Decide which PDO to choose from the source capabilities. + * + * @param port USB-C port number + * @param rdo requested Request Data Object. + * @param ma selected current limit (stored on success) + * @param mv selected supply voltage (stored on success) + * @param req_type request type + * @return <0 if invalid, else EC_SUCCESS + */ +int pd_build_request(int port, uint32_t *rdo, uint32_t *ma, uint32_t *mv, + enum pd_request_type req_type); + +/** + * Check if max voltage request is allowed (only used if + * CONFIG_USB_PD_CHECK_MAX_REQUEST_ALLOWED is defined). + * + * @return True if max voltage request allowed, False otherwise + */ +int pd_is_max_request_allowed(void); + +/** + * Callback with source capabilities packet + * + * @param port USB-C port number + * @param cnt the number of Power Data Objects. + * @param src_caps Power Data Objects representing the source capabilities. + */ +void pd_process_source_cap_callback(int port, int cnt, uint32_t *src_caps); + +/** + * Process source capabilities packet + * + * @param port USB-C port number + * @param cnt the number of Power Data Objects. + * @param src_caps Power Data Objects representing the source capabilities. + */ +void pd_process_source_cap(int port, int cnt, uint32_t *src_caps); + +/** + * Find PDO index that offers the most amount of power and stays within + * max_mv voltage. + * + * @param port USB-C port number + * @param max_mv maximum voltage (or -1 if no limit) + * @param pdo raw pdo corresponding to index, or index 0 on error (output) + * @return index of PDO within source cap packet + */ +int pd_find_pdo_index(int port, int max_mv, uint32_t *pdo); + +/** + * Extract power information out of a Power Data Object (PDO) + * + * @param pdo raw pdo to extract + * @param ma current of the PDO (output) + * @param mv voltage of the PDO (output) + */ +void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *mv); + +/** + * Reduce the sink power consumption to a minimum value. + * + * @param port USB-C port number + * @param ma reduce current to minimum value. + * @param mv reduce voltage to minimum value. + */ +void pd_snk_give_back(int port, uint32_t * const ma, uint32_t * const mv); + +/** + * Put a cap on the max voltage requested as a sink. + * @param mv maximum voltage in millivolts. + */ +void pd_set_max_voltage(unsigned mv); + +/** + * Get the max voltage that can be requested as set by pd_set_max_voltage(). + * @return max voltage + */ +unsigned pd_get_max_voltage(void); + +/** + * Check if this board supports the given input voltage. + * + * @mv input voltage + * @return 1 if voltage supported, 0 if not + */ +int pd_is_valid_input_voltage(int mv); + +/** + * Request a new operating voltage. + * + * @param rdo Request Data Object with the selected operating point. + * @param port The port which the request came in on. + * @return EC_SUCCESS if we can get the requested voltage/OP, <0 else. + */ +int pd_check_requested_voltage(uint32_t rdo, const int port); + +/** + * Run board specific checks on request message + * + * @param rdo the request data object word sent by the sink. + * @param pdo_cnt the total number of source PDOs. + * @return EC_SUCCESS if request is ok , <0 else. + */ +int pd_board_check_request(uint32_t rdo, int pdo_cnt); + +/** + * Select a new output voltage. + * + * param idx index of the new voltage in the source PDO table. + */ +void pd_transition_voltage(int idx); + +/** + * Go back to the default/safe state of the power supply + * + * @param port USB-C port number + */ +void pd_power_supply_reset(int port); + +/** + * Enable or disable VBUS discharge for a given port. + * + * @param port USB-C port number + * @enable 1 if enabling discharge, 0 if disabling + */ +void pd_set_vbus_discharge(int port, int enable); + +/** + * Enable the power supply output after the ready delay. + * + * @param port USB-C port number + * @return EC_SUCCESS if the power supply is ready, <0 else. + */ +int pd_set_power_supply_ready(int port); + +/** + * Ask the specified voltage from the PD source. + * + * It triggers a new negotiation sequence with the source. + * @param port USB-C port number + * @param mv request voltage in millivolts. + */ +void pd_request_source_voltage(int port, int mv); + +/** + * Set a voltage limit from the PD source. + * + * If the source is currently active, it triggers a new negotiation. + * @param port USB-C port number + * @param mv limit voltage in millivolts. + */ +void pd_set_external_voltage_limit(int port, int mv); + +/** + * Set the PD input current limit. + * + * @param port USB-C port number + * @param max_ma Maximum current limit + * @param supply_voltage Voltage at which current limit is applied + */ +void pd_set_input_current_limit(int port, uint32_t max_ma, + uint32_t supply_voltage); + + +/** + * Update the power contract if it exists. + * + * @param port USB-C port number. + */ +void pd_update_contract(int port); + +/* Encode DTS status of port partner in current limit parameter */ +typedef uint32_t typec_current_t; +#define TYPEC_CURRENT_DTS_MASK (1 << 31) +#define TYPEC_CURRENT_ILIM_MASK (~TYPEC_CURRENT_DTS_MASK) + +/** + * Set the type-C input current limit. + * + * @param port USB-C port number + * @param max_ma Maximum current limit + * @param supply_voltage Voltage at which current limit is applied + */ +void typec_set_input_current_limit(int port, typec_current_t max_ma, + uint32_t supply_voltage); + +/** + * Set the type-C current limit when sourcing current.. + * + * @param port USB-C port number + * @param rp One of enum tcpc_rp_value (eg TYPEC_RP_3A0) defining the limit. + */ +void typec_set_source_current_limit(int port, int rp); + +/** + * Verify board specific health status : current, voltages... + * + * @return EC_SUCCESS if the board is good, <0 else. + */ +int pd_board_checks(void); + +/** + * Return if VBUS is detected on type-C port + * + * @param port USB-C port number + * @return VBUS is detected + */ +int pd_snk_is_vbus_provided(int port); + +/** + * Notify PD protocol that VBUS has gone low + * + * @param port USB-C port number + */ +void pd_vbus_low(int port); + +/** + * Check if power swap is allowed. + * + * @param port USB-C port number + * @return True if power swap is allowed, False otherwise + */ +int pd_check_power_swap(int port); + +/** + * Check if data swap is allowed. + * + * @param port USB-C port number + * @param data_role current data role + * @return True if data swap is allowed, False otherwise + */ +int pd_check_data_swap(int port, int data_role); + +/** + * Check if vconn swap is allowed. + * + * @param port USB-C port number + * @return True if vconn swap is allowed, False otherwise + */ + +int pd_check_vconn_swap(int port); + +/** + * Check current power role for potential power swap + * + * @param port USB-C port number + * @param pr_role Our power role + * @param flags PD flags + */ +void pd_check_pr_role(int port, int pr_role, int flags); + +/** + * Check current data role for potential data swap + * + * @param port USB-C port number + * @param dr_role Our data role + * @param flags PD flags + */ +void pd_check_dr_role(int port, int dr_role, int flags); + +/** + * Check if we should charge from this device. This is + * basically a white-list for chargers that are dual-role, + * don't set the externally powered bit, but we should charge + * from by default. + * + * @param vid Port partner Vendor ID + * @param pid Port partner Product ID + */ +int pd_charge_from_device(uint16_t vid, uint16_t pid); + +/** + * Execute data swap. + * + * @param port USB-C port number + * @param data_role new data role + */ +void pd_execute_data_swap(int port, int data_role); + +/** + * Get PD device info used for VDO_CMD_SEND_INFO / VDO_CMD_READ_INFO + * + * @param info_data pointer to info data array + */ +void pd_get_info(uint32_t *info_data); + +/** + * Handle Vendor Defined Messages + * + * @param port USB-C port number + * @param cnt number of data objects in the payload. + * @param payload payload data. + * @param rpayload pointer to the data to send back. + * @return if >0, number of VDOs to send back. + */ +int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload); + +/** + * Handle Structured Vendor Defined Messages + * + * @param port USB-C port number + * @param cnt number of data objects in the payload. + * @param payload payload data. + * @param rpayload pointer to the data to send back. + * @return if >0, number of VDOs to send back. + */ +int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload); + +/** + * Handle Custom VDMs for flashing. + * + * @param port USB-C port number + * @param cnt number of data objects in the payload. + * @param payload payload data. + * @return if >0, number of VDOs to send back. + */ +int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload); + +/** + * Enter alternate mode on DFP + * + * @param port USB-C port number + * @param svid USB standard or vendor id to exit or zero for DFP amode reset. + * @param opos object position of mode to exit. + * @return vdm for UFP to be sent to enter mode or zero if not. + */ +uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos); + +/** + * Get DisplayPort pin mode for DFP to request from UFP's capabilities. + * + * @param port USB-C port number. + * @param status DisplayPort Status VDO. + * @return one-hot PIN config to request. + */ +int pd_dfp_dp_get_pin_mode(int port, uint32_t status); + +/** + * Exit alternate mode on DFP + * + * @param port USB-C port number + * @param svid USB standard or vendor id to exit or zero for DFP amode reset. + * @param opos object position of mode to exit. + * @return 1 if UFP should be sent exit mode VDM. + */ +int pd_dfp_exit_mode(int port, uint16_t svid, int opos); + +/** + * Initialize policy engine for DFP + * + * @param port USB-C port number + */ +void pd_dfp_pe_init(int port); + +/** + * Return the VID of the USB PD accessory connected to a specified port + * + * @param port USB-C port number + * @return the USB Vendor Identifier or 0 if it doesn't exist + */ +uint16_t pd_get_identity_vid(int port); + +/** + * Return the PID of the USB PD accessory connected to a specified port + * + * @param port USB-C port number + * @return the USB Product Identifier or 0 if it doesn't exist + */ +uint16_t pd_get_identity_pid(int port); + +/** + * Store Device ID & RW hash of device + * + * @param port USB-C port number + * @param dev_id device identifier + * @param rw_hash pointer to rw_hash + * @param current_image current image: RW or RO + * @return true if the dev / hash match an existing hash + * in our table, false otherwise + */ +int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash, + uint32_t ec_current_image); + +/** + * Try to fetch one PD log entry from accessory + * + * @param port USB-C accessory port number + * @return EC_RES_SUCCESS if the VDM was sent properly else error code + */ +int pd_fetch_acc_log_entry(int port); + +/** + * Analyze the log entry received as the VDO_CMD_GET_LOG payload. + * + * @param port USB-C accessory port number + * @param cnt number of data objects in payload + * @param payload payload data + */ +void pd_log_recv_vdm(int port, int cnt, uint32_t *payload); + +/** + * Send Vendor Defined Message + * + * @param port USB-C port number + * @param vid Vendor ID + * @param cmd VDO command number + * @param data Pointer to payload to send + * @param count number of data objects in payload + */ +void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data, + int count); + +/* Power Data Objects for the source and the sink */ +extern const uint32_t pd_src_pdo[]; +extern const int pd_src_pdo_cnt; +extern const uint32_t pd_src_pdo_max[]; +extern const int pd_src_pdo_max_cnt; +extern const uint32_t pd_snk_pdo[]; +extern const int pd_snk_pdo_cnt; + +/** + * Request that a host event be sent to notify the AP of a PD power event. + * + * @param mask host event mask. + */ +#if defined(HAS_TASK_HOSTCMD) && !defined(TEST_BUILD) +void pd_send_host_event(int mask); +#else +static inline void pd_send_host_event(int mask) { } +#endif + +/** + * Determine if in alternate mode or not. + * + * @param port port number. + * @param svid USB standard or vendor id + * @return object position of mode chosen in alternate mode otherwise zero. + */ +int pd_alt_mode(int port, uint16_t svid); + +/** + * Send hpd over USB PD. + * + * @param port port number. + * @param hpd hotplug detect type. + */ +void pd_send_hpd(int port, enum hpd_event hpd); + +/** + * Enable USB Billboard Device. + */ +extern const struct deferred_data pd_usb_billboard_deferred_data; +/* --- Physical layer functions : chip specific --- */ + +/* Packet preparation/retrieval */ + +/** + * Prepare packet reading state machine. + * + * @param port USB-C port number + */ +void pd_init_dequeue(int port); + +/** + * Prepare packet reading state machine. + * + * @param port USB-C port number + * @param off current position in the packet buffer. + * @param len minimum size to read in bits. + * @param val the read bits. + * @return new position in the packet buffer. + */ +int pd_dequeue_bits(int port, int off, int len, uint32_t *val); + +/** + * Advance until the end of the preamble. + * + * @param port USB-C port number + * @return new position in the packet buffer. + */ +int pd_find_preamble(int port); + +/** + * Write the preamble in the TX buffer. + * + * @param port USB-C port number + * @return new position in the packet buffer. + */ +int pd_write_preamble(int port); + +/** + * Write one 10-period symbol in the TX packet. + * corresponding to a quartet with 4b5b encoding + * and Biphase Mark Coding. + * + * @param port USB-C port number + * @param bit_off current position in the packet buffer. + * @param val10 the 10-bit integer. + * @return new position in the packet buffer. + */ +int pd_write_sym(int port, int bit_off, uint32_t val10); + + +/** + * Ensure that we have an edge after EOP and we end up at level 0, + * also fill the last byte. + * + * @param port USB-C port number + * @param bit_off current position in the packet buffer. + * @return new position in the packet buffer. + */ +int pd_write_last_edge(int port, int bit_off); + +/** + * Do 4B5B encoding on a 32-bit word. + * + * @param port USB-C port number + * @param off current offset in bits inside the message + * @param val32 32-bit word value to encode + * @return new offset in the message in bits. + */ +int encode_word(int port, int off, uint32_t val32); + +/** + * Ensure that we have an edge after EOP and we end up at level 0, + * also fill the last byte. + * + * @param port USB-C port number + * @param header PD packet header + * @param cnt number of payload words + * @param data payload content + * @return length of the message in bits. + */ +int prepare_message(int port, uint16_t header, uint8_t cnt, + const uint32_t *data); + +/** + * Dump the current PD packet on the console for debug. + * + * @param port USB-C port number + * @param msg context string. + */ +void pd_dump_packet(int port, const char *msg); + +/** + * Change the TX data clock frequency. + * + * @param port USB-C port number + * @param freq frequency in hertz. + */ +void pd_set_clock(int port, int freq); + +/* TX/RX callbacks */ + +/** + * Start sending over the wire the prepared packet. + * + * @param port USB-C port number + * @param polarity plug polarity (0=CC1, 1=CC2). + * @param bit_len size of the packet in bits. + * @return length transmitted or negative if error + */ +int pd_start_tx(int port, int polarity, int bit_len); + +/** + * Set PD TX DMA to use circular mode. Call this before pd_start_tx() to + * continually loop over the transmit buffer given in pd_start_tx(). + * + * @param port USB-C port number + */ +void pd_tx_set_circular_mode(int port); + +/** + * Stop PD TX DMA circular mode transaction already in progress. + * + * @param port USB-C port number + */ +void pd_tx_clear_circular_mode(int port); + +/** + * Call when we are done sending a packet. + * + * @param port USB-C port number + * @param polarity plug polarity (0=CC1, 1=CC2). + */ +void pd_tx_done(int port, int polarity); + +/** + * Check whether the PD reception is started. + * + * @param port USB-C port number + * @return true if the reception is on-going. + */ +int pd_rx_started(int port); + +/** + * Suspend the PD task. + * @param port USB-C port number + * @param enable pass 0 to resume, anything else to suspend + */ +void pd_set_suspend(int port, int enable); + +/** + * Check if the port has been initialized and PD task has not been + * suspended. + * + * @param port USB-C port number + * @return true if the PD task is not suspended. + */ +int pd_is_port_enabled(int port); + +/* Callback when the hardware has detected an incoming packet */ +void pd_rx_event(int port); +/* Start sampling the CC line for reception */ +void pd_rx_start(int port); +/* Call when we are done reading a packet */ +void pd_rx_complete(int port); + +/* restart listening to the CC wire */ +void pd_rx_enable_monitoring(int port); +/* stop listening to the CC wire during transmissions */ +void pd_rx_disable_monitoring(int port); + +/* get time since last RX edge interrupt */ +uint64_t get_time_since_last_edge(int port); + +/** + * Deinitialize the hardware used for PD. + * + * @param port USB-C port number + */ +void pd_hw_release(int port); + +/** + * Initialize the hardware used for PD RX/TX. + * + * @param port USB-C port number + * @param role Role to initialize pins in + */ +void pd_hw_init(int port, int role); + +/** + * Initialize the reception side of hardware used for PD. + * + * This is a subset of pd_hw_init() including only : + * the comparators + the RX edge delay timer + the RX DMA. + * + * @param port USB-C port number + */ +void pd_hw_init_rx(int port); + +/** + * Initialize the Power Delivery state machine + */ +void pd_init(int port); + +/** + * Run the state machine. This function must be called regularly + * to iterate through the state machine. It uses get_time() to + * determine what actions to take each call. + */ +void pd_run_state_machine(int port); + +/* --- Protocol layer functions --- */ + +/** + * Decode a raw packet in the RX buffer. + * + * @param port USB-C port number + * @param payload buffer to store the packet payload (must be 7x 32-bit) + * @return the packet header or <0 in case of error + */ +int pd_analyze_rx(int port, uint32_t *payload); + +/** + * Check if PD communication is enabled + * + * @return true if it's enabled or false otherwise + */ +int pd_comm_is_enabled(int port); + +/** + * Get connected state + * + * @param port USB-C port number + * @return True if port is in connected state + */ +int pd_is_connected(int port); + +/** + * Execute a hard reset + * + * @param port USB-C port number + */ +void pd_execute_hard_reset(int port); + +/** + * Signal to protocol layer that PD transmit is complete + * + * @param port USB-C port number + * @param status status of the transmission + */ +void pd_transmit_complete(int port, int status); + +/** + * Get port polarity. + * + * @param port USB-C port number + */ +int pd_get_polarity(int port); + +/** + * Get port partner data swap capable status + * + * @param port USB-C port number + */ +int pd_get_partner_data_swap_capable(int port); + +/** + * Request power swap command to be issued + * + * @param port USB-C port number + */ +void pd_request_power_swap(int port); + +/** + * Try to become the VCONN source, if we are not already the source and the + * other side is willing to accept a VCONN swap. + * + * @param port USB-C port number + */ +void pd_try_vconn_src(int port); + +/** + * Request data swap command to be issued + * + * @param port USB-C port number + */ +void pd_request_data_swap(int port); + +/** + * Set the PD communication enabled flag. When communication is disabled, + * the port can still detect connection and source power but will not + * send or respond to any PD communication. + * + * @param port USB-C port number + * @param enable Enable flag to set + */ +void pd_comm_enable(int port, int enable); + +/** + * Set the PD pings enabled flag. When source has negotiated power over + * PD successfully, it can optionally send pings periodically based on + * this enable flag. + * + * @param port USB-C port number + * @param enable Enable flag to set + */ +void pd_ping_enable(int port, int enable); + +/* Issue PD soft reset */ +void pd_soft_reset(void); + +/* Prepare PD communication for reset */ +void pd_prepare_reset(void); + +/** + * Signal power request to indicate a charger update that affects the port. + * + * @param port USB-C port number + */ +void pd_set_new_power_request(int port); + +/** + * Return true if partner port is a DTS or TS capable of entering debug + * mode (eg. is presenting Rp/Rp or Rd/Rd). + * + * @param port USB-C port number + */ +int pd_ts_dts_plugged(int port); + +/* ----- Logging ----- */ +#ifdef CONFIG_USB_PD_LOGGING +/** + * Record one event in the PD logging FIFO. + * + * @param type event type as defined by PD_EVENT_xx in ec_commands.h + * @param size_port payload size and port num (defined by PD_LOG_PORT_SIZE) + * @param data type-defined information + * @param payload pointer to the optional payload (0..16 bytes) + */ +void pd_log_event(uint8_t type, uint8_t size_port, + uint16_t data, void *payload); + +/** + * Retrieve one logged event and prepare a VDM with it. + * + * Used to answer the VDO_CMD_GET_LOG unstructured VDM. + * + * @param payload pointer to the payload data buffer (must be 7 words) + * @return number of 32-bit words in the VDM payload. + */ +int pd_vdm_get_log_entry(uint32_t *payload); +#else /* CONFIG_USB_PD_LOGGING */ +static inline void pd_log_event(uint8_t type, uint8_t size_port, + uint16_t data, void *payload) {} +static inline int pd_vdm_get_log_entry(uint32_t *payload) { return 0; } +#endif /* CONFIG_USB_PD_LOGGING */ + +#endif /* __CROS_EC_USB_PD_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.c b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.c new file mode 100644 index 00000000..49b9cdad --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.c @@ -0,0 +1,1019 @@ +/* Copyright (c) 2014 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 "USBC_TCPM/tcpm.h" +#include "usb_pd.h" +#include +#ifdef CONFIG_COMMON_RUNTIME +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) +#else +#define CPRINTS(format, args...) +#define CPRINTF(format, args...) +#endif + +static int rw_flash_changed = 1; + +int pd_check_requested_voltage(uint32_t rdo, const int port) { + int max_ma = rdo & 0x3FF; + int op_ma = (rdo >> 10) & 0x3FF; + int idx = RDO_POS(rdo); + uint32_t pdo; + uint32_t pdo_ma; +#if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ + defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) + const uint32_t *src_pdo; + const int pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port); +#else + const uint32_t *src_pdo = pd_src_pdo; + const int pdo_cnt = pd_src_pdo_cnt; +#endif + + /* Board specific check for this request */ + if (pd_board_check_request(rdo, pdo_cnt)) + return EC_ERROR_INVAL; + + /* check current ... */ + pdo = src_pdo[idx - 1]; + pdo_ma = (pdo & 0x3ff); + if (op_ma > pdo_ma) + return EC_ERROR_INVAL; /* too much op current */ + if (max_ma > pdo_ma && !(rdo & RDO_CAP_MISMATCH)) + return EC_ERROR_INVAL; /* too much max current */ + + CPRINTF("Requested %d V %d mA (for %d/%d mA)\n", + ((pdo >> 10) & 0x3ff) * 50, (pdo & 0x3ff) * 10, + op_ma * 10, max_ma * 10); + + /* Accept the requested voltage */ + return EC_SUCCESS; +} + +static int stub_pd_board_check_request(uint32_t rdo, int pdo_cnt) { + int idx = RDO_POS(rdo); + + /* Check for invalid index */ + return (!idx || idx > pdo_cnt) ? EC_ERROR_INVAL : EC_SUCCESS; +} +int pd_board_check_request(uint32_t, int) __attribute__((weak, alias("stub_pd_board_check_request"))); + +#ifdef CONFIG_USB_PD_DUAL_ROLE +/* Last received source cap */ +static uint32_t pd_src_caps[CONFIG_USB_PD_PORT_COUNT][PDO_MAX_OBJECTS]; +static uint8_t pd_src_cap_cnt[CONFIG_USB_PD_PORT_COUNT]; + +/* Cap on the max voltage requested as a sink (in millivolts) */ +static unsigned max_request_mv = PD_MAX_VOLTAGE_MV; /* no cap */ + +int pd_find_pdo_index(int port, int max_mv, uint32_t *selected_pdo) { + int i, uw, mv, ma; + int ret = 0; + int __attribute__((unused)) cur_mv = 0; + int cur_uw = 0; + int prefer_cur; + const uint32_t *src_caps = pd_src_caps[port]; + + /* max voltage is always limited by this boards max request */ + max_mv = MIN(max_mv, PD_MAX_VOLTAGE_MV); + + /* Get max power that is under our max voltage input */ + for (i = 0; i < pd_src_cap_cnt[port]; i++) { + /* its an unsupported Augmented PDO (PD3.0) */ + if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) + continue; + + mv = ((src_caps[i] >> 10) & 0x3FF) * 50; + /* Skip invalid voltage */ + if (!mv) + continue; + /* Skip any voltage not supported by this board */ + if (!pd_is_valid_input_voltage(mv)) + continue; + + if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { + uw = 250000 * (src_caps[i] & 0x3FF); + } else { + ma = (src_caps[i] & 0x3FF) * 10; + ma = MIN(ma, PD_MAX_CURRENT_MA); + uw = ma * mv; + } + + if (mv > max_mv) + continue; + uw = MIN(uw, PD_MAX_POWER_MW * 1000); + prefer_cur = 0; + + /* Apply special rules in case of 'tie' */ +#ifdef PD_PREFER_LOW_VOLTAGE + if (uw == cur_uw && mv < cur_mv) + prefer_cur = 1; +#elif defined(PD_PREFER_HIGH_VOLTAGE) + if (uw == cur_uw && mv > cur_mv) + prefer_cur = 1; +#endif + /* Prefer higher power, except for tiebreaker */ + if (uw > cur_uw || prefer_cur) { + ret = i; + cur_uw = uw; + cur_mv = mv; + } + } + + if (selected_pdo) + *selected_pdo = src_caps[ret]; + + return ret; +} + +void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *mv) { + int max_ma, uw; + + *mv = ((pdo >> 10) & 0x3FF) * 50; + + if (*mv == 0) { + CPRINTF("ERR:PDO mv=0\n"); + *ma = 0; + return; + } + + if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { + uw = 250000 * (pdo & 0x3FF); + max_ma = 1000 * MIN(1000 * uw, PD_MAX_POWER_MW) / *mv; + } else { + max_ma = 10 * (pdo & 0x3FF); + max_ma = MIN(max_ma, PD_MAX_POWER_MW * 1000 / *mv); + } + + *ma = MIN(max_ma, PD_MAX_CURRENT_MA); +} + +int pd_build_request(int port, uint32_t *rdo, uint32_t *ma, uint32_t *mv, + enum pd_request_type req_type) { + uint32_t pdo; + int pdo_index, flags = 0; + int uw; + int max_or_min_ma; + int max_or_min_mw; + + if (req_type == PD_REQUEST_VSAFE5V) { + /* src cap 0 should be vSafe5V */ + pdo_index = 0; + pdo = pd_src_caps[port][0]; + } else { + /* find pdo index for max voltage we can request */ + pdo_index = pd_find_pdo_index(port, max_request_mv, &pdo); + } + + pd_extract_pdo_power(pdo, ma, mv); + uw = *ma * *mv; + /* Mismatch bit set if less power offered than the operating power */ + if (uw < (1000 * PD_OPERATING_POWER_MW)) + flags |= RDO_CAP_MISMATCH; + +#ifdef CONFIG_USB_PD_GIVE_BACK + /* Tell source we are give back capable. */ + flags |= RDO_GIVE_BACK; + + /* + * BATTERY PDO: Inform the source that the sink will reduce + * power to this minimum level on receipt of a GotoMin Request. + */ + max_or_min_mw = PD_MIN_POWER_MW; + + /* + * FIXED or VARIABLE PDO: Inform the source that the sink will reduce + * current to this minimum level on receipt of a GotoMin Request. + */ + max_or_min_ma = PD_MIN_CURRENT_MA; +#else + /* + * Can't give back, so set maximum current and power to operating + * level. + */ + max_or_min_ma = *ma; + max_or_min_mw = uw / 1000; +#endif + + if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { + int mw = uw / 1000; + *rdo = RDO_BATT(pdo_index + 1, mw, max_or_min_mw, flags); + } else { + *rdo = RDO_FIXED(pdo_index + 1, *ma, max_or_min_ma, flags); + } + return EC_SUCCESS; +} + +void pd_process_source_cap(int port, int cnt, uint32_t *src_caps) { +#ifdef CONFIG_CHARGE_MANAGER + uint32_t ma, mv, pdo; +#endif + int i; + + pd_src_cap_cnt[port] = cnt; + for (i = 0; i < cnt; i++) + pd_src_caps[port][i] = *src_caps++; + +#ifdef CONFIG_CHARGE_MANAGER + /* Get max power info that we could request */ + pd_find_pdo_index(port, PD_MAX_VOLTAGE_MV, &pdo); + pd_extract_pdo_power(pdo, &ma, &mv); + + /* Set max. limit, but apply 500mA ceiling */ + //charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, PD_MIN_MA); + pd_set_input_current_limit(port, ma, mv); +#endif +} + +#pragma weak pd_process_source_cap_callback +void pd_process_source_cap_callback(int port, int cnt, uint32_t *src_caps) { +} + +void pd_set_max_voltage(unsigned mv) { + max_request_mv = mv; +} + +unsigned pd_get_max_voltage(void) { + return max_request_mv; +} + +int pd_charge_from_device(uint16_t vid, uint16_t pid) { + /* TODO: rewrite into table if we get more of these */ + /* + * White-list Apple charge-through accessory since it doesn't set + * externally powered bit, but we still need to charge from it when + * we are a sink. + */ + return (vid == USB_VID_APPLE && (pid == 0x1012 || pid == 0x1013)); +} +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + +#ifdef CONFIG_USB_PD_ALT_MODE + +#ifdef CONFIG_USB_PD_ALT_MODE_DFP + +static struct pd_policy pe[CONFIG_USB_PD_PORT_COUNT]; + +void pd_dfp_pe_init(int port) +{ + memset(&pe[port], 0, sizeof(struct pd_policy)); +} + +static void dfp_consume_identity(int port, int cnt, uint32_t *payload) +{ + int ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]); + size_t identity_size = MIN(sizeof(pe[port].identity), + (cnt - 1) * sizeof(uint32_t)); + pd_dfp_pe_init(port); + memcpy(&pe[port].identity, payload + 1, identity_size); + switch (ptype) { + case IDH_PTYPE_AMA: + /* TODO(tbroch) do I disable VBUS here if power contract + * requested it + */ + if (!PD_VDO_AMA_VBUS_REQ(payload[VDO_I(AMA)])) + pd_power_supply_reset(port); + +#if defined(CONFIG_USB_PD_DUAL_ROLE) && defined(CONFIG_USBC_VCONN_SWAP) + /* Adapter is requesting vconn, try to supply it */ + if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)])) + pd_try_vconn_src(port); +#endif + break; + default: + break; + } +} + +static int dfp_discover_svids(int port, uint32_t *payload) +{ + payload[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID); + return 1; +} + +static void dfp_consume_svids(int port, uint32_t *payload) +{ + int i; + uint32_t *ptr = payload + 1; + uint16_t svid0, svid1; + + for (i = pe[port].svid_cnt; i < pe[port].svid_cnt + 12; i += 2) { + if (i == SVID_DISCOVERY_MAX) { + CPRINTF("ERR:SVIDCNT\n"); + break; + } + + svid0 = PD_VDO_SVID_SVID0(*ptr); + if (!svid0) + break; + pe[port].svids[i].svid = svid0; + pe[port].svid_cnt++; + + svid1 = PD_VDO_SVID_SVID1(*ptr); + if (!svid1) + break; + pe[port].svids[i + 1].svid = svid1; + pe[port].svid_cnt++; + ptr++; + } + /* TODO(tbroch) need to re-issue discover svids if > 12 */ + if (i && ((i % 12) == 0)) + CPRINTF("ERR:SVID+12\n"); +} + +static int dfp_discover_modes(int port, uint32_t *payload) +{ + uint16_t svid = pe[port].svids[pe[port].svid_idx].svid; + if (pe[port].svid_idx >= pe[port].svid_cnt) + return 0; + payload[0] = VDO(svid, 1, CMD_DISCOVER_MODES); + return 1; +} + +static void dfp_consume_modes(int port, int cnt, uint32_t *payload) +{ + int idx = pe[port].svid_idx; + pe[port].svids[idx].mode_cnt = cnt - 1; + if (pe[port].svids[idx].mode_cnt < 0) { + CPRINTF("ERR:NOMODE\n"); + } else { + memcpy(pe[port].svids[pe[port].svid_idx].mode_vdo, &payload[1], + sizeof(uint32_t) * pe[port].svids[idx].mode_cnt); + } + + pe[port].svid_idx++; +} + +static int get_mode_idx(int port, uint16_t svid) +{ + int i; + + for (i = 0; i < PD_AMODE_COUNT; i++) { + if (pe[port].amodes[i].fx->svid == svid) + return i; + } + return -1; +} + +static struct svdm_amode_data *get_modep(int port, uint16_t svid) +{ + int idx = get_mode_idx(port, svid); + + return (idx == -1) ? NULL : &pe[port].amodes[idx]; +} + +int pd_alt_mode(int port, uint16_t svid) +{ + struct svdm_amode_data *modep = get_modep(port, svid); + + return (modep) ? modep->opos : -1; +} + +int allocate_mode(int port, uint16_t svid) +{ + int i, j; + struct svdm_amode_data *modep; + int mode_idx = get_mode_idx(port, svid); + + if (mode_idx != -1) + return mode_idx; + + /* There's no space to enter another mode */ + if (pe[port].amode_idx == PD_AMODE_COUNT) { + CPRINTF("ERR:NO AMODE SPACE\n"); + return -1; + } + + /* Allocate ... if SVID == 0 enter default supported policy */ + for (i = 0; i < supported_modes_cnt; i++) { + if (!&supported_modes[i]) + continue; + + for (j = 0; j < pe[port].svid_cnt; j++) { + struct svdm_svid_data *svidp = &pe[port].svids[j]; + if ((svidp->svid != supported_modes[i].svid) || + (svid && (svidp->svid != svid))) + continue; + + modep = &pe[port].amodes[pe[port].amode_idx]; + modep->fx = &supported_modes[i]; + modep->data = &pe[port].svids[j]; + pe[port].amode_idx++; + return pe[port].amode_idx - 1; + } + } + return -1; +} + +/* + * Enter default mode ( payload[0] == 0 ) or attempt to enter mode via svid & + * opos +*/ +uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos) +{ + int mode_idx = allocate_mode(port, svid); + struct svdm_amode_data *modep; + uint32_t mode_caps; + + if (mode_idx == -1) + return 0; + modep = &pe[port].amodes[mode_idx]; + + if (!opos) { + /* choose the lowest as default */ + modep->opos = 1; + } else if (opos <= modep->data->mode_cnt) { + modep->opos = opos; + } else { + CPRINTF("opos error\n"); + return 0; + } + + mode_caps = modep->data->mode_vdo[modep->opos - 1]; + if (modep->fx->enter(port, mode_caps) == -1) + return 0; + + /* SVDM to send to UFP for mode entry */ + return VDO(modep->fx->svid, 1, CMD_ENTER_MODE | VDO_OPOS(modep->opos)); +} + +static int validate_mode_request(struct svdm_amode_data *modep, + uint16_t svid, int opos) +{ + if (!modep->fx) + return 0; + + if (svid != modep->fx->svid) { + CPRINTF("ERR:svid r:0x%04x != c:0x%04x\n", + svid, modep->fx->svid); + return 0; + } + + if (opos != modep->opos) { + CPRINTF("ERR:opos r:%d != c:%d\n", + opos, modep->opos); + return 0; + } + + return 1; +} + +static void dfp_consume_attention(int port, uint32_t *payload) +{ + uint16_t svid = PD_VDO_VID(payload[0]); + int opos = PD_VDO_OPOS(payload[0]); + struct svdm_amode_data *modep = get_modep(port, svid); + + if (!modep || !validate_mode_request(modep, svid, opos)) + return; + + if (modep->fx->attention) + modep->fx->attention(port, payload); +} + +/* + * This algorithm defaults to choosing higher pin config over lower ones in + * order to prefer multi-function if desired. + * + * NAME | SIGNALING | OUTPUT TYPE | MULTI-FUNCTION | PIN CONFIG + * ------------------------------------------------------------- + * A | USB G2 | ? | no | 00_0001 + * B | USB G2 | ? | yes | 00_0010 + * C | DP | CONVERTED | no | 00_0100 + * D | PD | CONVERTED | yes | 00_1000 + * E | DP | DP | no | 01_0000 + * F | PD | DP | yes | 10_0000 + * + * if UFP has NOT asserted multi-function preferred code masks away B/D/F + * leaving only A/C/E. For single-output dongles that should leave only one + * possible pin config depending on whether its a converter DP->(VGA|HDMI) or DP + * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C + * receptacle must always choose C/D in those cases. + */ +int pd_dfp_dp_get_pin_mode(int port, uint32_t status) +{ + struct svdm_amode_data *modep = get_modep(port, USB_SID_DISPLAYPORT); + uint32_t mode_caps; + uint32_t pin_caps; + if (!modep) + return 0; + + mode_caps = modep->data->mode_vdo[modep->opos - 1]; + + /* TODO(crosbug.com/p/39656) revisit with DFP that can be a sink */ + pin_caps = PD_DP_PIN_CAPS(mode_caps); + + /* if don't want multi-function then ignore those pin configs */ + if (!PD_VDO_DPSTS_MF_PREF(status)) + pin_caps &= ~MODE_DP_PIN_MF_MASK; + + /* TODO(crosbug.com/p/39656) revisit if DFP drives USB Gen 2 signals */ + pin_caps &= ~MODE_DP_PIN_BR2_MASK; + + /* if C/D present they have precedence over E/F for USB-C->USB-C */ + if (pin_caps & (MODE_DP_PIN_C | MODE_DP_PIN_D)) + pin_caps &= ~(MODE_DP_PIN_E | MODE_DP_PIN_F); + + /* get_next_bit returns undefined for zero */ + if (!pin_caps) + return 0; + + return 1 << get_next_bit(&pin_caps); +} + +int pd_dfp_exit_mode(int port, uint16_t svid, int opos) +{ + struct svdm_amode_data *modep; + int idx; + + /* + * Empty svid signals we should reset DFP VDM state by exiting all + * entered modes then clearing state. This occurs when we've + * disconnected or for hard reset. + */ + if (!svid) { + for (idx = 0; idx < PD_AMODE_COUNT; idx++) + if (pe[port].amodes[idx].fx) + pe[port].amodes[idx].fx->exit(port); + + pd_dfp_pe_init(port); + return 0; + } + + /* + * TODO(crosbug.com/p/33946) : below needs revisited to allow multiple + * mode exit. Additionally it should honor OPOS == 7 as DFP's request + * to exit all modes. We currently don't have any UFPs that support + * multiple modes on one SVID. + */ + modep = get_modep(port, svid); + if (!modep || !validate_mode_request(modep, svid, opos)) + return 0; + + /* call DFPs exit function */ + modep->fx->exit(port); + /* exit the mode */ + modep->opos = 0; + return 1; +} + +uint16_t pd_get_identity_vid(int port) +{ + return PD_IDH_VID(pe[port].identity[0]); +} + +uint16_t pd_get_identity_pid(int port) +{ + return PD_PRODUCT_PID(pe[port].identity[2]); +} + +#ifdef CONFIG_CMD_USB_PD_PE +static void dump_pe(int port) +{ + const char * const idh_ptype_names[] = { + "UNDEF", "Hub", "Periph", "PCable", "ACable", "AMA", + "RSV6", "RSV7"}; + + int i, j, idh_ptype; + struct svdm_amode_data *modep; + uint32_t mode_caps; + + if (pe[port].identity[0] == 0) { + ccprintf("No identity discovered yet.\n"); + return; + } + idh_ptype = PD_IDH_PTYPE(pe[port].identity[0]); + ccprintf("IDENT:\n"); + ccprintf("\t[ID Header] %08x :: %s, VID:%04x\n", pe[port].identity[0], + idh_ptype_names[idh_ptype], pd_get_identity_vid(port)); + ccprintf("\t[Cert Stat] %08x\n", pe[port].identity[1]); + for (i = 2; i < ARRAY_SIZE(pe[port].identity); i++) { + ccprintf("\t"); + if (pe[port].identity[i]) + ccprintf("[%d] %08x ", i, pe[port].identity[i]); + } + ccprintf("\n"); + + if (pe[port].svid_cnt < 1) { + ccprintf("No SVIDS discovered yet.\n"); + return; + } + + for (i = 0; i < pe[port].svid_cnt; i++) { + ccprintf("SVID[%d]: %04x MODES:", i, pe[port].svids[i].svid); + for (j = 0; j < pe[port].svids[j].mode_cnt; j++) + ccprintf(" [%d] %08x", j + 1, + pe[port].svids[i].mode_vdo[j]); + ccprintf("\n"); + modep = get_modep(port, pe[port].svids[i].svid); + if (modep) { + mode_caps = modep->data->mode_vdo[modep->opos - 1]; + ccprintf("MODE[%d]: svid:%04x caps:%08x\n", modep->opos, + modep->fx->svid, mode_caps); + } + } +} + +static int command_pe(int argc, char **argv) +{ + int port; + char *e; + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + /* command: pe */ + port = strtoi(argv[1], &e, 10); + if (*e || port >= CONFIG_USB_PD_PORT_COUNT) + return EC_ERROR_PARAM2; + if (!strncasecmp(argv[2], "dump", 4)) + dump_pe(port); + + return EC_SUCCESS; +} + +DECLARE_CONSOLE_COMMAND(pe, command_pe, + " dump", + "USB PE"); +#endif /* CONFIG_CMD_USB_PD_PE */ + +#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ + +int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { + int cmd = PD_VDO_CMD(payload[0]); + int cmd_type = PD_VDO_CMDT(payload[0]); + int (*func)(int port, uint32_t *payload) = NULL; + + int rsize = 1; /* VDM header at a minimum */ + + payload[0] &= ~VDO_CMDT_MASK; + *rpayload = payload; + + if (cmd_type == CMDT_INIT) { + switch (cmd) { + case CMD_DISCOVER_IDENT: + func = svdm_rsp.identity; + break; + case CMD_DISCOVER_SVID: + func = svdm_rsp.svids; + break; + case CMD_DISCOVER_MODES: + func = svdm_rsp.modes; + break; + case CMD_ENTER_MODE: + func = svdm_rsp.enter_mode; + break; + case CMD_DP_STATUS: + func = svdm_rsp.amode->status; + break; + case CMD_DP_CONFIG: + func = svdm_rsp.amode->config; + break; + case CMD_EXIT_MODE: + func = svdm_rsp.exit_mode; + break; +#ifdef CONFIG_USB_PD_ALT_MODE_DFP + case CMD_ATTENTION: + /* + * attention is only SVDM with no response + * (just goodCRC) return zero here. + */ + dfp_consume_attention(port, payload); + return 0; +#endif + default: + CPRINTF("ERR:CMD:%d\n", cmd); + rsize = 0; + } + if (func) + rsize = func(port, payload); + else + /* not supported : NACK it */ + rsize = 0; + if (rsize >= 1) + payload[0] |= VDO_CMDT(CMDT_RSP_ACK); + else if (!rsize) { + payload[0] |= VDO_CMDT(CMDT_RSP_NAK); + rsize = 1; + } else { + payload[0] |= VDO_CMDT(CMDT_RSP_BUSY); + rsize = 1; + } + payload[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port)); + } else if (cmd_type == CMDT_RSP_ACK) { +#ifdef CONFIG_USB_PD_ALT_MODE_DFP + struct svdm_amode_data *modep; + + modep = get_modep(port, PD_VDO_VID(payload[0])); +#endif + switch (cmd) { +#ifdef CONFIG_USB_PD_ALT_MODE_DFP + case CMD_DISCOVER_IDENT: + dfp_consume_identity(port, cnt, payload); + rsize = dfp_discover_svids(port, payload); +#ifdef CONFIG_CHARGE_MANAGER + if (pd_charge_from_device(pd_get_identity_vid(port), + pd_get_identity_pid(port))) + charge_manager_update_dualrole(port, + CAP_DEDICATED); +#endif + break; + case CMD_DISCOVER_SVID: + dfp_consume_svids(port, payload); + rsize = dfp_discover_modes(port, payload); + break; + case CMD_DISCOVER_MODES: + dfp_consume_modes(port, cnt, payload); + rsize = dfp_discover_modes(port, payload); + /* enter the default mode for DFP */ + if (!rsize) { + payload[0] = pd_dfp_enter_mode(port, 0, 0); + if (payload[0]) + rsize = 1; + } + break; + case CMD_ENTER_MODE: + if (!modep) { + rsize = 0; + } else { + if (!modep->opos) + pd_dfp_enter_mode(port, 0, 0); + + if (modep->opos) { + rsize = modep->fx->status(port, + payload); + payload[0] |= PD_VDO_OPOS(modep->opos); + } + } + break; + case CMD_DP_STATUS: + /* DP status response & UFP's DP attention have same + payload */ + dfp_consume_attention(port, payload); + if (modep && modep->opos) + rsize = modep->fx->config(port, payload); + else + rsize = 0; + break; + case CMD_DP_CONFIG: + if (modep && modep->opos && modep->fx->post_config) + modep->fx->post_config(port); + /* no response after DFPs ack */ + rsize = 0; + break; + case CMD_EXIT_MODE: + /* no response after DFPs ack */ + rsize = 0; + break; +#endif + case CMD_ATTENTION: + /* no response after DFPs ack */ + rsize = 0; + break; + default: + CPRINTF("ERR:CMD:%d\n", cmd); + rsize = 0; + } + + payload[0] |= VDO_CMDT(CMDT_INIT); + payload[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port)); +#ifdef CONFIG_USB_PD_ALT_MODE_DFP + } else if (cmd_type == CMDT_RSP_BUSY) { + switch (cmd) { + case CMD_DISCOVER_IDENT: + case CMD_DISCOVER_SVID: + case CMD_DISCOVER_MODES: + /* resend if its discovery */ + rsize = 1; + break; + case CMD_ENTER_MODE: + /* Error */ + CPRINTF("ERR:ENTBUSY\n"); + rsize = 0; + break; + case CMD_EXIT_MODE: + rsize = 0; + break; + default: + rsize = 0; + } + } else if (cmd_type == CMDT_RSP_NAK) { + /* nothing to do */ + rsize = 0; +#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ + } else { + CPRINTF("ERR:CMDT:%d\n", cmd); + /* do not answer */ + rsize = 0; + } + return rsize; +} + +#else + +int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) +{ + return 0; +} + +#endif /* CONFIG_USB_PD_ALT_MODE */ + +#ifndef CONFIG_USB_PD_CUSTOM_VDM +int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { + return 0; +} +#endif /* !CONFIG_USB_PD_CUSTOM_VDM */ + +static void pd_usb_billboard_deferred(void) { +#if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP) \ + && !defined(CONFIG_USB_PD_SIMPLE_DFP) && defined(CONFIG_USB_BOS) + + /* + * TODO(tbroch) + * 1. Will we have multiple type-C port UFPs + * 2. Will there be other modes applicable to DFPs besides DP + */ + if (!pd_alt_mode(0, USB_SID_DISPLAYPORT)) + usb_connect(); + +#endif +} +DECLARE_DEFERRED( pd_usb_billboard_deferred); + +#ifdef CONFIG_USB_PD_ALT_MODE_DFP +static int hc_remote_pd_discovery(struct host_cmd_handler_args *args) +{ + const uint8_t *port = args->params; + struct ec_params_usb_pd_discovery_entry *r = args->response; + + if (*port >= CONFIG_USB_PD_PORT_COUNT) + return EC_RES_INVALID_PARAM; + + r->vid = pd_get_identity_vid(*port); + r->ptype = PD_IDH_PTYPE(pe[*port].identity[0]); + /* pid only included if vid is assigned */ + if (r->vid) + r->pid = PD_PRODUCT_PID(pe[*port].identity[2]); + + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DISCOVERY, + hc_remote_pd_discovery, + EC_VER_MASK(0)); + +static int hc_remote_pd_get_amode(struct host_cmd_handler_args *args) +{ + struct svdm_amode_data *modep; + const struct ec_params_usb_pd_get_mode_request *p = args->params; + struct ec_params_usb_pd_get_mode_response *r = args->response; + + if (p->port >= CONFIG_USB_PD_PORT_COUNT) + return EC_RES_INVALID_PARAM; + + /* no more to send */ + if (p->svid_idx >= pe[p->port].svid_cnt) { + r->svid = 0; + args->response_size = sizeof(r->svid); + return EC_RES_SUCCESS; + } + + r->svid = pe[p->port].svids[p->svid_idx].svid; + r->opos = 0; + memcpy(r->vdo, pe[p->port].svids[p->svid_idx].mode_vdo, 24); + modep = get_modep(p->port, r->svid); + + if (modep) + r->opos = pd_alt_mode(p->port, r->svid); + + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_GET_AMODE, + hc_remote_pd_get_amode, + EC_VER_MASK(0)); + +#endif + +#define FW_RW_END (CONFIG_EC_WRITABLE_STORAGE_OFF + \ + CONFIG_RW_STORAGE_OFF + CONFIG_RW_SIZE) + +/* + uint8_t *flash_hash_rw(void) + { + static struct sha256_ctx ctx; + + // re-calculate RW hash when changed as its time consuming + if (rw_flash_changed) { + rw_flash_changed = 0; + SHA256_init(&ctx); + SHA256_update(&ctx, (void *)CONFIG_PROGRAM_MEMORY_BASE + + CONFIG_RW_MEM_OFF, + CONFIG_RW_SIZE - RSANUMBYTES); + return SHA256_final(&ctx); + } else { + return ctx.buf; + } + } + + + void pd_get_info(uint32_t *info_data) + { + void *rw_hash = flash_hash_rw(); + + // copy first 20 bytes of RW hash + memcpy(info_data, rw_hash, 5 * sizeof(uint32_t)); + // copy other info into data msg + #if defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR) && \ + defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR) + info_data[5] = VDO_INFO(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR, + CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR, + ver_get_numcommits(), + (system_get_image_copy() != SYSTEM_IMAGE_RO)); + #else + info_data[5] = 0; + #endif + } + + int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload) + { + static int flash_offset; + int rsize = 1; // default is just VDM header returned + + switch (PD_VDO_CMD(payload[0])) { + case VDO_CMD_VERSION: + memcpy(payload + 1, ¤t_image_data.version, 24); + rsize = 7; + break; + case VDO_CMD_REBOOT: + // ensure the power supply is in a safe state + pd_power_supply_reset(0); + system_reset(0); + break; + case VDO_CMD_READ_INFO: + // copy info into response + pd_get_info(payload + 1); + rsize = 7; + break; + case VDO_CMD_FLASH_ERASE: + // do not kill the code under our feet + if (system_get_image_copy() != SYSTEM_IMAGE_RO) + break; + pd_log_event(PD_EVENT_ACC_RW_ERASE, 0, 0, NULL); + flash_offset = CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_STORAGE_OFF; + flash_physical_erase(CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_STORAGE_OFF, CONFIG_RW_SIZE); + rw_flash_changed = 1; + break; + case VDO_CMD_FLASH_WRITE: + // do not kill the code under our feet + if ((system_get_image_copy() != SYSTEM_IMAGE_RO) || + (flash_offset < CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_STORAGE_OFF)) + break; + flash_physical_write(flash_offset, 4*(cnt - 1), + (const char *)(payload+1)); + flash_offset += 4*(cnt - 1); + rw_flash_changed = 1; + break; + case VDO_CMD_ERASE_SIG: + // this is not touching the code area + { + uint32_t zero = 0; + int offset; + // zeroes the area containing the RSA signature + for (offset = FW_RW_END - RSANUMBYTES; + offset < FW_RW_END; offset += 4) + flash_physical_write(offset, 4, + (const char *)&zero); + } + break; + default: + // Unknown : do not answer + return 0; + } + return rsize; + } + */ +#ifdef CONFIG_USB_PD_DISCHARGE +void pd_set_vbus_discharge(int port, int enable) +{ + static struct mutex discharge_lock[CONFIG_USB_PD_PORT_COUNT]; + + mutex_lock(&discharge_lock[port]); + enable &= !board_vbus_source_enabled(port); +#ifdef CONFIG_USB_PD_DISCHARGE_GPIO + if (!port) + gpio_set_level(GPIO_USB_C0_DISCHARGE, enable); +#if CONFIG_USB_PD_PORT_COUNT > 1 + else + gpio_set_level(GPIO_USB_C1_DISCHARGE, enable); +#endif /* CONFIG_USB_PD_PORT_COUNT */ +#elif defined(CONFIG_USB_PD_DISCHARGE_TCPC) + tcpc_discharge_vbus(port, enable); +#else +#error "PD discharge implementation not defined" +#endif + mutex_unlock(&discharge_lock[port]); +} +#endif /* CONFIG_USB_PD_DISCHARGE */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.c b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.c new file mode 100644 index 00000000..d08379ba --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.c @@ -0,0 +1,4276 @@ +/* Copyright (c) 2014 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 "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "USBC_TCPM/tcpm.h" +#include "usb_pd_driver.h" +#include + +#ifdef CONFIG_COMMON_RUNTIME +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) + +BUILD_ASSERT(CONFIG_USB_PD_PORT_COUNT <= EC_USB_PD_MAX_PORTS); + +/* + * Debug log level - higher number == more log + * Level 0: Log state transitions + * Level 1: Level 0, plus state name + * Level 2: Level 1, plus packet info + * Level 3: Level 2, plus ping packet and packet dump on error + * + * Note that higher log level causes timing changes and thus may affect + * performance. + * + * Can be limited to constant debug_level by CONFIG_USB_PD_DEBUG_LEVEL + */ +#ifdef CONFIG_USB_PD_DEBUG_LEVEL +static const int debug_level = CONFIG_USB_PD_DEBUG_LEVEL; +#else +static int debug_level; +#endif + +/* + * PD communication enabled flag. When false, PD state machine still + * detects source/sink connection and disconnection, and will still + * provide VBUS, but never sends any PD communication. + */ +static uint8_t pd_comm_enabled[CONFIG_USB_PD_PORT_COUNT]; +#else /* CONFIG_COMMON_RUNTIME */ +#define CPRINTF(format, args...) +#define CPRINTS(format, args...) +static const int debug_level; +#endif + +#ifdef CONFIG_USB_PD_DUAL_ROLE +#define DUAL_ROLE_IF_ELSE(port, sink_clause, src_clause) \ + (pd[port].power_role == PD_ROLE_SINK ? (sink_clause) : (src_clause)) +#else +#define DUAL_ROLE_IF_ELSE(port, sink_clause, src_clause) (src_clause) +#endif + +#define READY_RETURN_STATE(port) DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_READY, \ + PD_STATE_SRC_READY) + +/* Type C supply voltage (mV) */ +#define TYPE_C_VOLTAGE 5000 /* mV */ + +/* PD counter definitions */ +#define PD_MESSAGE_ID_COUNT 7 +#define PD_HARD_RESET_COUNT 2 +#define PD_CAPS_COUNT 50 +#define PD_SNK_CAP_RETRIES 3 + +enum vdm_states { + VDM_STATE_ERR_BUSY = -3, + VDM_STATE_ERR_SEND = -2, + VDM_STATE_ERR_TMOUT = -1, + VDM_STATE_DONE = 0, + /* Anything >0 represents an active state */ + VDM_STATE_READY = 1, + VDM_STATE_BUSY = 2, + VDM_STATE_WAIT_RSP_BUSY = 3, +}; + +#ifdef CONFIG_USB_PD_DUAL_ROLE +/* Port dual-role state */ +enum pd_dual_role_states drp_state = CONFIG_USB_PD_INITIAL_DRP_STATE; + +/* Enable variable for Try.SRC states */ +static uint8_t pd_try_src_enable; +#endif + +#ifdef CONFIG_USB_PD_REV30 +/* + * The spec. revision is used to index into this array. + * Rev 0 (PD 1.0) - return PD_CTRL_REJECT + * Rev 1 (PD 2.0) - return PD_CTRL_REJECT + * Rev 2 (PD 3.0) - return PD_CTRL_NOT_SUPPORTED + */ +static const uint8_t refuse[] = { + PD_CTRL_REJECT, PD_CTRL_REJECT, PD_CTRL_NOT_SUPPORTED}; +#define REFUSE(r) refuse[r] +#else +#define REFUSE(r) PD_CTRL_REJECT +#endif + +#ifdef CONFIG_USB_PD_REV30 +/* + * The spec. revision is used to index into this array. + * Rev 0 (VDO 1.0) - return VDM_VER10 + * Rev 1 (VDO 1.0) - return VDM_VER10 + * Rev 2 (VDO 2.0) - return VDM_VER20 + */ +static const uint8_t vdo_ver[] = { + VDM_VER10, VDM_VER10, VDM_VER20}; +#define VDO_VER(v) vdo_ver[v] +#else +#define VDO_VER(v) VDM_VER10 +#endif + +// variables that used to be pd_task, but had to be promoted +// so both pd_init and pd_run_state_machine can see them +static int head; +static int port = TASK_ID_TO_PD_PORT(task_get_current()); +static uint32_t payload[7]; +static int timeout = 10*MSEC; +static int cc1, cc2; +static int res, incoming_packet = 0; +static int hard_reset_count = 0; +#ifdef CONFIG_USB_PD_DUAL_ROLE +static uint64_t next_role_swap = PD_T_DRP_SNK; +#ifndef CONFIG_USB_PD_VBUS_DETECT_NONE +static int snk_hard_reset_vbus_off = 0; +#endif +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +static const int auto_toggle_supported = tcpm_auto_toggle_supported(port); +#endif +#if defined(CONFIG_CHARGE_MANAGER) +static typec_current_t typec_curr = 0, typec_curr_change = 0; +#endif /* CONFIG_CHARGE_MANAGER */ +#endif /* CONFIG_USB_PD_DUAL_ROLE */ +static enum pd_states this_state; +static enum pd_cc_states new_cc_state; +static timestamp_t now; +static int caps_count = 0, hard_reset_sent = 0; +static int snk_cap_count = 0; +static int evt; + +static struct pd_protocol { + /* current port power role (SOURCE or SINK) */ + uint8_t power_role; + /* current port data role (DFP or UFP) */ + uint8_t data_role; + /* 3-bit rolling message ID counter */ + uint8_t msg_id; + /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */ + uint8_t polarity; + /* PD state for port */ + enum pd_states task_state; + /* PD state when we run state handler the last time */ + enum pd_states last_state; + /* bool: request state change to SUSPENDED */ + uint8_t req_suspend_state; + /* The state to go to after timeout */ + enum pd_states timeout_state; + /* port flags, see PD_FLAGS_* */ + uint32_t flags; + /* Timeout for the current state. Set to 0 for no timeout. */ + uint64_t timeout; + /* Time for source recovery after hard reset */ + uint64_t src_recover; + /* Time for CC debounce end */ + uint64_t cc_debounce; + /* The cc state */ + enum pd_cc_states cc_state; + /* status of last transmit */ + uint8_t tx_status; + + /* last requested voltage PDO index */ + int requested_idx; +#ifdef CONFIG_USB_PD_DUAL_ROLE + /* Current limit / voltage based on the last request message */ + uint32_t curr_limit; + uint32_t supply_voltage; + /* Signal charging update that affects the port */ + int new_power_request; + /* Store previously requested voltage request */ + int prev_request_mv; + /* Time for Try.SRC states */ + uint64_t try_src_marker; +#endif + + /* PD state for Vendor Defined Messages */ + enum vdm_states vdm_state; + /* Timeout for the current vdm state. Set to 0 for no timeout. */ + timestamp_t vdm_timeout; + /* next Vendor Defined Message to send */ + uint32_t vdo_data[VDO_MAX_SIZE]; + uint8_t vdo_count; + /* VDO to retry if UFP responder replied busy. */ + uint32_t vdo_retry; + +#ifdef CONFIG_USB_PD_CHROMEOS + /* Attached ChromeOS device id, RW hash, and current RO / RW image */ + uint16_t dev_id; + uint32_t dev_rw_hash[PD_RW_HASH_SIZE/4]; + enum ec_current_image current_image; +#endif +#ifdef CONFIG_USB_PD_REV30 + /* PD Collision avoidance buffer */ + uint16_t ca_buffered; + uint16_t ca_header; + uint32_t ca_buffer[PDO_MAX_OBJECTS]; + enum tcpm_transmit_type ca_type; + /* protocol revision */ + uint8_t rev; +#endif +} pd[CONFIG_USB_PD_PORT_COUNT]; + +#ifdef CONFIG_COMMON_RUNTIME +static const char * const pd_state_names[] = { + "DISABLED", "SUSPENDED", +#ifdef CONFIG_USB_PD_DUAL_ROLE + "SNK_DISCONNECTED", "SNK_DISCONNECTED_DEBOUNCE", + "SNK_HARD_RESET_RECOVER", + "SNK_DISCOVERY", "SNK_REQUESTED", "SNK_TRANSITION", "SNK_READY", + "SNK_SWAP_INIT", "SNK_SWAP_SNK_DISABLE", + "SNK_SWAP_SRC_DISABLE", "SNK_SWAP_STANDBY", "SNK_SWAP_COMPLETE", +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + "SRC_DISCONNECTED", "SRC_DISCONNECTED_DEBOUNCE", + "SRC_HARD_RESET_RECOVER", "SRC_STARTUP", + "SRC_DISCOVERY", "SRC_NEGOCIATE", "SRC_ACCEPTED", "SRC_POWERED", + "SRC_TRANSITION", "SRC_READY", "SRC_GET_SNK_CAP", "DR_SWAP", +#ifdef CONFIG_USB_PD_DUAL_ROLE + "SRC_SWAP_INIT", "SRC_SWAP_SNK_DISABLE", "SRC_SWAP_SRC_DISABLE", + "SRC_SWAP_STANDBY", +#ifdef CONFIG_USBC_VCONN_SWAP + "VCONN_SWAP_SEND", "VCONN_SWAP_INIT", "VCONN_SWAP_READY", +#endif /* CONFIG_USBC_VCONN_SWAP */ +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + "SOFT_RESET", "HARD_RESET_SEND", "HARD_RESET_EXECUTE", "BIST_RX", + "BIST_TX", +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE + "DRP_AUTO_TOGGLE", +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(pd_state_names) == PD_STATE_COUNT); +#endif + +/* + * 4 entry rw_hash table of type-C devices that AP has firmware updates for. + */ +#ifdef CONFIG_COMMON_RUNTIME +#define RW_HASH_ENTRIES 4 +static struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES]; +#endif + +int pd_comm_is_enabled(int port) +{ +#ifdef CONFIG_COMMON_RUNTIME + return pd_comm_enabled[port]; +#else + return 1; +#endif +} + +static inline void set_state_timeout(int port, + uint64_t timeout, + enum pd_states timeout_state) +{ + pd[port].timeout = timeout; + pd[port].timeout_state = timeout_state; +} + +#ifdef CONFIG_USB_PD_REV30 +int pd_get_rev(int port) +{ + return pd[port].rev; +} + +int pd_get_vdo_ver(int port) +{ + return vdo_ver[pd[port].rev]; +} +#endif + +/* Return flag for pd state is connected */ +int pd_is_connected(int port) +{ + if (pd[port].task_state == PD_STATE_DISABLED) + return 0; + +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE + if (pd[port].task_state == PD_STATE_DRP_AUTO_TOGGLE) + return 0; +#endif + + return DUAL_ROLE_IF_ELSE(port, + /* sink */ + pd[port].task_state != PD_STATE_SNK_DISCONNECTED && + pd[port].task_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE, + /* source */ + pd[port].task_state != PD_STATE_SRC_DISCONNECTED && + pd[port].task_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE); +} + +/* + * Return true if partner port is a DTS or TS capable of entering debug + * mode (eg. is presenting Rp/Rp or Rd/Rd). + */ +int pd_ts_dts_plugged(int port) +{ + return pd[port].flags & PD_FLAGS_TS_DTS_PARTNER; +} + +#ifdef CONFIG_USB_PD_DUAL_ROLE +void pd_vbus_low(int port) +{ + pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW; +} + +static inline int pd_is_vbus_present(int port) +{ +#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC + return tcpm_get_vbus_level(port); +#else + return pd_snk_is_vbus_provided(port); +#endif +} +#endif + +static inline void set_state(int port, enum pd_states next_state) +{ + enum pd_states last_state = pd[port].task_state; +#ifdef CONFIG_LOW_POWER_IDLE + int i; +#endif + + set_state_timeout(port, 0, 0); + pd[port].task_state = next_state; + + if (last_state == next_state) + return; + +#ifdef CONFIG_USB_PD_DUAL_ROLE +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE + /* Clear flag to allow DRP auto toggle when possible */ + if (last_state != PD_STATE_DRP_AUTO_TOGGLE) + pd[port].flags &= ~PD_FLAGS_TCPC_DRP_TOGGLE; +#endif + + /* Ignore dual-role toggling between sink and source */ + if ((last_state == PD_STATE_SNK_DISCONNECTED && + next_state == PD_STATE_SRC_DISCONNECTED) || + (last_state == PD_STATE_SRC_DISCONNECTED && + next_state == PD_STATE_SNK_DISCONNECTED)) + return; + + if (next_state == PD_STATE_SRC_DISCONNECTED || + next_state == PD_STATE_SNK_DISCONNECTED) { + /* Clear the input current limit */ + pd_set_input_current_limit(port, 0, 0); +#ifdef CONFIG_CHARGE_MANAGER + //typec_set_input_current_limit(port, 0, 0); + //charge_manager_set_ceil(port, + // CEIL_REQUESTOR_PD, + // CHARGE_CEIL_NONE); +#endif +#ifdef CONFIG_USBC_VCONN + tcpm_set_vconn(port, 0); +#endif +#else /* CONFIG_USB_PD_DUAL_ROLE */ + if (next_state == PD_STATE_SRC_DISCONNECTED) { +#endif + /* + * If we are source, make sure VBUS is off and + * if PD REV3.0, restore RP. + */ + if (pd[port].power_role == PD_ROLE_SOURCE) { + /* + * Rp is restored by pd_power_supply_reset if + * CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT is defined. + */ + pd_power_supply_reset(port); +#if !defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) && \ + defined(CONFIG_USB_PD_REV30) + /* Restore Rp */ + tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP); + tcpm_set_cc(port, TYPEC_CC_RP); +#endif + } +#ifdef CONFIG_USB_PD_REV30 + /* Adjust rev to highest level*/ + pd[port].rev = PD_REV30; +#endif +#ifdef CONFIG_USB_PD_CHROMEOS + pd[port].dev_id = 0; + pd[port].flags &= ~PD_FLAGS_RESET_ON_DISCONNECT_MASK; +#endif +#ifdef CONFIG_CHARGE_MANAGER + //charge_manager_update_dualrole(port, CAP_UNKNOWN); +#endif +#ifdef CONFIG_USB_PD_ALT_MODE_DFP + pd_dfp_exit_mode(port, 0, 0); +#endif +#ifdef CONFIG_USBC_SS_MUX + usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, + pd[port].polarity); +#endif + /* Disable TCPC RX */ + tcpm_set_rx_enable(port, 0); + } + +#ifdef CONFIG_LOW_POWER_IDLE + /* If a PD device is attached then disable deep sleep */ + for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) { + if (pd[i].flags & PD_FLAGS_PREVIOUS_PD_CONN) + break; + } + if (i == CONFIG_USB_PD_PORT_COUNT) + enable_sleep(SLEEP_MASK_USB_PD); + else + disable_sleep(SLEEP_MASK_USB_PD); +#endif + + if (debug_level >= 1) + CPRINTF("C%d st%d %s\n", port, next_state, + pd_state_names[next_state]); + else + CPRINTF("C%d st%d\n", port, next_state); +} + +/* increment message ID counter */ +static void inc_id(int port) +{ + pd[port].msg_id = (pd[port].msg_id + 1) & PD_MESSAGE_ID_COUNT; +} + +#ifdef CONFIG_USB_PD_REV30 +static void sink_can_xmit(int port, int rp) +{ + tcpm_select_rp_value(port, rp); + tcpm_set_cc(port, TYPEC_CC_RP); +} + +static inline void pd_ca_reset(int port) +{ + pd[port].ca_buffered = 0; +} +#endif + +void pd_transmit_complete(int port, int status) +{ + if (status == TCPC_TX_COMPLETE_SUCCESS) + inc_id(port); + + pd[port].tx_status = status; + //task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX, 0); + pd_task_set_event(PD_EVENT_TX, 0); +} + +static int pd_transmit(int port, enum tcpm_transmit_type type, + uint16_t header, const uint32_t *data) +{ + int evt; + + /* If comms are disabled, do not transmit, return error */ + if (!pd_comm_is_enabled(port)) + return -1; +#ifdef CONFIG_USB_PD_REV30 + /* Source-coordinated collision avoidance */ + /* + * In order to avoid message collisions due to asynchronous Messaging + * sent from the Sink, the Source sets Rp to SinkTxOk to indicate to + * the Sink that it is ok to initiate an AMS. When the Source wishes + * to initiate an AMS it sets Rp to SinkTxNG. When the Sink detects + * that Rp is set to SinkTxOk it May initiate an AMS. When the Sink + * detects that Rp is set to SinkTxNG it Shall Not initiate an AMS + * and Shall only send Messages that are part of an AMS the Source has + * initiated. Note that this restriction applies to SOP* AMS’s i.e. + * for both Port to Port and Port to Cable Plug communications. + * + * This starts after an Explicit Contract is in place + * PD R3 V1.1 Section 2.5.2. + * + * Note: a Sink can still send Hard Reset signaling at any time. + */ + if ((pd[port].rev == PD_REV30) && + (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT)) { + if (pd[port].power_role == PD_ROLE_SOURCE) { + /* + * Inform Sink that it can't transmit. If a sink + * transmition is in progress and a collsion occurs, + * a reset is generated. This should be rare because + * all extended messages are chunked. This effectively + * defaults to PD REV 2.0 collision avoidance. + */ + sink_can_xmit(port, SINK_TX_NG); + } else if (type != TCPC_TX_HARD_RESET) { + int cc1; + int cc2; + + tcpm_get_cc(port, &cc1, &cc2); + if (cc1 == TYPEC_CC_VOLT_SNK_1_5 || + cc2 == TYPEC_CC_VOLT_SNK_1_5) { + /* Sink can't transmit now. */ + /* Check if message is already buffered. */ + if (pd[port].ca_buffered) + return -1; + + /* Buffer message and send later. */ + pd[port].ca_type = type; + pd[port].ca_header = header; + memcpy(pd[port].ca_buffer, + data, sizeof(uint32_t) * + PD_HEADER_CNT(header)); + pd[port].ca_buffered = 1; + return 1; + } + } + } +#endif + tcpm_transmit(port, type, header, data); + + /* Wait until TX is complete */ + // Would wait, except that we're making tcpm_transmit blocking + //evt = task_wait_event_mask(PD_EVENT_TX, PD_T_TCPC_TX_TIMEOUT); + +#ifdef CONFIG_USB_PD_REV30 + /* + * If the source just completed a transmit, tell + * the sink it can transmit if it wants to. + */ + if ((pd[port].rev == PD_REV30) && + (pd[port].power_role == PD_ROLE_SOURCE) && + (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT)) { + sink_can_xmit(port, SINK_TX_OK); + } +#endif + + // removing task-based stuff from the library + //if (evt & TASK_EVENT_TIMER) + // return -1; + + /* TODO: give different error condition for failed vs discarded */ + return pd[port].tx_status == TCPC_TX_COMPLETE_SUCCESS ? 1 : -1; +} + +#ifdef CONFIG_USB_PD_REV30 +static void pd_ca_send_pending(int port) +{ + int cc1; + int cc2; + + /* Check if a message has been buffered. */ + if (!pd[port].ca_buffered) + return; + + tcpm_get_cc(port, &cc1, &cc2); + if ((cc1 != TYPEC_CC_VOLT_SNK_1_5) && + (cc2 != TYPEC_CC_VOLT_SNK_1_5)) + if (pd_transmit(port, pd[port].ca_type, + pd[port].ca_header, + pd[port].ca_buffer) < 0) + return; + + /* Message was sent, so free up the buffer. */ + pd[port].ca_buffered = 0; +} +#endif + +static void pd_update_roles(int port) +{ + /* Notify TCPC of role update */ + tcpm_set_msg_header(port, pd[port].power_role, pd[port].data_role); +} + +static int send_control(int port, int type) +{ + int bit_len; + uint16_t header = PD_HEADER(type, pd[port].power_role, + pd[port].data_role, pd[port].msg_id, 0, + pd_get_rev(port), 0); + + bit_len = pd_transmit(port, TCPC_TX_SOP, header, NULL); + if (debug_level >= 2) + CPRINTF("CTRL[%d]>%d\n", type, bit_len); + + return bit_len; +} + +static int send_source_cap(int port) +{ + int bit_len; +#if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ + defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) + const uint32_t *src_pdo; + const int src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port); +#else + const uint32_t *src_pdo = pd_src_pdo; + const int src_pdo_cnt = pd_src_pdo_cnt; +#endif + uint16_t header; + + if (src_pdo_cnt == 0) + /* No source capabilities defined, sink only */ + header = PD_HEADER(PD_CTRL_REJECT, pd[port].power_role, + pd[port].data_role, pd[port].msg_id, 0, + pd_get_rev(port), 0); + else + header = PD_HEADER(PD_DATA_SOURCE_CAP, pd[port].power_role, + pd[port].data_role, pd[port].msg_id, src_pdo_cnt, + pd_get_rev(port), 0); + + bit_len = pd_transmit(port, TCPC_TX_SOP, header, src_pdo); + if (debug_level >= 2) + CPRINTF("srcCAP>%d\n", bit_len); + + return bit_len; +} + +#ifdef CONFIG_USB_PD_REV30 +static int send_battery_cap(int port, uint32_t *payload) +{ + int bit_len; + uint16_t msg[6] = {0, 0, 0, 0, 0, 0}; + uint16_t header = PD_HEADER(PD_EXT_BATTERY_CAP, + pd[port].power_role, + pd[port].data_role, + pd[port].msg_id, + 3, /* Number of Data Objects */ + pd[port].rev, + 1 /* This is an exteded message */ + ); + + /* Set extended header */ + msg[0] = PD_EXT_HEADER(0, /* Chunk Number */ + 0, /* Request Chunk */ + 9 /* Data Size in bytes */ + ); + /* Set VID */ + msg[1] = USB_VID_GOOGLE; + + /* Set PID */ + msg[2] = CONFIG_USB_PID; + + if (battery_is_present()) { + /* + * We only have one fixed battery, + * so make sure batt cap ref is 0. + */ + if (BATT_CAP_REF(payload[0]) != 0) { + /* Invalid battery reference */ + msg[5] = 1; + } else { + uint32_t v; + uint32_t c; + + /* + * The Battery Design Capacity field shall return the + * Battery’s design capacity in tenths of Wh. If the + * Battery is Hot Swappable and is not present, the + * Battery Design Capacity field shall be set to 0. If + * the Battery is unable to report its Design Capacity, + * it shall return 0xFFFF + */ + msg[3] = 0xffff; + + /* + * The Battery Last Full Charge Capacity field shall + * return the Battery’s last full charge capacity in + * tenths of Wh. If the Battery is Hot Swappable and + * is not present, the Battery Last Full Charge Capacity + * field shall be set to 0. If the Battery is unable to + * report its Design Capacity, the Battery Last Full + * Charge Capacity field shall be set to 0xFFFF. + */ + msg[4] = 0xffff; + + if (battery_design_voltage(&v) == 0) { + if (battery_design_capacity(&c) == 0) { + /* + * Wh = (c * v) / 1000000 + * 10th of a Wh = Wh * 10 + */ + msg[3] = DIV_ROUND_NEAREST((c * v), + 100000); + } + + if (battery_full_charge_capacity(&c) == 0) { + /* + * Wh = (c * v) / 1000000 + * 10th of a Wh = Wh * 10 + */ + msg[4] = DIV_ROUND_NEAREST((c * v), + 100000); + } + } + } + } + + bit_len = pd_transmit(port, TCPC_TX_SOP, header, (uint32_t *)msg); + if (debug_level >= 2) + CPRINTF("batCap>%d\n", bit_len); + return bit_len; +} + +static int send_battery_status(int port, uint32_t *payload) +{ + int bit_len; + uint32_t msg = 0; + uint16_t header = PD_HEADER(PD_DATA_BATTERY_STATUS, + pd[port].power_role, + pd[port].data_role, + pd[port].msg_id, + 1, /* Number of Data Objects */ + pd[port].rev, + 0 /* This is NOT an extended message */ + ); + + if (battery_is_present()) { + /* + * We only have one fixed battery, + * so make sure batt cap ref is 0. + */ + if (BATT_CAP_REF(payload[0]) != 0) { + /* Invalid battery reference */ + msg |= BSDO_INVALID; + } else { + uint32_t v; + uint32_t c; + + if (battery_design_voltage(&v) != 0 || + battery_remaining_capacity(&c) != 0) { + msg |= BSDO_CAP(BSDO_CAP_UNKNOWN); + } else { + /* + * Wh = (c * v) / 1000000 + * 10th of a Wh = Wh * 10 + */ + msg |= BSDO_CAP(DIV_ROUND_NEAREST((c * v), + 100000)); + } + + /* Battery is present */ + msg |= BSDO_PRESENT; + + /* + * For drivers that are not smart battery compliant, + * battery_status() returns EC_ERROR_UNIMPLEMENTED and + * the battery is assumed to be idle. + */ + if (battery_status(&c) != 0) { + msg |= BSDO_IDLE; /* assume idle */ + } else { + if (c & STATUS_FULLY_CHARGED) + /* Fully charged */ + msg |= BSDO_IDLE; + else if (c & STATUS_DISCHARGING) + /* Discharging */ + msg |= BSDO_DISCHARGING; + /* else battery is charging.*/ + } + } + } else { + msg = BSDO_CAP(BSDO_CAP_UNKNOWN); + } + + bit_len = pd_transmit(port, TCPC_TX_SOP, header, &msg); + if (debug_level >= 2) + CPRINTF("batStat>%d\n", bit_len); + + return bit_len; +} +#endif + +#ifdef CONFIG_USB_PD_DUAL_ROLE +static void send_sink_cap(int port) +{ + int bit_len; + uint16_t header = PD_HEADER(PD_DATA_SINK_CAP, pd[port].power_role, + pd[port].data_role, pd[port].msg_id, pd_snk_pdo_cnt, + pd_get_rev(port), 0); + + bit_len = pd_transmit(port, TCPC_TX_SOP, header, pd_snk_pdo); + if (debug_level >= 2) + CPRINTF("snkCAP>%d\n", bit_len); +} + +static int send_request(int port, uint32_t rdo) +{ + int bit_len; + uint16_t header = PD_HEADER(PD_DATA_REQUEST, pd[port].power_role, + pd[port].data_role, pd[port].msg_id, 1, + pd_get_rev(port), 0); + + bit_len = pd_transmit(port, TCPC_TX_SOP, header, &rdo); + if (debug_level >= 2) + CPRINTF("REQ%d>\n", bit_len); + + return bit_len; +} +#ifdef CONFIG_BBRAM +static int pd_get_saved_active(int port) +{ + uint8_t val; + + if (system_get_bbram(port ? SYSTEM_BBRAM_IDX_PD1 : + SYSTEM_BBRAM_IDX_PD0, &val)) { + CPRINTS("PD NVRAM FAIL"); + return 0; + } + return !!val; +} + +static void pd_set_saved_active(int port, int val) +{ + if (system_set_bbram(port ? SYSTEM_BBRAM_IDX_PD1 : + SYSTEM_BBRAM_IDX_PD0, val)) + CPRINTS("PD NVRAM FAIL"); +} +#endif // CONFIG_BBRAM +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + +#ifdef CONFIG_COMMON_RUNTIME +static int send_bist_cmd(int port) +{ + /* currently only support sending bist carrier 2 */ + uint32_t bdo = BDO(BDO_MODE_CARRIER2, 0); + int bit_len; + uint16_t header = PD_HEADER(PD_DATA_BIST, pd[port].power_role, + pd[port].data_role, pd[port].msg_id, 1, + pd_get_rev(port), 0); + + bit_len = pd_transmit(port, TCPC_TX_SOP, header, &bdo); + CPRINTF("BIST>%d\n", bit_len); + + return bit_len; +} +#endif + +static void queue_vdm(int port, uint32_t *header, const uint32_t *data, + int data_cnt) +{ + pd[port].vdo_count = data_cnt + 1; + pd[port].vdo_data[0] = header[0]; + memcpy(&pd[port].vdo_data[1], data, sizeof(uint32_t) * data_cnt); + /* Set ready, pd task will actually send */ + pd[port].vdm_state = VDM_STATE_READY; +} + +static void handle_vdm_request(int port, int cnt, uint32_t *payload) +{ + int rlen = 0; + uint32_t *rdata; + + if (pd[port].vdm_state == VDM_STATE_BUSY) { + /* If UFP responded busy retry after timeout */ + if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_BUSY) { + pd[port].vdm_timeout.val = get_time().val + + PD_T_VDM_BUSY; + pd[port].vdm_state = VDM_STATE_WAIT_RSP_BUSY; + pd[port].vdo_retry = (payload[0] & ~VDO_CMDT_MASK) | + CMDT_INIT; + return; + } else { + pd[port].vdm_state = VDM_STATE_DONE; + } + } + + if (PD_VDO_SVDM(payload[0])) + rlen = pd_svdm(port, cnt, payload, &rdata); + else + rlen = pd_custom_vdm(port, cnt, payload, &rdata); + + if (rlen > 0) { + queue_vdm(port, rdata, &rdata[1], rlen - 1); + return; + } + if (debug_level >= 2) + CPRINTF("Unhandled VDM VID %04x CMD %04x\n", + PD_VDO_VID(payload[0]), payload[0] & 0xFFFF); +} + +void pd_execute_hard_reset(int port) +{ + if (pd[port].last_state == PD_STATE_HARD_RESET_SEND) + CPRINTF("C%d HARD RST TX\n", port); + else + CPRINTF("C%d HARD RST RX\n", port); + + pd[port].msg_id = 0; +#ifdef CONFIG_USB_PD_ALT_MODE_DFP + pd_dfp_exit_mode(port, 0, 0); +#endif + +#ifdef CONFIG_USB_PD_REV30 + pd[port].rev = PD_REV30; + pd_ca_reset(port); +#endif + /* + * Fake set last state to hard reset to make sure that the next + * state to run knows that we just did a hard reset. + */ + pd[port].last_state = PD_STATE_HARD_RESET_EXECUTE; + +#ifdef CONFIG_USB_PD_DUAL_ROLE + /* + * If we are swapping to a source and have changed to Rp, restore back + * to Rd and turn off vbus to match our power_role. + */ + if (pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY || + pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE) { + tcpm_set_cc(port, TYPEC_CC_RD); + pd_power_supply_reset(port); + } + + if (pd[port].power_role == PD_ROLE_SINK) { + /* Clear the input current limit */ + pd_set_input_current_limit(port, 0, 0); +#ifdef CONFIG_CHARGE_MANAGER + //charge_manager_set_ceil(port, + // CEIL_REQUESTOR_PD, + // CHARGE_CEIL_NONE); +#endif /* CONFIG_CHARGE_MANAGER */ + + set_state(port, PD_STATE_SNK_HARD_RESET_RECOVER); + return; + } +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + + /* We are a source, cut power */ + pd_power_supply_reset(port); + pd[port].src_recover = get_time().val + PD_T_SRC_RECOVER; + set_state(port, PD_STATE_SRC_HARD_RESET_RECOVER); +} + +static void execute_soft_reset(int port) +{ + pd[port].msg_id = 0; + set_state(port, DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_DISCOVERY, + PD_STATE_SRC_DISCOVERY)); + CPRINTF("C%d Soft Rst\n", port); +} + +void pd_soft_reset(void) +{ + int i; + + for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; ++i) + if (pd_is_connected(i)) { + set_state(i, PD_STATE_SOFT_RESET); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(i)); + } +} + +#ifdef CONFIG_USB_PD_DUAL_ROLE +/* + * Request desired charge voltage from source. + * Returns EC_SUCCESS on success or non-zero on failure. + */ +static int pd_send_request_msg(int port, int always_send_request) +{ + uint32_t rdo, curr_limit, supply_voltage; + int res; + +#ifdef CONFIG_CHARGE_MANAGER + //int charging = (charge_manager_get_active_charge_port() == port); + const int charging = 1; +#else + const int charging = 1; +#endif + +#ifdef CONFIG_USB_PD_CHECK_MAX_REQUEST_ALLOWED + int max_request_allowed = pd_is_max_request_allowed(); +#else + const int max_request_allowed = 1; +#endif + + /* Clear new power request */ + pd[port].new_power_request = 0; + + /* Build and send request RDO */ + /* + * If this port is not actively charging or we are not allowed to + * request the max voltage, then select vSafe5V + */ + res = pd_build_request(port, &rdo, &curr_limit, &supply_voltage, + charging && max_request_allowed ? + PD_REQUEST_MAX : PD_REQUEST_VSAFE5V); + + if (res != EC_SUCCESS) + /* + * If fail to choose voltage, do nothing, let source re-send + * source cap + */ + return -1; + + if (!always_send_request) { + /* Don't re-request the same voltage */ + if (pd[port].prev_request_mv == supply_voltage) + return EC_SUCCESS; +#ifdef CONFIG_CHARGE_MANAGER + /* Limit current to PD_MIN_MA during transition */ + //else + // charge_manager_force_ceil(port, PD_MIN_MA); +#endif + } + + CPRINTF("Req C%d [%d] %dmV %dmA", port, RDO_POS(rdo), + supply_voltage, curr_limit); + if (rdo & RDO_CAP_MISMATCH) + CPRINTF(" Mismatch"); + CPRINTF("\n"); + + pd[port].curr_limit = curr_limit; + pd[port].supply_voltage = supply_voltage; + pd[port].prev_request_mv = supply_voltage; + res = send_request(port, rdo); + if (res < 0) + return res; + set_state(port, PD_STATE_SNK_REQUESTED); + return EC_SUCCESS; +} +#endif + +static void pd_update_pdo_flags(int port, uint32_t pdo) +{ +#ifdef CONFIG_CHARGE_MANAGER +#ifdef CONFIG_USB_PD_ALT_MODE_DFP + int charge_whitelisted = + (pd[port].power_role == PD_ROLE_SINK && + pd_charge_from_device(pd_get_identity_vid(port), + pd_get_identity_pid(port))); +#else + const int charge_whitelisted = 0; +#endif +#endif + + /* can only parse PDO flags if type is fixed */ + if ((pdo & PDO_TYPE_MASK) != PDO_TYPE_FIXED) + return; + +#ifdef CONFIG_USB_PD_DUAL_ROLE + if (pdo & PDO_FIXED_DUAL_ROLE) + pd[port].flags |= PD_FLAGS_PARTNER_DR_POWER; + else + pd[port].flags &= ~PD_FLAGS_PARTNER_DR_POWER; + + if (pdo & PDO_FIXED_EXTERNAL) + pd[port].flags |= PD_FLAGS_PARTNER_EXTPOWER; + else + pd[port].flags &= ~PD_FLAGS_PARTNER_EXTPOWER; + + if (pdo & PDO_FIXED_COMM_CAP) + pd[port].flags |= PD_FLAGS_PARTNER_USB_COMM; + else + pd[port].flags &= ~PD_FLAGS_PARTNER_USB_COMM; +#endif + + if (pdo & PDO_FIXED_DATA_SWAP) + pd[port].flags |= PD_FLAGS_PARTNER_DR_DATA; + else + pd[port].flags &= ~PD_FLAGS_PARTNER_DR_DATA; + +#ifdef CONFIG_CHARGE_MANAGER + /* + * Treat device as a dedicated charger (meaning we should charge + * from it) if it does not support power swap, or if it is externally + * powered, or if we are a sink and the device identity matches a + * charging white-list. + */ + /* + if (!(pd[port].flags & PD_FLAGS_PARTNER_DR_POWER) || + (pd[port].flags & PD_FLAGS_PARTNER_EXTPOWER) || + charge_whitelisted) + charge_manager_update_dualrole(port, CAP_DEDICATED); + else + charge_manager_update_dualrole(port, CAP_DUALROLE); + */ +#endif +} + +static void handle_data_request(int port, uint16_t head, + uint32_t *payload) +{ + int type = PD_HEADER_TYPE(head); + int cnt = PD_HEADER_CNT(head); + + switch (type) { +#ifdef CONFIG_USB_PD_DUAL_ROLE + case PD_DATA_SOURCE_CAP: + if ((pd[port].task_state == PD_STATE_SNK_DISCOVERY) + || (pd[port].task_state == PD_STATE_SNK_TRANSITION) +#ifdef CONFIG_USB_PD_VBUS_DETECT_NONE + || (pd[port].task_state == + PD_STATE_SNK_HARD_RESET_RECOVER) +#endif + || (pd[port].task_state == PD_STATE_SNK_READY)) { +#ifdef CONFIG_USB_PD_REV30 + /* + * Only adjust sink rev if source rev is higher. + */ + if (PD_HEADER_REV(head) < pd[port].rev) + pd[port].rev = PD_HEADER_REV(head); +#endif + /* Port partner is now known to be PD capable */ + pd[port].flags |= PD_FLAGS_PREVIOUS_PD_CONN; + + /* src cap 0 should be fixed PDO */ + pd_update_pdo_flags(port, payload[0]); + + pd_process_source_cap(port, cnt, payload); + + /* Source will resend source cap on failure */ + pd_send_request_msg(port, 1); + + // We call the callback after we send the request + // because the timing on Request seems to be sensitive + // User code can take the time until PS_RDY to do stuff + pd_process_source_cap_callback(port, cnt, payload); + } + break; +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + case PD_DATA_REQUEST: + if ((pd[port].power_role == PD_ROLE_SOURCE) && (cnt == 1)) { +#ifdef CONFIG_USB_PD_REV30 + /* + * Adjust the rev level to what the sink supports. If + * they're equal, no harm done. + */ + pd[port].rev = PD_HEADER_REV(head); +#endif + if (!pd_check_requested_voltage(payload[0], port)) { + if (send_control(port, PD_CTRL_ACCEPT) < 0) + /* + * if we fail to send accept, do + * nothing and let sink timeout and + * send hard reset + */ + return; + + /* explicit contract is now in place */ + pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT; +#ifdef CONFIG_USB_PD_REV30 + /* + * Start Source-coordinated collision + * avoidance + */ + if (pd[port].rev == PD_REV30 && + pd[port].power_role == PD_ROLE_SOURCE) + sink_can_xmit(port, SINK_TX_OK); +#endif +#ifdef CONFIG_USB_PD_DUAL_ROLE +#ifdef CONFIG_BBRAM + pd_set_saved_active(port, 1); +#endif +#endif + pd[port].requested_idx = RDO_POS(payload[0]); + set_state(port, PD_STATE_SRC_ACCEPTED); + return; + } + } + /* the message was incorrect or cannot be satisfied */ + send_control(port, PD_CTRL_REJECT); + /* keep last contract in place (whether implicit or explicit) */ + set_state(port, PD_STATE_SRC_READY); + break; + case PD_DATA_BIST: + /* If not in READY state, then don't start BIST */ + if (DUAL_ROLE_IF_ELSE(port, + pd[port].task_state == PD_STATE_SNK_READY, + pd[port].task_state == PD_STATE_SRC_READY)) { + /* currently only support sending bist carrier mode 2 */ + if ((payload[0] >> 28) == 5) { + /* bist data object mode is 2 */ + pd_transmit(port, TCPC_TX_BIST_MODE_2, 0, + NULL); + /* Set to appropriate port disconnected state */ + set_state(port, DUAL_ROLE_IF_ELSE(port, + PD_STATE_SNK_DISCONNECTED, + PD_STATE_SRC_DISCONNECTED)); + } + } + break; + case PD_DATA_SINK_CAP: + pd[port].flags |= PD_FLAGS_SNK_CAP_RECVD; + /* snk cap 0 should be fixed PDO */ + pd_update_pdo_flags(port, payload[0]); + if (pd[port].task_state == PD_STATE_SRC_GET_SINK_CAP) + set_state(port, PD_STATE_SRC_READY); + break; +#ifdef CONFIG_USB_PD_REV30 + case PD_DATA_BATTERY_STATUS: + break; +#endif + case PD_DATA_VENDOR_DEF: + handle_vdm_request(port, cnt, payload); + break; + default: + CPRINTF("Unhandled data message type %d\n", type); + } +} + +#ifdef CONFIG_USB_PD_DUAL_ROLE +void pd_request_power_swap(int port) +{ + if (pd[port].task_state == PD_STATE_SRC_READY) + set_state(port, PD_STATE_SRC_SWAP_INIT); + else if (pd[port].task_state == PD_STATE_SNK_READY) + set_state(port, PD_STATE_SNK_SWAP_INIT); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); +} + +#ifdef CONFIG_USBC_VCONN_SWAP +static void pd_request_vconn_swap(int port) +{ + if (pd[port].task_state == PD_STATE_SRC_READY || + pd[port].task_state == PD_STATE_SNK_READY) + set_state(port, PD_STATE_VCONN_SWAP_SEND); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); +} + +void pd_try_vconn_src(int port) +{ + /* + * If we don't currently provide vconn, and we can supply it, send + * a vconn swap request. + */ + if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) { + if (pd_check_vconn_swap(port)) + pd_request_vconn_swap(port); + } +} +#endif +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + +void pd_request_data_swap(int port) +{ + if (DUAL_ROLE_IF_ELSE(port, + pd[port].task_state == PD_STATE_SNK_READY, + pd[port].task_state == PD_STATE_SRC_READY)) + set_state(port, PD_STATE_DR_SWAP); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); +} + +static void pd_set_data_role(int port, int role) +{ + pd[port].data_role = role; + pd_execute_data_swap(port, role); + +#ifdef CONFIG_USBC_SS_MUX +#ifdef CONFIG_USBC_SS_MUX_DFP_ONLY + /* + * Need to connect SS mux for if new data role is DFP. + * If new data role is UFP, then disconnect the SS mux. + */ + if (role == PD_ROLE_DFP) + usb_mux_set(port, TYPEC_MUX_USB, USB_SWITCH_CONNECT, + pd[port].polarity); + else + usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, + pd[port].polarity); +#else + usb_mux_set(port, TYPEC_MUX_USB, USB_SWITCH_CONNECT, + pd[port].polarity); +#endif +#endif + pd_update_roles(port); +} + +static void pd_dr_swap(int port) +{ + pd_set_data_role(port, !pd[port].data_role); + pd[port].flags |= PD_FLAGS_CHECK_IDENTITY; +} + +static void handle_ctrl_request(int port, uint16_t head, + uint32_t *payload) +{ + int type = PD_HEADER_TYPE(head); + int res; + + switch (type) { + case PD_CTRL_GOOD_CRC: + /* should not get it */ + break; + case PD_CTRL_PING: + /* Nothing else to do */ + break; + case PD_CTRL_GET_SOURCE_CAP: + res = send_source_cap(port); + if ((res >= 0) && + (pd[port].task_state == PD_STATE_SRC_DISCOVERY)) + set_state(port, PD_STATE_SRC_NEGOCIATE); + break; + case PD_CTRL_GET_SINK_CAP: +#ifdef CONFIG_USB_PD_DUAL_ROLE + send_sink_cap(port); +#else + send_control(port, REFUSE(pd[port].rev)); +#endif + break; +#ifdef CONFIG_USB_PD_DUAL_ROLE + case PD_CTRL_GOTO_MIN: +#ifdef CONFIG_USB_PD_GIVE_BACK + if (pd[port].task_state == PD_STATE_SNK_READY) { + /* + * Reduce power consumption now! + * + * The source will restore power to this sink + * by sending a new source cap message at a + * later time. + */ + pd_snk_give_back(port, &pd[port].curr_limit, + &pd[port].supply_voltage); + set_state(port, PD_STATE_SNK_TRANSITION); + } +#endif + + break; + case PD_CTRL_PS_RDY: + if (pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE) { + set_state(port, PD_STATE_SNK_SWAP_STANDBY); + } else if (pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY) { + /* reset message ID and swap roles */ + pd[port].msg_id = 0; + pd[port].power_role = PD_ROLE_SINK; + pd_update_roles(port); + set_state(port, PD_STATE_SNK_DISCOVERY); +#ifdef CONFIG_USBC_VCONN_SWAP + } else if (pd[port].task_state == PD_STATE_VCONN_SWAP_INIT) { + /* + * If VCONN is on, then this PS_RDY tells us it's + * ok to turn VCONN off + */ + if (pd[port].flags & PD_FLAGS_VCONN_ON) + set_state(port, PD_STATE_VCONN_SWAP_READY); +#endif + } else if (pd[port].task_state == PD_STATE_SNK_DISCOVERY) { + /* Don't know what power source is ready. Reset. */ + set_state(port, PD_STATE_HARD_RESET_SEND); + } else if (pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY) { + /* Do nothing, assume this is a redundant PD_RDY */ + } else if (pd[port].power_role == PD_ROLE_SINK) { + set_state(port, PD_STATE_SNK_READY); + pd_set_input_current_limit(port, pd[port].curr_limit, + pd[port].supply_voltage); +#ifdef CONFIG_CHARGE_MANAGER + /* Set ceiling based on what's negotiated */ + //charge_manager_set_ceil(port, + // CEIL_REQUESTOR_PD, + // pd[port].curr_limit); +#endif + } + break; +#endif + case PD_CTRL_REJECT: + case PD_CTRL_WAIT: + if (pd[port].task_state == PD_STATE_DR_SWAP) + set_state(port, READY_RETURN_STATE(port)); +#ifdef CONFIG_USBC_VCONN_SWAP + else if (pd[port].task_state == PD_STATE_VCONN_SWAP_SEND) + set_state(port, READY_RETURN_STATE(port)); +#endif +#ifdef CONFIG_USB_PD_DUAL_ROLE + else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT) + set_state(port, PD_STATE_SRC_READY); + else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT) + set_state(port, PD_STATE_SNK_READY); + else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) { + /* + * Explicit Contract in place + * + * On reception of a WAIT message, transition to + * PD_STATE_SNK_READY after PD_T_SINK_REQUEST ms to + * send another reqest. + * + * On reception of a REJECT messag, transition to + * PD_STATE_SNK_READY but don't resend the request. + * + * NO Explicit Contract in place + * + * On reception of a WAIT or REJECT message, + * transition to PD_STATE_SNK_DISCOVERY + */ + if (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT) { + /* We have an explicit contract */ + if (type == PD_CTRL_WAIT) { + /* + * Trigger a new power request when + * we enter PD_STATE_SNK_READY + */ + pd[port].new_power_request = 1; + + /* + * After the request is triggered, + * make sure the request is sent. + */ + pd[port].prev_request_mv = 0; + + /* + * Transition to PD_STATE_SNK_READY + * after PD_T_SINK_REQUEST ms. + */ + set_state_timeout(port, get_time().val + + PD_T_SINK_REQUEST, + PD_STATE_SNK_READY); + } else { + /* The request was rejected */ + set_state(port, PD_STATE_SNK_READY); + } + } else { + /* No explicit contract */ + set_state(port, PD_STATE_SNK_DISCOVERY); + } + } +#endif + break; + case PD_CTRL_ACCEPT: + if (pd[port].task_state == PD_STATE_SOFT_RESET) { + /* + * For the case that we sent soft reset in SNK_DISCOVERY + * on startup due to VBUS never low, clear the flag. + */ + pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW; + execute_soft_reset(port); + } else if (pd[port].task_state == PD_STATE_DR_SWAP) { + /* switch data role */ + pd_dr_swap(port); + set_state(port, READY_RETURN_STATE(port)); +#ifdef CONFIG_USB_PD_DUAL_ROLE +#ifdef CONFIG_USBC_VCONN_SWAP + } else if (pd[port].task_state == PD_STATE_VCONN_SWAP_SEND) { + /* switch vconn */ + set_state(port, PD_STATE_VCONN_SWAP_INIT); +#endif + } else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT) { + /* explicit contract goes away for power swap */ + pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT; + set_state(port, PD_STATE_SRC_SWAP_SNK_DISABLE); + } else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT) { + /* explicit contract goes away for power swap */ + pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT; + set_state(port, PD_STATE_SNK_SWAP_SNK_DISABLE); + } else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) { + /* explicit contract is now in place */ + pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT; +#ifdef CONFIG_BBRAM + pd_set_saved_active(port, 1); +#endif + set_state(port, PD_STATE_SNK_TRANSITION); +#endif + } + break; + case PD_CTRL_SOFT_RESET: + execute_soft_reset(port); + /* We are done, acknowledge with an Accept packet */ + send_control(port, PD_CTRL_ACCEPT); + break; + case PD_CTRL_PR_SWAP: +#ifdef CONFIG_USB_PD_DUAL_ROLE + if (pd_check_power_swap(port)) { + send_control(port, PD_CTRL_ACCEPT); + /* + * Clear flag for checking power role to avoid + * immediately requesting another swap. + */ + pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE; + set_state(port, + DUAL_ROLE_IF_ELSE(port, + PD_STATE_SNK_SWAP_SNK_DISABLE, + PD_STATE_SRC_SWAP_SNK_DISABLE)); + } else { + send_control(port, REFUSE(pd[port].rev)); + } +#else + send_control(port, REFUSE(pd[port].rev)); +#endif + break; + case PD_CTRL_DR_SWAP: + if (pd_check_data_swap(port, pd[port].data_role)) { + /* + * Accept switch and perform data swap. Clear + * flag for checking data role to avoid + * immediately requesting another swap. + */ + pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE; + if (send_control(port, PD_CTRL_ACCEPT) >= 0) + pd_dr_swap(port); + } else { + send_control(port, REFUSE(pd[port].rev)); + + } + break; + case PD_CTRL_VCONN_SWAP: +#ifdef CONFIG_USBC_VCONN_SWAP + if (pd[port].task_state == PD_STATE_SRC_READY || + pd[port].task_state == PD_STATE_SNK_READY) { + if (pd_check_vconn_swap(port)) { + if (send_control(port, PD_CTRL_ACCEPT) > 0) + set_state(port, + PD_STATE_VCONN_SWAP_INIT); + } else { + send_control(port, REFUSE(pd[port].rev)); + } + } +#else + send_control(port, REFUSE(pd[port].rev)); +#endif + break; + default: +#ifdef CONFIG_USB_PD_REV30 + send_control(port, PD_CTRL_NOT_SUPPORTED); +#endif + CPRINTF("Unhandled ctrl message type %d\n", type); + } +} + +#ifdef CONFIG_USB_PD_REV30 +static void handle_ext_request(int port, uint16_t head, uint32_t *payload) +{ + int type = PD_HEADER_TYPE(head); + + switch (type) { + case PD_EXT_GET_BATTERY_CAP: + send_battery_cap(port, payload); + break; + case PD_EXT_GET_BATTERY_STATUS: + send_battery_status(port, payload); + break; + case PD_EXT_BATTERY_CAP: + break; + default: + send_control(port, PD_CTRL_NOT_SUPPORTED); + } +} +#endif + +static void handle_request(int port, uint16_t head, + uint32_t *payload) +{ + int cnt = PD_HEADER_CNT(head); + int p; + + /* dump received packet content (only dump ping at debug level 3) */ + if ((debug_level == 2 && PD_HEADER_TYPE(head) != PD_CTRL_PING) || + debug_level >= 3) { + CPRINTF("RECV %04x/%d ", head, cnt); + for (p = 0; p < cnt; p++) + CPRINTF("[%d]%08x ", p, payload[p]); + CPRINTF("\n"); + } + + /* + * If we are in disconnected state, we shouldn't get a request. + * Ignore it if we get one. + */ + if (!pd_is_connected(port)) + return; + +#ifdef CONFIG_USB_PD_REV30 + /* Check if this is an extended chunked data message. */ + if (pd[port].rev == PD_REV30 && PD_HEADER_EXT(head)) { + handle_ext_request(port, head, payload); + return; + } +#endif + if (cnt) + handle_data_request(port, head, payload); + else + handle_ctrl_request(port, head, payload); +} + +void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data, + int count) +{ + if (count > VDO_MAX_SIZE - 1) { + CPRINTF("VDM over max size\n"); + return; + } + + /* set VDM header with VID & CMD */ + pd[port].vdo_data[0] = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ? + 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), cmd); +#ifdef CONFIG_USB_PD_REV30 + pd[port].vdo_data[0] |= VDO_SVDM_VERS(vdo_ver[pd[port].rev]); +#endif + queue_vdm(port, pd[port].vdo_data, data, count); + + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); +} + +static inline int pdo_busy(int port) +{ + /* + * Note, main PDO state machine (pd_task) uses READY state exclusively + * to denote port partners have successfully negociated a contract. All + * other protocol actions force state transitions. + */ + int rv = (pd[port].task_state != PD_STATE_SRC_READY); +#ifdef CONFIG_USB_PD_DUAL_ROLE + rv &= (pd[port].task_state != PD_STATE_SNK_READY); +#endif + return rv; +} + +static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr) +{ + uint64_t timeout; + int cmd = PD_VDO_CMD(vdm_hdr); + + /* its not a structured VDM command */ + if (!PD_VDO_SVDM(vdm_hdr)) + return 500*MSEC; + + switch (PD_VDO_CMDT(vdm_hdr)) { + case CMDT_INIT: + if ((cmd == CMD_ENTER_MODE) || (cmd == CMD_EXIT_MODE)) + timeout = PD_T_VDM_WAIT_MODE_E; + else + timeout = PD_T_VDM_SNDR_RSP; + break; + default: + if ((cmd == CMD_ENTER_MODE) || (cmd == CMD_EXIT_MODE)) + timeout = PD_T_VDM_E_MODE; + else + timeout = PD_T_VDM_RCVR_RSP; + break; + } + return timeout; +} + +static void pd_vdm_send_state_machine(int port) +{ + int res; + uint16_t header; + + switch (pd[port].vdm_state) { + case VDM_STATE_READY: + /* Only transmit VDM if connected. */ + if (!pd_is_connected(port)) { + pd[port].vdm_state = VDM_STATE_ERR_BUSY; + break; + } + + /* + * if there's traffic or we're not in PDO ready state don't send + * a VDM. + */ + if (pdo_busy(port)) + break; + + /* Prepare and send VDM */ + header = PD_HEADER(PD_DATA_VENDOR_DEF, pd[port].power_role, + pd[port].data_role, pd[port].msg_id, + (int)pd[port].vdo_count, + pd_get_rev(port), 0); + res = pd_transmit(port, TCPC_TX_SOP, header, + pd[port].vdo_data); + if (res < 0) { + pd[port].vdm_state = VDM_STATE_ERR_SEND; + } else { + pd[port].vdm_state = VDM_STATE_BUSY; + pd[port].vdm_timeout.val = get_time().val + + vdm_get_ready_timeout(pd[port].vdo_data[0]); + } + break; + case VDM_STATE_WAIT_RSP_BUSY: + /* wait and then initiate request again */ + if (get_time().val > pd[port].vdm_timeout.val) { + pd[port].vdo_data[0] = pd[port].vdo_retry; + pd[port].vdo_count = 1; + pd[port].vdm_state = VDM_STATE_READY; + } + break; + case VDM_STATE_BUSY: + /* Wait for VDM response or timeout */ + if (pd[port].vdm_timeout.val && + (get_time().val > pd[port].vdm_timeout.val)) { + pd[port].vdm_state = VDM_STATE_ERR_TMOUT; + } + break; + default: + break; + } +} + +#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO +static inline void pd_dev_dump_info(uint16_t dev_id, uint8_t *hash) +{ + int j; + ccprintf("DevId:%d.%d Hash:", HW_DEV_ID_MAJ(dev_id), + HW_DEV_ID_MIN(dev_id)); + for (j = 0; j < PD_RW_HASH_SIZE; j += 4) { + ccprintf(" 0x%02x%02x%02x%02x", hash[j + 3], hash[j + 2], + hash[j + 1], hash[j]); + } + ccprintf("\n"); +} +#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */ + +int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash, + uint32_t current_image) +{ +#ifdef CONFIG_COMMON_RUNTIME + int i; +#endif + +#ifdef CONFIG_USB_PD_CHROMEOS + pd[port].dev_id = dev_id; + memcpy(pd[port].dev_rw_hash, rw_hash, PD_RW_HASH_SIZE); +#endif +#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO + if (debug_level >= 2) + pd_dev_dump_info(dev_id, (uint8_t *)rw_hash); +#endif +#ifdef CONFIG_USB_PD_CHROMEOS + pd[port].current_image = current_image; +#endif + +#ifdef CONFIG_COMMON_RUNTIME + /* Search table for matching device / hash */ + for (i = 0; i < RW_HASH_ENTRIES; i++) + if (dev_id == rw_hash_table[i].dev_id) + return !memcmp(rw_hash, + rw_hash_table[i].dev_rw_hash, + PD_RW_HASH_SIZE); +#endif + return 0; +} + +#ifdef CONFIG_USB_PD_DUAL_ROLE +enum pd_dual_role_states pd_get_dual_role(void) +{ + return drp_state; +} + +#ifdef CONFIG_USB_PD_TRY_SRC +static void pd_update_try_source(void) +{ + int i; + +#ifndef CONFIG_CHARGER + int batt_soc = board_get_battery_soc(); +#else + int batt_soc = charge_get_percent(); +#endif + + /* + * Enable try source when dual-role toggling AND battery is present + * and at some minimum percentage. + */ + pd_try_src_enable = drp_state == PD_DRP_TOGGLE_ON && + batt_soc >= CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC; +#if defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \ + defined(CONFIG_BATTERY_PRESENT_GPIO) + /* + * When battery is cutoff in ship mode it may not be reliable to + * check if battery is present with its state of charge. + * Also check if battery is initialized and ready to provide power. + */ + pd_try_src_enable &= (battery_is_present() == BP_YES); +#endif + + /* + * Clear this flag to cover case where a TrySrc + * mode went from enabled to disabled and trying_source + * was active at that time. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) + pd[i].flags &= ~PD_FLAGS_TRY_SRC; + +} +DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pd_update_try_source, HOOK_PRIO_DEFAULT); +#endif + +void pd_set_dual_role(enum pd_dual_role_states state) +{ + int i; + drp_state = state; + +#ifdef CONFIG_USB_PD_TRY_SRC + pd_update_try_source(); +#endif + + /* Inform PD tasks of dual role change. */ + for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) + // getting rid of task stuff + //task_set_event(PD_PORT_TO_TASK_ID(i), + // PD_EVENT_UPDATE_DUAL_ROLE, 0); + ; +} + +void pd_update_dual_role_config(int port) +{ + /* + * Change to sink if port is currently a source AND (new DRP + * state is force sink OR new DRP state is either toggle off + * or debug accessory toggle only and we are in the source + * disconnected state). + */ + if (pd[port].power_role == PD_ROLE_SOURCE && + ((drp_state == PD_DRP_FORCE_SINK && !pd_ts_dts_plugged(port)) || + (drp_state == PD_DRP_TOGGLE_OFF + && pd[port].task_state == PD_STATE_SRC_DISCONNECTED))) { + pd[port].power_role = PD_ROLE_SINK; + set_state(port, PD_STATE_SNK_DISCONNECTED); + tcpm_set_cc(port, TYPEC_CC_RD); + /* Make sure we're not sourcing VBUS. */ + pd_power_supply_reset(port); + } + + /* + * Change to source if port is currently a sink and the + * new DRP state is force source. + */ + if (pd[port].power_role == PD_ROLE_SINK && + drp_state == PD_DRP_FORCE_SOURCE) { + pd[port].power_role = PD_ROLE_SOURCE; + set_state(port, PD_STATE_SRC_DISCONNECTED); + tcpm_set_cc(port, TYPEC_CC_RP); + } + +#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \ + defined(CONFIG_USB_PD_TCPC_LOW_POWER) + /* When switching drp mode, make sure tcpc is out of standby mode */ + tcpm_set_drp_toggle(port, 0); +#endif +} + +int pd_get_role(int port) +{ + return pd[port].power_role; +} + +static int pd_is_power_swapping(int port) +{ + /* return true if in the act of swapping power roles */ + return pd[port].task_state == PD_STATE_SNK_SWAP_SNK_DISABLE || + pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE || + pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY || + pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE || + pd[port].task_state == PD_STATE_SRC_SWAP_SNK_DISABLE || + pd[port].task_state == PD_STATE_SRC_SWAP_SRC_DISABLE || + pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY; +} + +/* + * Provide Rp to ensure the partner port is in a known state (eg. not + * PD negotiated, not sourcing 20V). + */ +static void pd_partner_port_reset(int port) +{ + uint64_t timeout; + +#ifdef CONFIG_BBRAM + /* + * Check our battery-backed previous port state. If PD comms were + * active, and we didn't just lose power, make sure we + * don't boot into RO with a pre-existing power contract. + */ + if (!pd_get_saved_active(port) || + system_get_image_copy() != SYSTEM_IMAGE_RO || + system_get_reset_flags() & + (RESET_FLAG_BROWNOUT | RESET_FLAG_POWER_ON)) + return; +#endif // CONFIG_BBRAM + /* Provide Rp for 100 msec. or until we no longer have VBUS. */ + tcpm_set_cc(port, TYPEC_CC_RP); + timeout = get_time().val + 100 * MSEC; + + while (get_time().val < timeout && pd_is_vbus_present(port)) + msleep(10); +#ifdef CONFIG_BBRAM + pd_set_saved_active(port, 0); +#endif +} +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + +int pd_get_polarity(int port) +{ + return pd[port].polarity; +} + +int pd_get_partner_data_swap_capable(int port) +{ + /* return data swap capable status of port partner */ + return pd[port].flags & PD_FLAGS_PARTNER_DR_DATA; +} + +#ifdef CONFIG_COMMON_RUNTIME +void pd_comm_enable(int port, int enable) +{ + /* We don't check port >= CONFIG_USB_PD_PORT_COUNT deliberately */ + pd_comm_enabled[port] = enable; + + /* If type-C connection, then update the TCPC RX enable */ + if (pd_is_connected(port)) + tcpm_set_rx_enable(port, enable); + +#ifdef CONFIG_USB_PD_DUAL_ROLE + /* + * If communications are enabled, start hard reset timer for + * any port in PD_SNK_DISCOVERY. + */ + if (enable && pd[port].task_state == PD_STATE_SNK_DISCOVERY) + set_state_timeout(port, + get_time().val + PD_T_SINK_WAIT_CAP, + PD_STATE_HARD_RESET_SEND); +#endif +} +#endif + +void pd_ping_enable(int port, int enable) +{ + if (enable) + pd[port].flags |= PD_FLAGS_PING_ENABLED; + else + pd[port].flags &= ~PD_FLAGS_PING_ENABLED; +} + +/** + * 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_SNK_DEF) || (cc == TYPEC_CC_VOLT_SNK_1_5) || + (cc == TYPEC_CC_VOLT_SNK_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 int get_snk_polarity(int cc1, int cc2) +{ + /* the following assumes: + * TYPEC_CC_VOLT_SNK_3_0 > TYPEC_CC_VOLT_SNK_1_5 + * TYPEC_CC_VOLT_SNK_1_5 > TYPEC_CC_VOLT_SNK_DEF + * TYPEC_CC_VOLT_SNK_DEF > TYPEC_CC_VOLT_OPEN + */ + return (cc2 > cc1); +} + +#if defined(CONFIG_CHARGE_MANAGER) +/** + * Returns type C current limit (mA) based upon cc_voltage (mV). + */ +static typec_current_t get_typec_current_limit(int polarity, int cc1, int cc2) +{ + typec_current_t charge; + int cc = polarity ? cc2 : cc1; + int cc_alt = polarity ? cc1 : cc2; + + if (cc == TYPEC_CC_VOLT_SNK_3_0 && cc_alt != TYPEC_CC_VOLT_SNK_1_5) + charge = 3000; + else if (cc == TYPEC_CC_VOLT_SNK_1_5) + charge = 1500; + else + charge = 0; + + if (cc_is_rp(cc_alt)) + charge |= TYPEC_CURRENT_DTS_MASK; + + return charge; +} + +/** + * Signal power request to indicate a charger update that affects the port. + */ +void pd_set_new_power_request(int port) +{ + pd[port].new_power_request = 1; + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); +} +#endif /* CONFIG_CHARGE_MANAGER */ + +#if defined(CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP) && defined(CONFIG_USBC_SS_MUX) +/* + * Backwards compatible DFP does not support USB SS because it applies VBUS + * before debouncing CC and setting USB SS muxes, but SS detection will fail + * before we are done debouncing CC. + */ +#error "Backwards compatible DFP does not support USB" +#endif + +#ifdef CONFIG_COMMON_RUNTIME + +/* Initialize globals based on system state. */ +static void pd_init_tasks(void) +{ + static int initialized; + int enable = 1; + int i; + + /* Initialize globals once, for all PD tasks. */ + if (initialized) + return; + +#if defined(HAS_TASK_CHIPSET) && defined(CONFIG_USB_PD_DUAL_ROLE) + /* Set dual-role state based on chipset power state */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + drp_state = PD_DRP_FORCE_SINK; + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + drp_state = PD_DRP_TOGGLE_OFF; + else /* CHIPSET_STATE_ON */ + drp_state = PD_DRP_TOGGLE_ON; +#endif + +#if defined(CONFIG_USB_PD_COMM_DISABLED) + enable = 0; +#elif defined(CONFIG_USB_PD_COMM_LOCKED) + /* Disable PD communication at init if we're in RO and locked. */ + if (!system_is_in_rw() && system_is_locked()) + enable = 0; +#endif + for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) + pd_comm_enabled[i] = enable; + CPRINTS("PD comm %sabled", enable ? "en" : "dis"); + + initialized = 1; +} +#endif /* CONFIG_COMMON_RUNTIME */ + +#ifndef CONFIG_USB_PD_TCPC +static int pd_restart_tcpc(int port) +{ + if (board_set_tcpc_power_mode) { + /* force chip reset */ + board_set_tcpc_power_mode(port, 0); + } + return tcpm_init(port); +} +#endif + +void pd_init(int port) +{ +#ifdef CONFIG_COMMON_RUNTIME + pd_init_tasks(); +#endif + + /* Ensure the power supply is in the default state */ + pd_power_supply_reset(port); + +#ifdef CONFIG_USB_PD_TCPC_BOARD_INIT + /* Board specific TCPC init */ + board_tcpc_init(); +#endif + + /* Initialize TCPM driver and wait for TCPC to be ready */ + res = tcpm_init(port); + +#ifdef CONFIG_USB_PD_DUAL_ROLE + //pd_partner_port_reset(port); +#endif + + CPRINTS("TCPC p%d init %s", port, res ? "failed" : "ready"); + this_state = res ? PD_STATE_SUSPENDED : PD_DEFAULT_STATE(port); +#ifndef CONFIG_USB_PD_TCPC + if (!res) { + struct ec_response_pd_chip_info *info; + tcpm_get_chip_info(port, 0, &info); + CPRINTS("TCPC p%d VID:0x%x PID:0x%x DID:0x%x FWV:0x%lx", + port, info->vendor_id, info->product_id, + info->device_id, info->fw_version_number); + } +#endif + +#ifdef CONFIG_USB_PD_REV30 + /* Set Revision to highest */ + pd[port].rev = PD_REV30; + pd_ca_reset(port); +#endif + +#ifdef CONFIG_USB_PD_DUAL_ROLE + /* + * If VBUS is high, then initialize flag for VBUS has always been + * present. This flag is used to maintain a PD connection after a + * reset by sending a soft reset. + */ + //pd[port].flags = pd_is_vbus_present(port) ? PD_FLAGS_VBUS_NEVER_LOW : 0; + pd[port].flags = 0; +#endif + + /* Disable TCPC RX until connection is established */ + tcpm_set_rx_enable(port, 0); + +#ifdef CONFIG_USBC_SS_MUX + /* Initialize USB mux to its default state */ + usb_mux_init(port); +#endif + + /* Initialize PD protocol state variables for each port. */ + pd[port].power_role = PD_ROLE_DEFAULT(port); + pd[port].vdm_state = VDM_STATE_DONE; + set_state(port, this_state); +#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT + ASSERT(PD_ROLE_DEFAULT(port) == PD_ROLE_SINK); + tcpm_select_rp_value(port, CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT); +#else + tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP); +#endif + tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE ? + TYPEC_CC_RP : TYPEC_CC_RD); + +#ifdef CONFIG_USB_PD_ALT_MODE_DFP + /* Initialize PD Policy engine */ + pd_dfp_pe_init(port); +#endif + +#ifdef CONFIG_CHARGE_MANAGER + /* Initialize PD and type-C supplier current limits to 0 */ + pd_set_input_current_limit(port, 0, 0); + //typec_set_input_current_limit(port, 0, 0); + //charge_manager_update_dualrole(port, CAP_UNKNOWN); +#endif +} + +void pd_run_state_machine(int port) +{ +#ifdef CONFIG_USB_PD_REV30 + /* send any pending messages */ + pd_ca_send_pending(port); +#endif + /* process VDM messages last */ + pd_vdm_send_state_machine(port); + + /* Verify board specific health status : current, voltages... */ + res = pd_board_checks(); + if (res != EC_SUCCESS) { + /* cut the power */ + pd_execute_hard_reset(port); + /* notify the other side of the issue */ + pd_transmit(port, TCPC_TX_HARD_RESET, 0, NULL); + } + + /* wait for next event/packet or timeout expiration */ + // getting rid of task stuff + //evt = task_wait_event(timeout); + +#ifdef CONFIG_USB_PD_DUAL_ROLE + if (evt & PD_EVENT_UPDATE_DUAL_ROLE) + pd_update_dual_role_config(port); +#endif + +#ifdef CONFIG_USB_PD_TCPC + /* + * run port controller task to check CC and/or read incoming + * messages + */ + tcpc_run(port, evt); +#else + /* if TCPC has reset, then need to initialize it again */ + if (evt & PD_EVENT_TCPC_RESET) { + CPRINTS("TCPC p%d reset!", port); + if (tcpm_init(port) != EC_SUCCESS) + CPRINTS("TCPC p%d init failed", port); +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE + } + + if ((evt & PD_EVENT_TCPC_RESET) && + (pd[port].task_state != PD_STATE_DRP_AUTO_TOGGLE)) { +#endif + /* Ensure CC termination is default */ + tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == + PD_ROLE_SOURCE ? TYPEC_CC_RP : TYPEC_CC_RD); + + /* + * If we have a stable contract in the default role, + * then simply update TCPC with some missing info + * so that we can continue without resetting PD comms. + * Otherwise, go to the default disconnected state + * and force renegotiation. + */ + if (pd[port].vdm_state == VDM_STATE_DONE && ( +#ifdef CONFIG_USB_PD_DUAL_ROLE + (PD_ROLE_DEFAULT(port) == PD_ROLE_SINK && + pd[port].task_state == PD_STATE_SNK_READY) || +#endif + (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE && + pd[port].task_state == PD_STATE_SRC_READY))) { + tcpm_set_polarity(port, pd[port].polarity); + tcpm_set_msg_header(port, pd[port].power_role, + pd[port].data_role); + tcpm_set_rx_enable(port, 1); + } else { + /* Ensure state variables are at default */ + pd[port].power_role = PD_ROLE_DEFAULT(port); + pd[port].vdm_state = VDM_STATE_DONE; + set_state(port, PD_DEFAULT_STATE(port)); + } + } +#endif + + /* process any potential incoming message */ + incoming_packet = evt & PD_EVENT_RX; + //if (incoming_packet) { + if (!tcpm_get_message(port, payload, &head)) + handle_request(port, head, payload); + //} + + if (pd[port].req_suspend_state) + set_state(port, PD_STATE_SUSPENDED); + + /* if nothing to do, verify the state of the world in 500ms */ + this_state = pd[port].task_state; + timeout = 500*MSEC; + switch (this_state) { + case PD_STATE_DISABLED: + /* Nothing to do */ + break; + case PD_STATE_SRC_DISCONNECTED: + timeout = 10*MSEC; + tcpm_get_cc(port, &cc1, &cc2); +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE + /* + * Attempt TCPC auto DRP toggle if it is + * not already auto toggling and not try.src + */ + if (auto_toggle_supported && + !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) && + !(pd[port].flags & PD_FLAGS_TRY_SRC) && + (cc1 == TYPEC_CC_VOLT_OPEN && + cc2 == TYPEC_CC_VOLT_OPEN)) { + set_state(port, PD_STATE_DRP_AUTO_TOGGLE); + timeout = 2*MSEC; + break; + } +#endif + + /* Vnc monitoring */ + if ((cc1 == TYPEC_CC_VOLT_RD || + cc2 == TYPEC_CC_VOLT_RD) || + (cc1 == TYPEC_CC_VOLT_RA && + cc2 == TYPEC_CC_VOLT_RA)) { +#ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP + /* Enable VBUS */ + if (pd_set_power_supply_ready(port)) + break; +#endif + pd[port].cc_state = PD_CC_NONE; + set_state(port, + PD_STATE_SRC_DISCONNECTED_DEBOUNCE); + } +#if defined(CONFIG_USB_PD_DUAL_ROLE) + /* + * Try.SRC state is embedded here. Wait for SNK + * detect, or if timer expires, transition to + * SNK_DISCONNETED. + * + * If Try.SRC state is not active, then this block + * handles the normal DRP toggle from SRC->SNK + */ + else if ((pd[port].flags & PD_FLAGS_TRY_SRC && + get_time().val >= pd[port].try_src_marker) || + (!(pd[port].flags & PD_FLAGS_TRY_SRC) && + drp_state != PD_DRP_FORCE_SOURCE && + drp_state != PD_DRP_FREEZE && + get_time().val >= next_role_swap)) { + pd[port].power_role = PD_ROLE_SINK; + set_state(port, PD_STATE_SNK_DISCONNECTED); + tcpm_set_cc(port, TYPEC_CC_RD); + next_role_swap = get_time().val + PD_T_DRP_SNK; + pd[port].try_src_marker = get_time().val + + PD_T_TRY_WAIT; + + /* Swap states quickly */ + timeout = 2*MSEC; + } +#endif + break; + case PD_STATE_SRC_DISCONNECTED_DEBOUNCE: + timeout = 20*MSEC; + tcpm_get_cc(port, &cc1, &cc2); + + if (cc1 == TYPEC_CC_VOLT_RD && + cc2 == TYPEC_CC_VOLT_RD) { + /* Debug accessory */ + new_cc_state = PD_CC_DEBUG_ACC; + } else if (cc1 == TYPEC_CC_VOLT_RD || + cc2 == TYPEC_CC_VOLT_RD) { + /* UFP attached */ + new_cc_state = PD_CC_UFP_ATTACHED; + } else if (cc1 == TYPEC_CC_VOLT_RA && + cc2 == TYPEC_CC_VOLT_RA) { + /* Audio accessory */ + new_cc_state = PD_CC_AUDIO_ACC; + } else { + /* No UFP */ + set_state(port, PD_STATE_SRC_DISCONNECTED); + timeout = 5*MSEC; + break; + } + /* If in Try.SRC state, then don't need to debounce */ + if (!(pd[port].flags & PD_FLAGS_TRY_SRC)) { + /* Debounce the cc state */ + if (new_cc_state != pd[port].cc_state) { + pd[port].cc_debounce = get_time().val + + PD_T_CC_DEBOUNCE; + pd[port].cc_state = new_cc_state; + break; + } else if (get_time().val < + pd[port].cc_debounce) { + break; + } + } + + /* Debounce complete */ + /* UFP is attached */ + if (new_cc_state == PD_CC_UFP_ATTACHED || + new_cc_state == PD_CC_DEBUG_ACC) { + pd[port].polarity = (cc1 != TYPEC_CC_VOLT_RD); + tcpm_set_polarity(port, pd[port].polarity); + + /* initial data role for source is DFP */ + pd_set_data_role(port, PD_ROLE_DFP); + + if (new_cc_state == PD_CC_DEBUG_ACC) + pd[port].flags |= + PD_FLAGS_TS_DTS_PARTNER; + +#ifndef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP + /* Enable VBUS */ + if (pd_set_power_supply_ready(port)) { +#ifdef CONFIG_USBC_SS_MUX + usb_mux_set(port, TYPEC_MUX_NONE, + USB_SWITCH_DISCONNECT, + pd[port].polarity); +#endif + break; + } +#endif + /* If PD comm is enabled, enable TCPC RX */ + if (pd_comm_is_enabled(port)) + tcpm_set_rx_enable(port, 1); + +#ifdef CONFIG_USBC_VCONN + tcpm_set_vconn(port, 1); + pd[port].flags |= PD_FLAGS_VCONN_ON; +#endif + + pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE | + PD_FLAGS_CHECK_DR_ROLE; + hard_reset_count = 0; + timeout = 5*MSEC; + set_state(port, PD_STATE_SRC_STARTUP); + } + /* + * AUDIO_ACC will remain in this state indefinitely + * until disconnect. + */ + break; + case PD_STATE_SRC_HARD_RESET_RECOVER: + /* Do not continue until hard reset recovery time */ + if (get_time().val < pd[port].src_recover) { + timeout = 50*MSEC; + break; + } + + /* Enable VBUS */ + timeout = 10*MSEC; + if (pd_set_power_supply_ready(port)) { + set_state(port, PD_STATE_SRC_DISCONNECTED); + break; + } +#ifdef CONFIG_USB_PD_TCPM_TCPCI + /* + * After transmitting hard reset, TCPM writes + * to RECEIVE_DETECT register to enable + * PD message passing. + */ + if (pd_comm_is_enabled(port)) + tcpm_set_rx_enable(port, 1); +#endif /* CONFIG_USB_PD_TCPM_TCPCI */ + + set_state(port, PD_STATE_SRC_STARTUP); + break; + case PD_STATE_SRC_STARTUP: + /* Wait for power source to enable */ + if (pd[port].last_state != pd[port].task_state) { + pd[port].flags |= PD_FLAGS_CHECK_IDENTITY; + /* reset various counters */ + caps_count = 0; + pd[port].msg_id = 0; + snk_cap_count = 0; + set_state_timeout( + port, +#ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP + /* + * delay for power supply to start up. + * subtract out debounce time if coming + * from debounce state since vbus is + * on during debounce. + */ + get_time().val + + PD_POWER_SUPPLY_TURN_ON_DELAY - + (pd[port].last_state == + PD_STATE_SRC_DISCONNECTED_DEBOUNCE + ? PD_T_CC_DEBOUNCE : 0), +#else + get_time().val + + PD_POWER_SUPPLY_TURN_ON_DELAY, +#endif + PD_STATE_SRC_DISCOVERY); + } + break; + case PD_STATE_SRC_DISCOVERY: + if (pd[port].last_state != pd[port].task_state) { + /* + * If we have had PD connection with this port + * partner, then start NoResponseTimer. + */ + if (pd[port].flags & PD_FLAGS_PREVIOUS_PD_CONN) + set_state_timeout(port, + get_time().val + + PD_T_NO_RESPONSE, + hard_reset_count < + PD_HARD_RESET_COUNT ? + PD_STATE_HARD_RESET_SEND : + PD_STATE_SRC_DISCONNECTED); + } + + /* Send source cap some minimum number of times */ + if (caps_count < PD_CAPS_COUNT) { + /* Query capabilities of the other side */ + res = send_source_cap(port); + /* packet was acked => PD capable device) */ + if (res >= 0) { + set_state(port, + PD_STATE_SRC_NEGOCIATE); + timeout = 10*MSEC; + hard_reset_count = 0; + caps_count = 0; + /* Port partner is PD capable */ + pd[port].flags |= + PD_FLAGS_PREVIOUS_PD_CONN; + } else { /* failed, retry later */ + timeout = PD_T_SEND_SOURCE_CAP; + caps_count++; + } + } + break; + case PD_STATE_SRC_NEGOCIATE: + /* wait for a "Request" message */ + if (pd[port].last_state != pd[port].task_state) + set_state_timeout(port, + get_time().val + + PD_T_SENDER_RESPONSE, + PD_STATE_HARD_RESET_SEND); + break; + case PD_STATE_SRC_ACCEPTED: + /* Accept sent, wait for enabling the new voltage */ + if (pd[port].last_state != pd[port].task_state) + set_state_timeout( + port, + get_time().val + + PD_T_SINK_TRANSITION, + PD_STATE_SRC_POWERED); + break; + case PD_STATE_SRC_POWERED: + /* Switch to the new requested voltage */ + if (pd[port].last_state != pd[port].task_state) { + pd_transition_voltage(pd[port].requested_idx); + set_state_timeout( + port, + get_time().val + + PD_POWER_SUPPLY_TURN_ON_DELAY, + PD_STATE_SRC_TRANSITION); + } + break; + case PD_STATE_SRC_TRANSITION: + /* the voltage output is good, notify the source */ + res = send_control(port, PD_CTRL_PS_RDY); + if (res >= 0) { + timeout = 10*MSEC; + /* it'a time to ping regularly the sink */ + set_state(port, PD_STATE_SRC_READY); + } else { + /* The sink did not ack, cut the power... */ + set_state(port, PD_STATE_SRC_DISCONNECTED); + } + break; + case PD_STATE_SRC_READY: + timeout = PD_T_SOURCE_ACTIVITY; + + /* + * Don't send any PD traffic if we woke up due to + * incoming packet or if VDO response pending to avoid + * collisions. + */ + if (incoming_packet || + (pd[port].vdm_state == VDM_STATE_BUSY)) + break; + + /* Send updated source capabilities to our partner */ + if (pd[port].flags & PD_FLAGS_UPDATE_SRC_CAPS) { + res = send_source_cap(port); + if (res >= 0) { + set_state(port, + PD_STATE_SRC_NEGOCIATE); + pd[port].flags &= + ~PD_FLAGS_UPDATE_SRC_CAPS; + } + break; + } + + /* Send get sink cap if haven't received it yet */ + if (!(pd[port].flags & PD_FLAGS_SNK_CAP_RECVD)) { + if (++snk_cap_count <= PD_SNK_CAP_RETRIES) { + /* Get sink cap to know if dual-role device */ + send_control(port, PD_CTRL_GET_SINK_CAP); + set_state(port, PD_STATE_SRC_GET_SINK_CAP); + break; + } else if (debug_level >= 2 && + snk_cap_count == PD_SNK_CAP_RETRIES+1) { + CPRINTF("ERR SNK_CAP\n"); + } + } + + /* Check power role policy, which may trigger a swap */ + if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) { + pd_check_pr_role(port, PD_ROLE_SOURCE, + pd[port].flags); + pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE; + break; + } + + /* Check data role policy, which may trigger a swap */ + if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) { + pd_check_dr_role(port, pd[port].data_role, + pd[port].flags); + pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE; + break; + } + + /* Send discovery SVDMs last */ + if (pd[port].data_role == PD_ROLE_DFP && + (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) { +#ifndef CONFIG_USB_PD_SIMPLE_DFP + pd_send_vdm(port, USB_SID_PD, + CMD_DISCOVER_IDENT, NULL, 0); +#endif + pd[port].flags &= ~PD_FLAGS_CHECK_IDENTITY; + break; + } + + if (!(pd[port].flags & PD_FLAGS_PING_ENABLED)) + break; + + /* Verify that the sink is alive */ + res = send_control(port, PD_CTRL_PING); + if (res >= 0) + break; + + /* Ping dropped. Try soft reset. */ + set_state(port, PD_STATE_SOFT_RESET); + timeout = 10 * MSEC; + break; + case PD_STATE_SRC_GET_SINK_CAP: + if (pd[port].last_state != pd[port].task_state) + set_state_timeout(port, + get_time().val + + PD_T_SENDER_RESPONSE, + PD_STATE_SRC_READY); + break; + case PD_STATE_DR_SWAP: + if (pd[port].last_state != pd[port].task_state) { + res = send_control(port, PD_CTRL_DR_SWAP); + if (res < 0) { + timeout = 10*MSEC; + /* + * If failed to get goodCRC, send + * soft reset, otherwise ignore + * failure. + */ + set_state(port, res == -1 ? + PD_STATE_SOFT_RESET : + READY_RETURN_STATE(port)); + break; + } + /* Wait for accept or reject */ + set_state_timeout(port, + get_time().val + + PD_T_SENDER_RESPONSE, + READY_RETURN_STATE(port)); + } + break; +#ifdef CONFIG_USB_PD_DUAL_ROLE + case PD_STATE_SRC_SWAP_INIT: + if (pd[port].last_state != pd[port].task_state) { + res = send_control(port, PD_CTRL_PR_SWAP); + if (res < 0) { + timeout = 10*MSEC; + /* + * If failed to get goodCRC, send + * soft reset, otherwise ignore + * failure. + */ + set_state(port, res == -1 ? + PD_STATE_SOFT_RESET : + PD_STATE_SRC_READY); + break; + } + /* Wait for accept or reject */ + set_state_timeout(port, + get_time().val + + PD_T_SENDER_RESPONSE, + PD_STATE_SRC_READY); + } + break; + case PD_STATE_SRC_SWAP_SNK_DISABLE: + /* Give time for sink to stop drawing current */ + if (pd[port].last_state != pd[port].task_state) + set_state_timeout(port, + get_time().val + + PD_T_SINK_TRANSITION, + PD_STATE_SRC_SWAP_SRC_DISABLE); + break; + case PD_STATE_SRC_SWAP_SRC_DISABLE: + /* Turn power off */ + if (pd[port].last_state != pd[port].task_state) { + pd_power_supply_reset(port); + set_state_timeout(port, + get_time().val + + PD_POWER_SUPPLY_TURN_OFF_DELAY, + PD_STATE_SRC_SWAP_STANDBY); + } + break; + case PD_STATE_SRC_SWAP_STANDBY: + /* Send PS_RDY to let sink know our power is off */ + if (pd[port].last_state != pd[port].task_state) { + /* Send PS_RDY */ + res = send_control(port, PD_CTRL_PS_RDY); + if (res < 0) { + timeout = 10*MSEC; + set_state(port, + PD_STATE_SRC_DISCONNECTED); + break; + } + /* Switch to Rd and swap roles to sink */ + tcpm_set_cc(port, TYPEC_CC_RD); + pd[port].power_role = PD_ROLE_SINK; + /* Wait for PS_RDY from new source */ + set_state_timeout(port, + get_time().val + + PD_T_PS_SOURCE_ON, + PD_STATE_SNK_DISCONNECTED); + } + break; + case PD_STATE_SUSPENDED: { +#ifndef CONFIG_USB_PD_TCPC + int rstatus; +#endif + CPRINTS("TCPC p%d suspended!", port); + pd[port].req_suspend_state = 0; +#ifdef CONFIG_USB_PD_TCPC + pd_rx_disable_monitoring(port); + pd_hw_release(port); + pd_power_supply_reset(port); +#else + rstatus = tcpm_release(port); + if (rstatus != 0 && rstatus != EC_ERROR_UNIMPLEMENTED) + CPRINTS("TCPC p%d release failed!", port); +#endif + /* Wait for resume */ + // getting rid of task stuff + //while (pd[port].task_state == PD_STATE_SUSPENDED) + // task_wait_event(-1); +#ifdef CONFIG_USB_PD_TCPC + pd_hw_init(port, PD_ROLE_DEFAULT(port)); + CPRINTS("TCPC p%d resumed!", port); +#else + if (rstatus != EC_ERROR_UNIMPLEMENTED && + pd_restart_tcpc(port) != 0) { + /* stay in PD_STATE_SUSPENDED */ + CPRINTS("TCPC p%d restart failed!", port); + break; + } + set_state(port, PD_DEFAULT_STATE(port)); + CPRINTS("TCPC p%d resumed!", port); +#endif + break; + } + case PD_STATE_SNK_DISCONNECTED: +#ifdef CONFIG_USB_PD_LOW_POWER + timeout = drp_state != PD_DRP_TOGGLE_ON ? SECOND + : 10*MSEC; +#else + timeout = 10*MSEC; +#endif + tcpm_get_cc(port, &cc1, &cc2); + +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE + /* + * Attempt TCPC auto DRP toggle if it is + * not already auto toggling and not try.src + */ + if (auto_toggle_supported && + !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) && + !(pd[port].flags & PD_FLAGS_TRY_SRC) && + (cc1 == TYPEC_CC_VOLT_OPEN && + cc2 == TYPEC_CC_VOLT_OPEN)) { + set_state(port, PD_STATE_DRP_AUTO_TOGGLE); + timeout = 2*MSEC; + break; + } +#endif + + /* Source connection monitoring */ + if (cc1 != TYPEC_CC_VOLT_OPEN || + cc2 != TYPEC_CC_VOLT_OPEN) { + pd[port].cc_state = PD_CC_NONE; + hard_reset_count = 0; + new_cc_state = PD_CC_NONE; + pd[port].cc_debounce = get_time().val + + PD_T_CC_DEBOUNCE; + set_state(port, + PD_STATE_SNK_DISCONNECTED_DEBOUNCE); + timeout = 10*MSEC; + break; + } + + /* + * If Try.SRC is active and failed to detect a SNK, + * then it transitions to TryWait.SNK. Need to prevent + * normal dual role toggle until tDRPTryWait timer + * expires. + */ + if (pd[port].flags & PD_FLAGS_TRY_SRC) { + if (get_time().val > pd[port].try_src_marker) + pd[port].flags &= ~PD_FLAGS_TRY_SRC; + break; + } + + /* If no source detected, check for role toggle. */ + if (drp_state == PD_DRP_TOGGLE_ON && + get_time().val >= next_role_swap) { + /* Swap roles to source */ + pd[port].power_role = PD_ROLE_SOURCE; + set_state(port, PD_STATE_SRC_DISCONNECTED); + tcpm_set_cc(port, TYPEC_CC_RP); + next_role_swap = get_time().val + PD_T_DRP_SRC; + + /* Swap states quickly */ + timeout = 2*MSEC; + } + break; + case PD_STATE_SNK_DISCONNECTED_DEBOUNCE: + tcpm_get_cc(port, &cc1, &cc2); + + if (cc_is_rp(cc1) && cc_is_rp(cc2)) { + /* Debug accessory */ + new_cc_state = PD_CC_DEBUG_ACC; + } else if (cc_is_rp(cc1) || cc_is_rp(cc2)) { + new_cc_state = PD_CC_DFP_ATTACHED; + } else { + /* No connection any more */ + set_state(port, PD_STATE_SNK_DISCONNECTED); + timeout = 5*MSEC; + break; + } + + timeout = 20*MSEC; + + /* Debounce the cc state */ + if (new_cc_state != pd[port].cc_state) { + pd[port].cc_debounce = get_time().val + + PD_T_CC_DEBOUNCE; + pd[port].cc_state = new_cc_state; + break; + } + /* Wait for CC debounce and VBUS present */ + if (get_time().val < pd[port].cc_debounce || + !pd_is_vbus_present(port)) + break; + + if (pd_try_src_enable && + !(pd[port].flags & PD_FLAGS_TRY_SRC)) { + /* + * If TRY_SRC is enabled, but not active, + * then force attempt to connect as source. + */ + pd[port].try_src_marker = get_time().val + + PD_T_TRY_SRC; + /* Swap roles to source */ + pd[port].power_role = PD_ROLE_SOURCE; + tcpm_set_cc(port, TYPEC_CC_RP); + timeout = 2*MSEC; + set_state(port, PD_STATE_SRC_DISCONNECTED); + /* Set flag after the state change */ + pd[port].flags |= PD_FLAGS_TRY_SRC; + break; + } + + /* We are attached */ + pd[port].polarity = get_snk_polarity(cc1, cc2); + tcpm_set_polarity(port, pd[port].polarity); + /* reset message ID on connection */ + pd[port].msg_id = 0; + /* initial data role for sink is UFP */ + pd_set_data_role(port, PD_ROLE_UFP); +#if defined(CONFIG_CHARGE_MANAGER) + typec_curr = get_typec_current_limit(pd[port].polarity, + cc1, cc2); + //typec_set_input_current_limit( + // port, typec_curr, TYPE_C_VOLTAGE); +#endif + /* If PD comm is enabled, enable TCPC RX */ + if (pd_comm_is_enabled(port)) + tcpm_set_rx_enable(port, 1); + + /* DFP is attached */ + if (new_cc_state == PD_CC_DFP_ATTACHED || + new_cc_state == PD_CC_DEBUG_ACC) { + pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE | + PD_FLAGS_CHECK_DR_ROLE | + PD_FLAGS_CHECK_IDENTITY; + if (new_cc_state == PD_CC_DEBUG_ACC) + pd[port].flags |= + PD_FLAGS_TS_DTS_PARTNER; + send_control(port, PD_CTRL_GET_SOURCE_CAP); + set_state(port, PD_STATE_SNK_DISCOVERY); + timeout = 10*MSEC; + //hook_call_deferred( + // &pd_usb_billboard_deferred_data, + // PD_T_AME); + } + break; + case PD_STATE_SNK_HARD_RESET_RECOVER: + if (pd[port].last_state != pd[port].task_state) + pd[port].flags |= PD_FLAGS_CHECK_IDENTITY; +#ifdef CONFIG_USB_PD_VBUS_DETECT_NONE + /* + * Can't measure vbus state so this is the maximum + * recovery time for the source. + */ + if (pd[port].last_state != pd[port].task_state) + set_state_timeout(port, get_time().val + + PD_T_SAFE_0V + + PD_T_SRC_RECOVER_MAX + + PD_T_SRC_TURN_ON, + PD_STATE_SNK_DISCONNECTED); +#else + /* Wait for VBUS to go low and then high*/ + if (pd[port].last_state != pd[port].task_state) { + snk_hard_reset_vbus_off = 0; + set_state_timeout(port, + get_time().val + + PD_T_SAFE_0V, + hard_reset_count < + PD_HARD_RESET_COUNT ? + PD_STATE_HARD_RESET_SEND : + PD_STATE_SNK_DISCOVERY); + } + + if (!pd_is_vbus_present(port) && + !snk_hard_reset_vbus_off) { + /* VBUS has gone low, reset timeout */ + snk_hard_reset_vbus_off = 1; + set_state_timeout(port, + get_time().val + + PD_T_SRC_RECOVER_MAX + + PD_T_SRC_TURN_ON, + PD_STATE_SNK_DISCONNECTED); + } + if (pd_is_vbus_present(port) && + snk_hard_reset_vbus_off) { +#ifdef CONFIG_USB_PD_TCPM_TCPCI + /* + * After transmitting hard reset, TCPM writes + * to RECEIVE_MESSAGE register to enable + * PD message passing. + */ + if (pd_comm_is_enabled(port)) + tcpm_set_rx_enable(port, 1); +#endif /* CONFIG_USB_PD_TCPM_TCPCI */ + + /* VBUS went high again */ + set_state(port, PD_STATE_SNK_DISCOVERY); + timeout = 10*MSEC; + } + + /* + * Don't need to set timeout because VBUS changing + * will trigger an interrupt and wake us up. + */ +#endif + break; + case PD_STATE_SNK_DISCOVERY: + /* Wait for source cap expired only if we are enabled */ + if ((pd[port].last_state != pd[port].task_state) + && pd_comm_is_enabled(port)) { + /* + * If VBUS has never been low, and we timeout + * waiting for source cap, try a soft reset + * first, in case we were already in a stable + * contract before this boot. + */ + if (pd[port].flags & PD_FLAGS_VBUS_NEVER_LOW) + set_state_timeout(port, + get_time().val + + PD_T_SINK_WAIT_CAP, + PD_STATE_SOFT_RESET); + /* + * If we haven't passed hard reset counter, + * start SinkWaitCapTimer, otherwise start + * NoResponseTimer. + */ + else if (hard_reset_count < PD_HARD_RESET_COUNT) + set_state_timeout(port, + get_time().val + + PD_T_SINK_WAIT_CAP, + PD_STATE_HARD_RESET_SEND); + else if (pd[port].flags & + PD_FLAGS_PREVIOUS_PD_CONN) + /* ErrorRecovery */ + set_state_timeout(port, + get_time().val + + PD_T_NO_RESPONSE, + PD_STATE_SNK_DISCONNECTED); +#if defined(CONFIG_CHARGE_MANAGER) + /* + * If we didn't come from disconnected, must + * have come from some path that did not set + * typec current limit. So, set to 0 so that + * we guarantee this is revised below. + */ + if (pd[port].last_state != + PD_STATE_SNK_DISCONNECTED_DEBOUNCE) + typec_curr = 0; +#endif + } + +#if defined(CONFIG_CHARGE_MANAGER) + timeout = PD_T_SINK_ADJ - PD_T_DEBOUNCE; + + /* Check if CC pull-up has changed */ + tcpm_get_cc(port, &cc1, &cc2); + if (typec_curr != get_typec_current_limit( + pd[port].polarity, cc1, cc2)) { + /* debounce signal by requiring two reads */ + if (typec_curr_change) { + /* set new input current limit */ + typec_curr = get_typec_current_limit( + pd[port].polarity, cc1, cc2); + //typec_set_input_current_limit( + // port, typec_curr, TYPE_C_VOLTAGE); + } else { + /* delay for debounce */ + timeout = PD_T_DEBOUNCE; + } + typec_curr_change = !typec_curr_change; + } else { + typec_curr_change = 0; + } +#endif + break; + case PD_STATE_SNK_REQUESTED: + /* Wait for ACCEPT or REJECT */ + if (pd[port].last_state != pd[port].task_state) { + hard_reset_count = 0; + set_state_timeout(port, + get_time().val + + PD_T_SENDER_RESPONSE, + PD_STATE_HARD_RESET_SEND); + } + break; + case PD_STATE_SNK_TRANSITION: + /* Wait for PS_RDY */ + if (pd[port].last_state != pd[port].task_state) + set_state_timeout(port, + get_time().val + + PD_T_PS_TRANSITION, + PD_STATE_HARD_RESET_SEND); + break; + case PD_STATE_SNK_READY: + timeout = 20*MSEC; + + /* + * Don't send any PD traffic if we woke up due to + * incoming packet or if VDO response pending to avoid + * collisions. + */ + if (incoming_packet || + (pd[port].vdm_state == VDM_STATE_BUSY)) + break; + + /* Check for new power to request */ + if (pd[port].new_power_request) { + if (pd_send_request_msg(port, 0) != EC_SUCCESS) + set_state(port, PD_STATE_SOFT_RESET); + break; + } + + /* Check power role policy, which may trigger a swap */ + if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) { + pd_check_pr_role(port, PD_ROLE_SINK, + pd[port].flags); + pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE; + break; + } + + /* Check data role policy, which may trigger a swap */ + if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) { + pd_check_dr_role(port, pd[port].data_role, + pd[port].flags); + pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE; + break; + } + + /* If DFP, send discovery SVDMs */ + if (pd[port].data_role == PD_ROLE_DFP && + (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) { + pd_send_vdm(port, USB_SID_PD, + CMD_DISCOVER_IDENT, NULL, 0); + pd[port].flags &= ~PD_FLAGS_CHECK_IDENTITY; + break; + } + + /* Sent all messages, don't need to wake very often */ + timeout = 200*MSEC; + break; + case PD_STATE_SNK_SWAP_INIT: + if (pd[port].last_state != pd[port].task_state) { + res = send_control(port, PD_CTRL_PR_SWAP); + if (res < 0) { + timeout = 10*MSEC; + /* + * If failed to get goodCRC, send + * soft reset, otherwise ignore + * failure. + */ + set_state(port, res == -1 ? + PD_STATE_SOFT_RESET : + PD_STATE_SNK_READY); + break; + } + /* Wait for accept or reject */ + set_state_timeout(port, + get_time().val + + PD_T_SENDER_RESPONSE, + PD_STATE_SNK_READY); + } + break; + case PD_STATE_SNK_SWAP_SNK_DISABLE: + /* Stop drawing power */ + pd_set_input_current_limit(port, 0, 0); +#ifdef CONFIG_CHARGE_MANAGER + //typec_set_input_current_limit(port, 0, 0); + //charge_manager_set_ceil(port, + // CEIL_REQUESTOR_PD, + // CHARGE_CEIL_NONE); +#endif + set_state(port, PD_STATE_SNK_SWAP_SRC_DISABLE); + timeout = 10*MSEC; + break; + case PD_STATE_SNK_SWAP_SRC_DISABLE: + /* Wait for PS_RDY */ + if (pd[port].last_state != pd[port].task_state) + set_state_timeout(port, + get_time().val + + PD_T_PS_SOURCE_OFF, + PD_STATE_HARD_RESET_SEND); + break; + case PD_STATE_SNK_SWAP_STANDBY: + if (pd[port].last_state != pd[port].task_state) { + /* Switch to Rp and enable power supply */ + tcpm_set_cc(port, TYPEC_CC_RP); + if (pd_set_power_supply_ready(port)) { + /* Restore Rd */ + tcpm_set_cc(port, TYPEC_CC_RD); + timeout = 10*MSEC; + set_state(port, + PD_STATE_SNK_DISCONNECTED); + break; + } + /* Wait for power supply to turn on */ + set_state_timeout( + port, + get_time().val + + PD_POWER_SUPPLY_TURN_ON_DELAY, + PD_STATE_SNK_SWAP_COMPLETE); + } + break; + case PD_STATE_SNK_SWAP_COMPLETE: + /* Send PS_RDY and change to source role */ + res = send_control(port, PD_CTRL_PS_RDY); + if (res < 0) { + /* Restore Rd */ + tcpm_set_cc(port, TYPEC_CC_RD); + pd_power_supply_reset(port); + timeout = 10 * MSEC; + set_state(port, PD_STATE_SNK_DISCONNECTED); + break; + } + + /* Don't send GET_SINK_CAP on swap */ + snk_cap_count = PD_SNK_CAP_RETRIES+1; + caps_count = 0; + pd[port].msg_id = 0; + pd[port].power_role = PD_ROLE_SOURCE; + pd_update_roles(port); + set_state(port, PD_STATE_SRC_DISCOVERY); + timeout = 10*MSEC; + break; +#ifdef CONFIG_USBC_VCONN_SWAP + case PD_STATE_VCONN_SWAP_SEND: + if (pd[port].last_state != pd[port].task_state) { + res = send_control(port, PD_CTRL_VCONN_SWAP); + if (res < 0) { + timeout = 10*MSEC; + /* + * If failed to get goodCRC, send + * soft reset, otherwise ignore + * failure. + */ + set_state(port, res == -1 ? + PD_STATE_SOFT_RESET : + READY_RETURN_STATE(port)); + break; + } + /* Wait for accept or reject */ + set_state_timeout(port, + get_time().val + + PD_T_SENDER_RESPONSE, + READY_RETURN_STATE(port)); + } + break; + case PD_STATE_VCONN_SWAP_INIT: + if (pd[port].last_state != pd[port].task_state) { + if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) { + /* Turn VCONN on and wait for it */ + tcpm_set_vconn(port, 1); + set_state_timeout(port, + get_time().val + PD_VCONN_SWAP_DELAY, + PD_STATE_VCONN_SWAP_READY); + } else { + set_state_timeout(port, + get_time().val + PD_T_VCONN_SOURCE_ON, + READY_RETURN_STATE(port)); + } + } + break; + case PD_STATE_VCONN_SWAP_READY: + if (pd[port].last_state != pd[port].task_state) { + if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) { + /* VCONN is now on, send PS_RDY */ + pd[port].flags |= PD_FLAGS_VCONN_ON; + res = send_control(port, + PD_CTRL_PS_RDY); + if (res == -1) { + timeout = 10*MSEC; + /* + * If failed to get goodCRC, + * send soft reset + */ + set_state(port, + PD_STATE_SOFT_RESET); + break; + } + set_state(port, + READY_RETURN_STATE(port)); + } else { + /* Turn VCONN off and wait for it */ + tcpm_set_vconn(port, 0); + pd[port].flags &= ~PD_FLAGS_VCONN_ON; + set_state_timeout(port, + get_time().val + PD_VCONN_SWAP_DELAY, + READY_RETURN_STATE(port)); + } + } + break; +#endif /* CONFIG_USBC_VCONN_SWAP */ +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + case PD_STATE_SOFT_RESET: + if (pd[port].last_state != pd[port].task_state) { + /* Message ID of soft reset is always 0 */ + pd[port].msg_id = 0; + res = send_control(port, PD_CTRL_SOFT_RESET); + + /* if soft reset failed, try hard reset. */ + if (res < 0) { + set_state(port, + PD_STATE_HARD_RESET_SEND); + timeout = 5*MSEC; + break; + } + + set_state_timeout( + port, + get_time().val + PD_T_SENDER_RESPONSE, + PD_STATE_HARD_RESET_SEND); + } + break; + case PD_STATE_HARD_RESET_SEND: + hard_reset_count++; + if (pd[port].last_state != pd[port].task_state) + hard_reset_sent = 0; +#ifdef CONFIG_CHARGE_MANAGER + if (pd[port].last_state == PD_STATE_SNK_DISCOVERY || + (pd[port].last_state == PD_STATE_SOFT_RESET && + (pd[port].flags & PD_FLAGS_VBUS_NEVER_LOW))) { + pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW; + /* + * If discovery timed out, assume that we + * have a dedicated charger attached. This + * may not be a correct assumption according + * to the specification, but it generally + * works in practice and the harmful + * effects of a wrong assumption here + * are minimal. + */ + //charge_manager_update_dualrole(port, + // CAP_DEDICATED); + } +#endif + + /* try sending hard reset until it succeeds */ + if (!hard_reset_sent) { + if (pd_transmit(port, TCPC_TX_HARD_RESET, + 0, NULL) < 0) { + timeout = 10*MSEC; + break; + } + + /* successfully sent hard reset */ + hard_reset_sent = 1; + /* + * If we are source, delay before cutting power + * to allow sink time to get hard reset. + */ + if (pd[port].power_role == PD_ROLE_SOURCE) { + set_state_timeout(port, + get_time().val + PD_T_PS_HARD_RESET, + PD_STATE_HARD_RESET_EXECUTE); + } else { + set_state(port, + PD_STATE_HARD_RESET_EXECUTE); + timeout = 10*MSEC; + } + } + break; + case PD_STATE_HARD_RESET_EXECUTE: +#ifdef CONFIG_USB_PD_DUAL_ROLE + /* + * If hard reset while in the last stages of power + * swap, then we need to restore our CC resistor. + */ + if (pd[port].last_state == PD_STATE_SNK_SWAP_STANDBY) + tcpm_set_cc(port, TYPEC_CC_RD); +#endif + + /* reset our own state machine */ + pd_execute_hard_reset(port); + timeout = 10*MSEC; + break; +#ifdef CONFIG_COMMON_RUNTIME + case PD_STATE_BIST_RX: + send_bist_cmd(port); + /* Delay at least enough for partner to finish BIST */ + timeout = PD_T_BIST_RECEIVE + 20*MSEC; + /* Set to appropriate port disconnected state */ + set_state(port, DUAL_ROLE_IF_ELSE(port, + PD_STATE_SNK_DISCONNECTED, + PD_STATE_SRC_DISCONNECTED)); + break; + case PD_STATE_BIST_TX: + pd_transmit(port, TCPC_TX_BIST_MODE_2, 0, NULL); + /* Delay at least enough to finish sending BIST */ + timeout = PD_T_BIST_TRANSMIT + 20*MSEC; + /* Set to appropriate port disconnected state */ + set_state(port, DUAL_ROLE_IF_ELSE(port, + PD_STATE_SNK_DISCONNECTED, + PD_STATE_SRC_DISCONNECTED)); + break; +#endif +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE + case PD_STATE_DRP_AUTO_TOGGLE: + { + enum pd_states next_state; + + assert(auto_toggle_supported); + + /* Check for connection */ + tcpm_get_cc(port, &cc1, &cc2); + + /* Set to appropriate port state */ + if (cc1 == TYPEC_CC_VOLT_OPEN && + cc2 == TYPEC_CC_VOLT_OPEN) + /* nothing connected, keep toggling*/ + next_state = PD_STATE_DRP_AUTO_TOGGLE; + else if ((cc_is_rp(cc1) || cc_is_rp(cc2)) && + drp_state != PD_DRP_FORCE_SOURCE) + /* SNK allowed unless ForceSRC */ + next_state = PD_STATE_SNK_DISCONNECTED; + else if (((cc1 == TYPEC_CC_VOLT_RD || + cc2 == TYPEC_CC_VOLT_RD) || + (cc1 == TYPEC_CC_VOLT_RA && + cc2 == TYPEC_CC_VOLT_RA)) && + (drp_state != PD_DRP_TOGGLE_OFF && + drp_state != PD_DRP_FORCE_SINK)) + /* SRC allowed unless ForceSNK or Toggle Off */ + next_state = PD_STATE_SRC_DISCONNECTED; + else + /* Anything else, keep toggling */ + next_state = PD_STATE_DRP_AUTO_TOGGLE; + + if (next_state != PD_STATE_DRP_AUTO_TOGGLE) { + tcpm_set_drp_toggle(port, 0); +#ifdef CONFIG_USB_PD_TCPC_LOW_POWER + CPRINTS("TCPC p%d Exit Low Power Mode", port); +#endif + } + + if (next_state == PD_STATE_SNK_DISCONNECTED) { + tcpm_set_cc(port, TYPEC_CC_RD); + pd[port].power_role = PD_ROLE_SINK; + timeout = 2*MSEC; + } else if (next_state == PD_STATE_SRC_DISCONNECTED) { + tcpm_set_cc(port, TYPEC_CC_RP); + pd[port].power_role = PD_ROLE_SOURCE; + timeout = 2*MSEC; + } else { + tcpm_set_drp_toggle(port, 1); + pd[port].flags |= PD_FLAGS_TCPC_DRP_TOGGLE; + timeout = -1; +#ifdef CONFIG_USB_PD_TCPC_LOW_POWER + CPRINTS("TCPC p%d Low Power Mode", port); +#endif + } + set_state(port, next_state); + + break; + } +#endif + default: + break; + } + + pd[port].last_state = this_state; + + /* + * Check for state timeout, and if not check if need to adjust + * timeout value to wake up on the next state timeout. + */ + now = get_time(); + if (pd[port].timeout) { + if (now.val >= pd[port].timeout) { + set_state(port, pd[port].timeout_state); + /* On a state timeout, run next state soon */ + timeout = timeout < 10*MSEC ? timeout : 10*MSEC; + } else if (pd[port].timeout - now.val < timeout) { + timeout = pd[port].timeout - now.val; + } + } + + /* Check for disconnection if we're connected */ + if (!pd_is_connected(port)) + return; +#ifdef CONFIG_USB_PD_DUAL_ROLE + if (pd_is_power_swapping(port)) + return; +#endif + if (pd[port].power_role == PD_ROLE_SOURCE) { + /* Source: detect disconnect by monitoring CC */ + tcpm_get_cc(port, &cc1, &cc2); + if (pd[port].polarity) + cc1 = cc2; + if (cc1 == TYPEC_CC_VOLT_OPEN) { + set_state(port, PD_STATE_SRC_DISCONNECTED); + /* Debouncing */ + timeout = 10*MSEC; +#ifdef CONFIG_USB_PD_DUAL_ROLE + /* + * If Try.SRC is configured, then ATTACHED_SRC + * needs to transition to TryWait.SNK. Change + * power role to SNK and start state timer. + */ + if (pd_try_src_enable) { + /* Swap roles to sink */ + pd[port].power_role = PD_ROLE_SINK; + tcpm_set_cc(port, TYPEC_CC_RD); + /* Set timer for TryWait.SNK state */ + pd[port].try_src_marker = get_time().val + + PD_T_TRY_WAIT; + /* Advance to TryWait.SNK state */ + set_state(port, + PD_STATE_SNK_DISCONNECTED); + /* Mark state as TryWait.SNK */ + pd[port].flags |= PD_FLAGS_TRY_SRC; + } +#endif + } + } +#ifdef CONFIG_USB_PD_DUAL_ROLE + /* + * Sink disconnect if VBUS is low and we are not recovering + * a hard reset. + */ + if (pd[port].power_role == PD_ROLE_SINK && + !pd_is_vbus_present(port) && + pd[port].task_state != PD_STATE_SNK_HARD_RESET_RECOVER && + pd[port].task_state != PD_STATE_HARD_RESET_EXECUTE) { + /* Sink: detect disconnect by monitoring VBUS */ + set_state(port, PD_STATE_SNK_DISCONNECTED); + /* set timeout small to reconnect fast */ + timeout = 5*MSEC; + } +#endif /* CONFIG_USB_PD_DUAL_ROLE */ +} + +#ifdef CONFIG_USB_PD_DUAL_ROLE +static void dual_role_on(void) +{ + int i; + + for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) { +#ifdef CONFIG_CHARGE_MANAGER + //if (charge_manager_get_active_charge_port() != i) +#endif + pd[i].flags |= PD_FLAGS_CHECK_PR_ROLE | + PD_FLAGS_CHECK_DR_ROLE; + + pd[i].flags |= PD_FLAGS_CHECK_IDENTITY; + } + + pd_set_dual_role(PD_DRP_TOGGLE_ON); + CPRINTS("chipset -> S0"); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, dual_role_on, HOOK_PRIO_DEFAULT); + +static void dual_role_off(void) +{ + pd_set_dual_role(PD_DRP_TOGGLE_OFF); + CPRINTS("chipset -> S3"); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, dual_role_off, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, dual_role_off, HOOK_PRIO_DEFAULT); + +static void dual_role_force_sink(void) +{ + pd_set_dual_role(PD_DRP_FORCE_SINK); + CPRINTS("chipset -> S5"); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, dual_role_force_sink, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + +#ifdef CONFIG_COMMON_RUNTIME + +/* + * (enable=1) request pd_task transition to the suspended state. hang + * around for a while until we observe the state change. this can + * take a while (like 300ms) on startup when pd_task is sleeping in + * tcpci_tcpm_init. + * + * (enable=0) force pd_task out of the suspended state and into the + * port's default state. + */ + +void pd_set_suspend(int port, int enable) +{ + int tries = 300; + + if (enable) { + pd[port].req_suspend_state = 1; + do { + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); + if (pd[port].task_state == PD_STATE_SUSPENDED) + break; + msleep(1); + } while (--tries != 0); + if (!tries) + CPRINTS("TCPC p%d set_suspend failed!", port); + } else { + if (pd[port].task_state != PD_STATE_SUSPENDED) + CPRINTS("TCPC p%d suspend disable request " + "while not suspended!", port); + set_state(port, PD_DEFAULT_STATE(port)); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); + } +} + +int pd_is_port_enabled(int port) +{ + switch (pd[port].task_state) { + case PD_STATE_DISABLED: + case PD_STATE_SUSPENDED: + return 0; + default: + return 1; + } +} + +#if defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) +static int hex8tou32(char *str, uint32_t *val) +{ + char *ptr = str; + uint32_t tmp = 0; + + while (*ptr) { + char c = *ptr++; + if (c >= '0' && c <= '9') + tmp = (tmp << 4) + (c - '0'); + else if (c >= 'A' && c <= 'F') + tmp = (tmp << 4) + (c - 'A' + 10); + else if (c >= 'a' && c <= 'f') + tmp = (tmp << 4) + (c - 'a' + 10); + else + return EC_ERROR_INVAL; + } + if (ptr != str + 8) + return EC_ERROR_INVAL; + *val = tmp; + return EC_SUCCESS; +} + +static int remote_flashing(int argc, char **argv) +{ + int port, cnt, cmd; + uint32_t data[VDO_MAX_SIZE-1]; + char *e; + static int flash_offset[CONFIG_USB_PD_PORT_COUNT]; + + if (argc < 4 || argc > (VDO_MAX_SIZE + 4 - 1)) + return EC_ERROR_PARAM_COUNT; + + port = strtoi(argv[1], &e, 10); + if (*e || port >= CONFIG_USB_PD_PORT_COUNT) + return EC_ERROR_PARAM2; + + cnt = 0; + if (!strcasecmp(argv[3], "erase")) { + cmd = VDO_CMD_FLASH_ERASE; + flash_offset[port] = 0; + ccprintf("ERASE ..."); + } else if (!strcasecmp(argv[3], "reboot")) { + cmd = VDO_CMD_REBOOT; + ccprintf("REBOOT ..."); + } else if (!strcasecmp(argv[3], "signature")) { + cmd = VDO_CMD_ERASE_SIG; + ccprintf("ERASE SIG ..."); + } else if (!strcasecmp(argv[3], "info")) { + cmd = VDO_CMD_READ_INFO; + ccprintf("INFO..."); + } else if (!strcasecmp(argv[3], "version")) { + cmd = VDO_CMD_VERSION; + ccprintf("VERSION..."); + } else { + int i; + argc -= 3; + for (i = 0; i < argc; i++) + if (hex8tou32(argv[i+3], data + i)) + return EC_ERROR_INVAL; + cmd = VDO_CMD_FLASH_WRITE; + cnt = argc; + ccprintf("WRITE %d @%04x ...", argc * 4, + flash_offset[port]); + flash_offset[port] += argc * 4; + } + + pd_send_vdm(port, USB_VID_GOOGLE, cmd, data, cnt); + + /* Wait until VDM is done */ + while (pd[port].vdm_state > 0) + task_wait_event(100*MSEC); + + ccprintf("DONE %d\n", pd[port].vdm_state); + return EC_SUCCESS; +} +#endif /* defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) */ + +#if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP) +void pd_send_hpd(int port, enum hpd_event hpd) +{ + uint32_t data[1]; + int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT); + if (!opos) + return; + + data[0] = VDO_DP_STATUS((hpd == hpd_irq), /* IRQ_HPD */ + (hpd != hpd_low), /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ + 1, /* enabled */ + 0, /* power low */ + 0x2); + pd_send_vdm(port, USB_SID_DISPLAYPORT, + VDO_OPOS(opos) | CMD_ATTENTION, data, 1); + /* Wait until VDM is done. */ + while (pd[0].vdm_state > 0) + task_wait_event(USB_PD_RX_TMOUT_US * (PD_RETRY_COUNT + 1)); +} +#endif + +int pd_fetch_acc_log_entry(int port) +{ + timestamp_t timeout; + + /* Cannot send a VDM now, the host should retry */ + if (pd[port].vdm_state > 0) + return pd[port].vdm_state == VDM_STATE_BUSY ? + EC_RES_BUSY : EC_RES_UNAVAILABLE; + + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_GET_LOG, NULL, 0); + timeout.val = get_time().val + 75*MSEC; + + /* Wait until VDM is done */ + while ((pd[port].vdm_state > 0) && + (get_time().val < timeout.val)) + task_wait_event(10*MSEC); + + if (pd[port].vdm_state > 0) + return EC_RES_TIMEOUT; + else if (pd[port].vdm_state < 0) + return EC_RES_ERROR; + + return EC_RES_SUCCESS; +} + +#ifdef CONFIG_USB_PD_DUAL_ROLE +void pd_request_source_voltage(int port, int mv) +{ + pd_set_max_voltage(mv); + + if (pd[port].task_state == PD_STATE_SNK_READY || + pd[port].task_state == PD_STATE_SNK_TRANSITION) { + /* Set flag to send new power request in pd_task */ + pd[port].new_power_request = 1; + } else { + pd[port].power_role = PD_ROLE_SINK; + tcpm_set_cc(port, TYPEC_CC_RD); + set_state(port, PD_STATE_SNK_DISCONNECTED); + } + + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); +} + +void pd_set_external_voltage_limit(int port, int mv) +{ + pd_set_max_voltage(mv); + + if (pd[port].task_state == PD_STATE_SNK_READY || + pd[port].task_state == PD_STATE_SNK_TRANSITION) { + /* Set flag to send new power request in pd_task */ + pd[port].new_power_request = 1; + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); + } +} + +void pd_update_contract(int port) +{ + if ((pd[port].task_state >= PD_STATE_SRC_NEGOCIATE) && + (pd[port].task_state <= PD_STATE_SRC_GET_SINK_CAP)) { + pd[port].flags |= PD_FLAGS_UPDATE_SRC_CAPS; + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); + } +} + +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + +static int command_pd(int argc, char **argv) +{ + int port; + char *e; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + +#if defined(CONFIG_CMD_PD) && defined(CONFIG_USB_PD_DUAL_ROLE) + /* command: pd */ + if (!strcasecmp(argv[1], "dualrole")) { + if (argc < 3) { + ccprintf("dual-role toggling: "); + switch (drp_state) { + case PD_DRP_TOGGLE_ON: + ccprintf("on\n"); + break; + case PD_DRP_TOGGLE_OFF: + ccprintf("off\n"); + break; + case PD_DRP_FREEZE: + ccprintf("freeze\n"); + break; + case PD_DRP_FORCE_SINK: + ccprintf("force sink\n"); + break; + case PD_DRP_FORCE_SOURCE: + ccprintf("force source\n"); + break; + } + } else { + if (!strcasecmp(argv[2], "on")) + pd_set_dual_role(PD_DRP_TOGGLE_ON); + else if (!strcasecmp(argv[2], "off")) + pd_set_dual_role(PD_DRP_TOGGLE_OFF); + else if (!strcasecmp(argv[2], "freeze")) + pd_set_dual_role(PD_DRP_FREEZE); + else if (!strcasecmp(argv[2], "sink")) + pd_set_dual_role(PD_DRP_FORCE_SINK); + else if (!strcasecmp(argv[2], "source")) + pd_set_dual_role(PD_DRP_FORCE_SOURCE); + else + return EC_ERROR_PARAM3; + } + return EC_SUCCESS; + } else +#endif + if (!strcasecmp(argv[1], "dump")) { +#ifndef CONFIG_USB_PD_DEBUG_LEVEL + int level; + + if (argc >= 3) { + level = strtoi(argv[2], &e, 10); + if (*e) + return EC_ERROR_PARAM2; + debug_level = level; + } else +#endif + ccprintf("dump level: %d\n", debug_level); + + return EC_SUCCESS; + } +#ifdef CONFIG_CMD_PD +#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO + else if (!strncasecmp(argv[1], "rwhashtable", 3)) { + int i; + struct ec_params_usb_pd_rw_hash_entry *p; + for (i = 0; i < RW_HASH_ENTRIES; i++) { + p = &rw_hash_table[i]; + pd_dev_dump_info(p->dev_id, p->dev_rw_hash); + } + return EC_SUCCESS; + } +#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */ +#ifdef CONFIG_USB_PD_TRY_SRC + else if (!strncasecmp(argv[1], "trysrc", 6)) { + int enable; + + if (argc < 2) { + return EC_ERROR_PARAM_COUNT; + } else if (argc >= 3) { + enable = strtoi(argv[2], &e, 10); + if (*e) + return EC_ERROR_PARAM3; + pd_try_src_enable = enable ? 1 : 0; + } + + ccprintf("Try.SRC %s\n", pd_try_src_enable ? "on" : "off"); + return EC_SUCCESS; + } +#endif +#endif + /* command: pd [args] */ + port = strtoi(argv[1], &e, 10); + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + if (*e || port >= CONFIG_USB_PD_PORT_COUNT) + return EC_ERROR_PARAM2; +#if defined(CONFIG_CMD_PD) && defined(CONFIG_USB_PD_DUAL_ROLE) + + if (!strcasecmp(argv[2], "tx")) { + set_state(port, PD_STATE_SNK_DISCOVERY); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); + } else if (!strcasecmp(argv[2], "bist_rx")) { + set_state(port, PD_STATE_BIST_RX); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); + } else if (!strcasecmp(argv[2], "bist_tx")) { + if (*e) + return EC_ERROR_PARAM3; + set_state(port, PD_STATE_BIST_TX); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); + } else if (!strcasecmp(argv[2], "charger")) { + pd[port].power_role = PD_ROLE_SOURCE; + tcpm_set_cc(port, TYPEC_CC_RP); + set_state(port, PD_STATE_SRC_DISCONNECTED); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); + } else if (!strncasecmp(argv[2], "dev", 3)) { + int max_volt; + if (argc >= 4) + max_volt = strtoi(argv[3], &e, 10) * 1000; + else + max_volt = pd_get_max_voltage(); + + pd_request_source_voltage(port, max_volt); + ccprintf("max req: %dmV\n", max_volt); + } else if (!strcasecmp(argv[2], "disable")) { + pd_comm_enable(port, 0); + ccprintf("Port C%d disable\n", port); + return EC_SUCCESS; + } else if (!strcasecmp(argv[2], "enable")) { + pd_comm_enable(port, 1); + ccprintf("Port C%d enabled\n", port); + return EC_SUCCESS; + } else if (!strncasecmp(argv[2], "hard", 4)) { + set_state(port, PD_STATE_HARD_RESET_SEND); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); + } else if (!strncasecmp(argv[2], "info", 4)) { + int i; + ccprintf("Hash "); + for (i = 0; i < PD_RW_HASH_SIZE / 4; i++) + ccprintf("%08x ", pd[port].dev_rw_hash[i]); + ccprintf("\nImage %s\n", system_image_copy_t_to_string( + pd[port].current_image)); + } else if (!strncasecmp(argv[2], "soft", 4)) { + set_state(port, PD_STATE_SOFT_RESET); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(port)); + } else if (!strncasecmp(argv[2], "swap", 4)) { + if (argc < 4) + return EC_ERROR_PARAM_COUNT; + + if (!strncasecmp(argv[3], "power", 5)) + pd_request_power_swap(port); + else if (!strncasecmp(argv[3], "data", 4)) + pd_request_data_swap(port); +#ifdef CONFIG_USBC_VCONN_SWAP + else if (!strncasecmp(argv[3], "vconn", 5)) + pd_request_vconn_swap(port); +#endif + else + return EC_ERROR_PARAM3; + } else if (!strncasecmp(argv[2], "ping", 4)) { + int enable; + + if (argc > 3) { + enable = strtoi(argv[3], &e, 10); + if (*e) + return EC_ERROR_PARAM3; + pd_ping_enable(port, enable); + } + + ccprintf("Pings %s\n", + (pd[port].flags & PD_FLAGS_PING_ENABLED) ? + "on" : "off"); + } else if (!strncasecmp(argv[2], "vdm", 3)) { + if (argc < 4) + return EC_ERROR_PARAM_COUNT; + + if (!strncasecmp(argv[3], "ping", 4)) { + uint32_t enable; + if (argc < 5) + return EC_ERROR_PARAM_COUNT; + enable = strtoi(argv[4], &e, 10); + if (*e) + return EC_ERROR_PARAM4; + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_PING_ENABLE, + &enable, 1); + } else if (!strncasecmp(argv[3], "curr", 4)) { + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_CURRENT, + NULL, 0); + } else if (!strncasecmp(argv[3], "vers", 4)) { + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_VERSION, + NULL, 0); + } else { + return EC_ERROR_PARAM_COUNT; + } +#if defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) + } else if (!strncasecmp(argv[2], "flash", 4)) { + return remote_flashing(argc, argv); +#endif + } else +#endif + if (!strncasecmp(argv[2], "state", 5)) { + ccprintf("Port C%d CC%d, %s - Role: %s-%s%s " + "State: %s, Flags: 0x%04x\n", + port, pd[port].polarity + 1, + pd_comm_is_enabled(port) ? "Ena" : "Dis", + pd[port].power_role == PD_ROLE_SOURCE ? "SRC" : "SNK", + pd[port].data_role == PD_ROLE_DFP ? "DFP" : "UFP", + (pd[port].flags & PD_FLAGS_VCONN_ON) ? "-VC" : "", + pd_state_names[pd[port].task_state], + pd[port].flags); + } else { + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(pd, command_pd, + "dualrole|dump|rwhashtable" + "|trysrc [0|1]\n\t " + "[tx|bist_rx|bist_tx|charger|clock|dev|disable|enable" + "|soft|hash|hard|ping|state|swap [power|data]|" + "vdm [ping | curr | vers]]", + "USB PD"); + +#ifdef HAS_TASK_HOSTCMD + +static int hc_pd_ports(struct host_cmd_handler_args *args) +{ + struct ec_response_usb_pd_ports *r = args->response; + r->num_ports = CONFIG_USB_PD_PORT_COUNT; + + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_PORTS, + hc_pd_ports, + EC_VER_MASK(0)); + +static const enum pd_dual_role_states dual_role_map[USB_PD_CTRL_ROLE_COUNT] = { + [USB_PD_CTRL_ROLE_TOGGLE_ON] = PD_DRP_TOGGLE_ON, + [USB_PD_CTRL_ROLE_TOGGLE_OFF] = PD_DRP_TOGGLE_OFF, + [USB_PD_CTRL_ROLE_FORCE_SINK] = PD_DRP_FORCE_SINK, + [USB_PD_CTRL_ROLE_FORCE_SOURCE] = PD_DRP_FORCE_SOURCE, + [USB_PD_CTRL_ROLE_FREEZE] = PD_DRP_FREEZE, +}; + +#ifdef CONFIG_USBC_SS_MUX +static const enum typec_mux typec_mux_map[USB_PD_CTRL_MUX_COUNT] = { + [USB_PD_CTRL_MUX_NONE] = TYPEC_MUX_NONE, + [USB_PD_CTRL_MUX_USB] = TYPEC_MUX_USB, + [USB_PD_CTRL_MUX_AUTO] = TYPEC_MUX_DP, + [USB_PD_CTRL_MUX_DP] = TYPEC_MUX_DP, + [USB_PD_CTRL_MUX_DOCK] = TYPEC_MUX_DOCK, +}; +#endif + +static int hc_usb_pd_control(struct host_cmd_handler_args *args) +{ + const struct ec_params_usb_pd_control *p = args->params; + struct ec_response_usb_pd_control_v1 *r_v1 = args->response; + struct ec_response_usb_pd_control *r = args->response; + + if (p->port >= CONFIG_USB_PD_PORT_COUNT) + return EC_RES_INVALID_PARAM; + + if (p->role >= USB_PD_CTRL_ROLE_COUNT || + p->mux >= USB_PD_CTRL_MUX_COUNT) + return EC_RES_INVALID_PARAM; + + if (p->role != USB_PD_CTRL_ROLE_NO_CHANGE) + pd_set_dual_role(dual_role_map[p->role]); + +#ifdef CONFIG_USBC_SS_MUX + if (p->mux != USB_PD_CTRL_MUX_NO_CHANGE) + usb_mux_set(p->port, typec_mux_map[p->mux], + typec_mux_map[p->mux] == TYPEC_MUX_NONE ? + USB_SWITCH_DISCONNECT : + USB_SWITCH_CONNECT, + pd_get_polarity(p->port)); +#endif /* CONFIG_USBC_SS_MUX */ + + if (p->swap == USB_PD_CTRL_SWAP_DATA) + pd_request_data_swap(p->port); +#ifdef CONFIG_USB_PD_DUAL_ROLE + else if (p->swap == USB_PD_CTRL_SWAP_POWER) + pd_request_power_swap(p->port); +#ifdef CONFIG_USBC_VCONN_SWAP + else if (p->swap == USB_PD_CTRL_SWAP_VCONN) + pd_request_vconn_swap(p->port); +#endif +#endif + + if (args->version == 0) { + r->enabled = pd_comm_is_enabled(p->port); + r->role = pd[p->port].power_role; + r->polarity = pd[p->port].polarity; + r->state = pd[p->port].task_state; + args->response_size = sizeof(*r); + } else { + r_v1->enabled = + (pd_comm_is_enabled(p->port) ? + PD_CTRL_RESP_ENABLED_COMMS : 0) | + (pd_is_connected(p->port) ? + PD_CTRL_RESP_ENABLED_CONNECTED : 0) | + ((pd[p->port].flags & PD_FLAGS_PREVIOUS_PD_CONN) ? + PD_CTRL_RESP_ENABLED_PD_CAPABLE : 0); + r_v1->role = + (pd[p->port].power_role ? PD_CTRL_RESP_ROLE_POWER : 0) | + (pd[p->port].data_role ? PD_CTRL_RESP_ROLE_DATA : 0) | + ((pd[p->port].flags & PD_FLAGS_VCONN_ON) ? + PD_CTRL_RESP_ROLE_VCONN : 0) | + ((pd[p->port].flags & PD_FLAGS_PARTNER_DR_POWER) ? + PD_CTRL_RESP_ROLE_DR_POWER : 0) | + ((pd[p->port].flags & PD_FLAGS_PARTNER_DR_DATA) ? + PD_CTRL_RESP_ROLE_DR_DATA : 0) | + ((pd[p->port].flags & PD_FLAGS_PARTNER_USB_COMM) ? + PD_CTRL_RESP_ROLE_USB_COMM : 0) | + ((pd[p->port].flags & PD_FLAGS_PARTNER_EXTPOWER) ? + PD_CTRL_RESP_ROLE_EXT_POWERED : 0); + r_v1->polarity = pd[p->port].polarity; + strzcpy(r_v1->state, + pd_state_names[pd[p->port].task_state], + sizeof(r_v1->state)); + args->response_size = sizeof(*r_v1); + } + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_CONTROL, + hc_usb_pd_control, + EC_VER_MASK(0) | EC_VER_MASK(1)); + +static int hc_remote_flash(struct host_cmd_handler_args *args) +{ + const struct ec_params_usb_pd_fw_update *p = args->params; + int port = p->port; + const uint32_t *data = &(p->size) + 1; + int i, size, rv = EC_RES_SUCCESS; + timestamp_t timeout; + + if (port >= CONFIG_USB_PD_PORT_COUNT) + return EC_RES_INVALID_PARAM; + + if (p->size + sizeof(*p) > args->params_size) + return EC_RES_INVALID_PARAM; + +#if defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \ + defined(CONFIG_BATTERY_PRESENT_GPIO) + /* + * Do not allow PD firmware update if no battery and this port + * is sinking power, because we will lose power. + */ + if (battery_is_present() != BP_YES && + charge_manager_get_active_charge_port() == port) + return EC_RES_UNAVAILABLE; +#endif + + /* + * Busy still with a VDM that host likely generated. 1 deep VDM queue + * so just return for retry logic on host side to deal with. + */ + if (pd[port].vdm_state > 0) + return EC_RES_BUSY; + + switch (p->cmd) { + case USB_PD_FW_REBOOT: + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0); + + /* + * Return immediately to free pending i2c bus. Host needs to + * manage this delay. + */ + return EC_RES_SUCCESS; + + case USB_PD_FW_FLASH_ERASE: + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_ERASE, NULL, 0); + + /* + * Return immediately. Host needs to manage delays here which + * can be as long as 1.2 seconds on 64KB RW flash. + */ + return EC_RES_SUCCESS; + + case USB_PD_FW_ERASE_SIG: + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0); + timeout.val = get_time().val + 500*MSEC; + break; + + case USB_PD_FW_FLASH_WRITE: + /* Data size must be a multiple of 4 */ + if (!p->size || p->size % 4) + return EC_RES_INVALID_PARAM; + + size = p->size / 4; + for (i = 0; i < size; i += VDO_MAX_SIZE - 1) { + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE, + data + i, MIN(size - i, VDO_MAX_SIZE - 1)); + timeout.val = get_time().val + 500*MSEC; + + /* Wait until VDM is done */ + while ((pd[port].vdm_state > 0) && + (get_time().val < timeout.val)) + task_wait_event(10*MSEC); + + if (pd[port].vdm_state > 0) + return EC_RES_TIMEOUT; + } + return EC_RES_SUCCESS; + + default: + return EC_RES_INVALID_PARAM; + break; + } + + /* Wait until VDM is done or timeout */ + while ((pd[port].vdm_state > 0) && (get_time().val < timeout.val)) + task_wait_event(50*MSEC); + + if ((pd[port].vdm_state > 0) || + (pd[port].vdm_state == VDM_STATE_ERR_TMOUT)) + rv = EC_RES_TIMEOUT; + else if (pd[port].vdm_state < 0) + rv = EC_RES_ERROR; + + return rv; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_FW_UPDATE, + hc_remote_flash, + EC_VER_MASK(0)); + +static int hc_remote_rw_hash_entry(struct host_cmd_handler_args *args) +{ + int i, idx = 0, found = 0; + const struct ec_params_usb_pd_rw_hash_entry *p = args->params; + static int rw_hash_next_idx; + + if (!p->dev_id) + return EC_RES_INVALID_PARAM; + + for (i = 0; i < RW_HASH_ENTRIES; i++) { + if (p->dev_id == rw_hash_table[i].dev_id) { + idx = i; + found = 1; + break; + } + } + if (!found) { + idx = rw_hash_next_idx; + rw_hash_next_idx = rw_hash_next_idx + 1; + if (rw_hash_next_idx == RW_HASH_ENTRIES) + rw_hash_next_idx = 0; + } + memcpy(&rw_hash_table[idx], p, sizeof(*p)); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_RW_HASH_ENTRY, + hc_remote_rw_hash_entry, + EC_VER_MASK(0)); + +static int hc_remote_pd_dev_info(struct host_cmd_handler_args *args) +{ + const uint8_t *port = args->params; + struct ec_params_usb_pd_rw_hash_entry *r = args->response; + + if (*port >= CONFIG_USB_PD_PORT_COUNT) + return EC_RES_INVALID_PARAM; + + r->dev_id = pd[*port].dev_id; + + if (r->dev_id) { + memcpy(r->dev_rw_hash, pd[*port].dev_rw_hash, + PD_RW_HASH_SIZE); + } + + r->current_image = pd[*port].current_image; + + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} + +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DEV_INFO, + hc_remote_pd_dev_info, + EC_VER_MASK(0)); + +#ifndef CONFIG_USB_PD_TCPC +#ifdef CONFIG_EC_CMD_PD_CHIP_INFO +static int hc_remote_pd_chip_info(struct host_cmd_handler_args *args) +{ + const struct ec_params_pd_chip_info *p = args->params; + struct ec_response_pd_chip_info *r = args->response, *info; + + if (p->port >= CONFIG_USB_PD_PORT_COUNT) + return EC_RES_INVALID_PARAM; + + if (tcpm_get_chip_info(p->port, p->renew, &info)) + return EC_RES_ERROR; + + memcpy(r, info, sizeof(*r)); + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PD_CHIP_INFO, + hc_remote_pd_chip_info, + EC_VER_MASK(0)); +#endif +#endif + +#ifdef CONFIG_USB_PD_ALT_MODE_DFP +static int hc_remote_pd_set_amode(struct host_cmd_handler_args *args) +{ + const struct ec_params_usb_pd_set_mode_request *p = args->params; + + if ((p->port >= CONFIG_USB_PD_PORT_COUNT) || (!p->svid) || (!p->opos)) + return EC_RES_INVALID_PARAM; + + switch (p->cmd) { + case PD_EXIT_MODE: + if (pd_dfp_exit_mode(p->port, p->svid, p->opos)) + pd_send_vdm(p->port, p->svid, + CMD_EXIT_MODE | VDO_OPOS(p->opos), NULL, 0); + else { + CPRINTF("Failed exit mode\n"); + return EC_RES_ERROR; + } + break; + case PD_ENTER_MODE: + if (pd_dfp_enter_mode(p->port, p->svid, p->opos)) + pd_send_vdm(p->port, p->svid, CMD_ENTER_MODE | + VDO_OPOS(p->opos), NULL, 0); + break; + default: + return EC_RES_INVALID_PARAM; + } + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_SET_AMODE, + hc_remote_pd_set_amode, + EC_VER_MASK(0)); +#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ + +#endif /* HAS_TASK_HOSTCMD */ + +#ifdef CONFIG_CMD_PD_CONTROL + +static int pd_control(struct host_cmd_handler_args *args) +{ + static int pd_control_disabled[CONFIG_USB_PD_PORT_COUNT]; + const struct ec_params_pd_control *cmd = args->params; + int enable = 0; + + if (cmd->chip >= CONFIG_USB_PD_PORT_COUNT) + return EC_RES_INVALID_PARAM; + + /* Always allow disable command */ + if (cmd->subcmd == PD_CONTROL_DISABLE) { + pd_control_disabled[cmd->chip] = 1; + return EC_RES_SUCCESS; + } + + if (pd_control_disabled[cmd->chip]) + return EC_RES_ACCESS_DENIED; + + if (cmd->subcmd == PD_SUSPEND) { + enable = 0; + } else if (cmd->subcmd == PD_RESUME) { + enable = 1; + } else if (cmd->subcmd == PD_RESET) { +#ifdef HAS_TASK_PDCMD + board_reset_pd_mcu(); +#else + return EC_RES_INVALID_COMMAND; +#endif + } else if (cmd->subcmd == PD_CHIP_ON && board_set_tcpc_power_mode) { + board_set_tcpc_power_mode(cmd->chip, 1); + return EC_RES_SUCCESS; + } else { + return EC_RES_INVALID_COMMAND; + } + + pd_comm_enable(cmd->chip, enable); + pd_set_suspend(cmd->chip, !enable); + + return EC_RES_SUCCESS; +} + +DECLARE_HOST_COMMAND(EC_CMD_PD_CONTROL, pd_control, EC_VER_MASK(0)); +#endif /* CONFIG_CMD_PD_CONTROL */ + +#endif /* CONFIG_COMMON_RUNTIME */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h b/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h new file mode 100644 index 00000000..982dcf37 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h @@ -0,0 +1,276 @@ +/* Copyright 2015 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 Power delivery port management - common header for TCPM drivers */ + +#ifndef __CROS_EC_USB_PD_TCPM_TCPM_H +#define __CROS_EC_USB_PD_TCPM_TCPM_H + +#include "tcpm_driver.h" +#include "usb_pd_tcpm.h" + +#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \ + !defined(CONFIG_USB_PD_DUAL_ROLE) +#error "DRP auto toggle requires board to have DRP support" +#error "Please upgrade your board configuration" +#endif + +#ifndef CONFIG_USB_PD_TCPC +extern const struct tcpc_config_t tcpc_config[]; + +/* I2C wrapper functions - get I2C port / slave addr from config struct. */ +int tcpc_write(int port, int reg, int val); +int tcpc_write16(int port, int reg, int val); +int tcpc_read(int port, int reg, int *val); +int tcpc_read16(int port, int reg, int *val); +int tcpc_xfer(int port, + const uint8_t *out, int out_size, + uint8_t *in, int in_size, + int flags); + +/* TCPM driver wrapper function */ +static inline int tcpm_init(int port) +{ + int rv; + + rv = tcpc_config[port].drv->init(port); + if (rv) + return rv; + + /* Board specific post TCPC init */ + if (board_tcpc_post_init) + rv = board_tcpc_post_init(port); + + return rv; +} + +static inline int tcpm_release(int port) +{ + return tcpc_config[port].drv->release(port); +} + +static inline int tcpm_get_cc(int port, int *cc1, int *cc2) +{ + return tcpc_config[port].drv->get_cc(port, cc1, cc2); +} + +static inline int tcpm_get_vbus_level(int port) +{ + return tcpc_config[port].drv->get_vbus_level(port); +} + +static inline int tcpm_select_rp_value(int port, int rp) +{ + return tcpc_config[port].drv->select_rp_value(port, rp); +} + +static inline int tcpm_set_cc(int port, int pull) +{ + return tcpc_config[port].drv->set_cc(port, pull); +} + +static inline int tcpm_set_polarity(int port, int polarity) +{ + return tcpc_config[port].drv->set_polarity(port, polarity); +} + +static inline int tcpm_set_vconn(int port, int enable) +{ + return tcpc_config[port].drv->set_vconn(port, enable); +} + +static inline int tcpm_set_msg_header(int port, int power_role, int data_role) +{ + return tcpc_config[port].drv->set_msg_header(port, power_role, + data_role); +} + +static inline int tcpm_set_rx_enable(int port, int enable) +{ + return tcpc_config[port].drv->set_rx_enable(port, enable); +} + +static inline int tcpm_get_message(int port, uint32_t *payload, int *head) +{ + return tcpc_config[port].drv->get_message(port, payload, head); +} + +static inline int tcpm_transmit(int port, enum tcpm_transmit_type type, + uint16_t header, const uint32_t *data) +{ + return tcpc_config[port].drv->transmit(port, type, header, data); +} + +static inline void tcpc_alert(int port) +{ + tcpc_config[port].drv->tcpc_alert(port); +} + +static inline void tcpc_discharge_vbus(int port, int enable) +{ + tcpc_config[port].drv->tcpc_discharge_vbus(port, enable); +} + +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +static inline int tcpm_auto_toggle_supported(int port) +{ + return !!tcpc_config[port].drv->drp_toggle; +} + +static inline int tcpm_set_drp_toggle(int port, int enable) +{ + return tcpc_config[port].drv->drp_toggle(port, enable); +} +#endif + +#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC +static inline int tcpc_i2c_read(const int port, const int addr, + const int reg, int *data) +{ + return tcpc_read(port, reg, data); +} + +static inline int tcpc_i2c_write(const int port, const int addr, + const int reg, int data) +{ + return tcpc_write(port, reg, data); +} +#endif + +static inline int tcpm_get_chip_info(int port, int renew, + struct ec_response_pd_chip_info **info) +{ + if (tcpc_config[port].drv->get_chip_info) + return tcpc_config[port].drv->get_chip_info(port, renew, info); + return EC_ERROR_UNIMPLEMENTED; +} + +#else + +/** + * Initialize TCPM driver and wait for TCPC readiness. + * + * @param port Type-C port number + * + * @return EC_SUCCESS or error + */ +int tcpm_init(int port); + +/** + * Read the CC line status. + * + * @param port Type-C port number + * @param cc1 pointer to CC status for CC1 + * @param cc2 pointer to CC status for CC2 + * + * @return EC_SUCCESS or error + */ +int tcpm_get_cc(int port, int *cc1, int *cc2); + +/** + * Read VBUS + * + * @param port Type-C port number + * + * @return 0 => VBUS not detected, 1 => VBUS detected + */ +int tcpm_get_vbus_level(int port); + +/** + * Set the value of the CC pull-up used when we are a source. + * + * @param port Type-C port number + * @param rp One of enum tcpc_rp_value + * + * @return EC_SUCCESS or error + */ +int tcpm_select_rp_value(int port, int rp); + +/** + * Set the CC pull resistor. This sets our role as either source or sink. + * + * @param port Type-C port number + * @param pull One of enum tcpc_cc_pull + * + * @return EC_SUCCESS or error + */ +int tcpm_set_cc(int port, int pull); + +/** + * Set polarity + * + * @param port Type-C port number + * @param polarity 0=> transmit on CC1, 1=> transmit on CC2 + * + * @return EC_SUCCESS or error + */ +int tcpm_set_polarity(int port, int polarity); + +/** + * Set Vconn. + * + * @param port Type-C port number + * @param polarity Polarity of the CC line to read + * + * @return EC_SUCCESS or error + */ +int tcpm_set_vconn(int port, int enable); + +/** + * Set PD message header to use for goodCRC + * + * @param port Type-C port number + * @param power_role Power role to use in header + * @param data_role Data role to use in header + * + * @return EC_SUCCESS or error + */ +int tcpm_set_msg_header(int port, int power_role, int data_role); + +/** + * Set RX enable flag + * + * @param port Type-C port number + * @enable true for enable, false for disable + * + * @return EC_SUCCESS or error + */ +int tcpm_set_rx_enable(int port, int enable); + +/** + * Read last received PD message. + * + * @param port Type-C port number + * @param payload Pointer to location to copy payload of message + * @param header of message + * + * @return EC_SUCCESS or error + */ +int tcpm_get_message(int port, uint32_t *payload, int *head); + +/** + * Transmit PD message + * + * @param port Type-C port number + * @param type Transmit type + * @param header Packet header + * @param cnt Number of bytes in payload + * @param data Payload + * + * @return EC_SUCCESS or error + */ +int tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header, + const uint32_t *data); + +/** + * TCPC is asserting alert + * + * @param port Type-C port number + */ +void tcpc_alert(int port); + +#endif + +#endif diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h b/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h new file mode 100644 index 00000000..947a88c9 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h @@ -0,0 +1,354 @@ +/* Copyright 2015 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 Power delivery port management */ + +#ifndef __CROS_EC_USB_PD_TCPM_H +#define __CROS_EC_USB_PD_TCPM_H + +/* List of common error codes that can be returned */ +enum ec_error_list { + /* Success - no error */ + EC_SUCCESS = 0, + /* Unknown error */ + EC_ERROR_UNKNOWN = 1, + /* Function not implemented yet */ + EC_ERROR_UNIMPLEMENTED = 2, + /* Overflow error; too much input provided. */ + EC_ERROR_OVERFLOW = 3, + /* Timeout */ + EC_ERROR_TIMEOUT = 4, + /* Invalid argument */ + EC_ERROR_INVAL = 5, + /* Already in use, or not ready yet */ + EC_ERROR_BUSY = 6, + /* Access denied */ + EC_ERROR_ACCESS_DENIED = 7, + /* Failed because component does not have power */ + EC_ERROR_NOT_POWERED = 8, + /* Failed because component is not calibrated */ + EC_ERROR_NOT_CALIBRATED = 9, + /* Failed because CRC error */ + EC_ERROR_CRC = 10, + /* Invalid console command param (PARAMn means parameter n is bad) */ + EC_ERROR_PARAM1 = 11, + EC_ERROR_PARAM2 = 12, + EC_ERROR_PARAM3 = 13, + EC_ERROR_PARAM4 = 14, + EC_ERROR_PARAM5 = 15, + EC_ERROR_PARAM6 = 16, + EC_ERROR_PARAM7 = 17, + EC_ERROR_PARAM8 = 18, + EC_ERROR_PARAM9 = 19, + /* Wrong number of params */ + EC_ERROR_PARAM_COUNT = 20, + /* Interrupt event not handled */ + EC_ERROR_NOT_HANDLED = 21, + /* Data has not changed */ + EC_ERROR_UNCHANGED = 22, + /* Memory allocation */ + EC_ERROR_MEMORY_ALLOCATION = 23, + + /* Verified boot errors */ + EC_ERROR_VBOOT_SIGNATURE = 0x1000, /* 4096 */ + EC_ERROR_VBOOT_SIG_MAGIC = 0x1001, + EC_ERROR_VBOOT_SIG_SIZE = 0x1002, + EC_ERROR_VBOOT_SIG_ALGORITHM = 0x1003, + EC_ERROR_VBOOT_HASH_ALGORITHM = 0x1004, + EC_ERROR_VBOOT_SIG_OFFSET = 0x1005, + EC_ERROR_VBOOT_DATA_SIZE = 0x1006, + + /* Verified boot key errors */ + EC_ERROR_VBOOT_KEY = 0x1100, + EC_ERROR_VBOOT_KEY_MAGIC = 0x1101, + EC_ERROR_VBOOT_KEY_SIZE = 0x1102, + + /* Verified boot data errors */ + EC_ERROR_VBOOT_DATA = 0x1200, + EC_ERROR_VBOOT_DATA_VERIFY = 0x1201, + + /* Module-internal error codes may use this range. */ + EC_ERROR_INTERNAL_FIRST = 0x10000, + EC_ERROR_INTERNAL_LAST = 0x1FFFF +}; + +/* Flags for i2c_xfer() */ +#define I2C_XFER_START (1 << 0) /* Start smbus session from idle state */ +#define I2C_XFER_STOP (1 << 1) /* Terminate smbus session with stop bit */ +#define I2C_XFER_SINGLE (I2C_XFER_START | I2C_XFER_STOP) /* One transaction */ + +/* Default retry count for transmitting */ +#define PD_RETRY_COUNT 3 + +/* Time to wait for TCPC to complete transmit */ +#define PD_T_TCPC_TX_TIMEOUT (100*MSEC) + +enum tcpc_cc_voltage_status { + TYPEC_CC_VOLT_OPEN = 0, + TYPEC_CC_VOLT_RA = 1, + TYPEC_CC_VOLT_RD = 2, + TYPEC_CC_VOLT_SNK_DEF = 5, + TYPEC_CC_VOLT_SNK_1_5 = 6, + TYPEC_CC_VOLT_SNK_3_0 = 7, +}; + +enum tcpc_cc_pull { + TYPEC_CC_RA = 0, + TYPEC_CC_RP = 1, + TYPEC_CC_RD = 2, + TYPEC_CC_OPEN = 3, +}; + +enum tcpc_rp_value { + TYPEC_RP_USB = 0, + TYPEC_RP_1A5 = 1, + TYPEC_RP_3A0 = 2, + TYPEC_RP_RESERVED = 3, +}; + +enum tcpm_transmit_type { + TCPC_TX_SOP = 0, + TCPC_TX_SOP_PRIME = 1, + TCPC_TX_SOP_PRIME_PRIME = 2, + TCPC_TX_SOP_DEBUG_PRIME = 3, + TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4, + TCPC_TX_HARD_RESET = 5, + TCPC_TX_CABLE_RESET = 6, + TCPC_TX_BIST_MODE_2 = 7 +}; + +enum tcpc_transmit_complete { + TCPC_TX_COMPLETE_SUCCESS = 0, + TCPC_TX_COMPLETE_DISCARDED = 1, + TCPC_TX_COMPLETE_FAILED = 2, +}; + +struct tcpm_drv { + /** + * Initialize TCPM driver and wait for TCPC readiness. + * + * @param port Type-C port number + * + * @return EC_SUCCESS or error + */ + int (*init)(int port); + + /** + * Release the TCPM hardware and disconnect the driver. + * Only .init() can be called after .release(). + * + * @param port Type-C port number + * + * @return EC_SUCCESS or error + */ + int (*release)(int port); + + /** + * Read the CC line status. + * + * @param port Type-C port number + * @param cc1 pointer to CC status for CC1 + * @param cc2 pointer to CC status for CC2 + * + * @return EC_SUCCESS or error + */ + int (*get_cc)(int port, int *cc1, int *cc2); + + /** + * Read VBUS + * + * @param port Type-C port number + * + * @return 0 => VBUS not detected, 1 => VBUS detected + */ + int (*get_vbus_level)(int port); + + /** + * Set the value of the CC pull-up used when we are a source. + * + * @param port Type-C port number + * @param rp One of enum tcpc_rp_value + * + * @return EC_SUCCESS or error + */ + int (*select_rp_value)(int port, int rp); + + /** + * Set the CC pull resistor. This sets our role as either source or sink. + * + * @param port Type-C port number + * @param pull One of enum tcpc_cc_pull + * + * @return EC_SUCCESS or error + */ + int (*set_cc)(int port, int pull); + + /** + * Set polarity + * + * @param port Type-C port number + * @param polarity 0=> transmit on CC1, 1=> transmit on CC2 + * + * @return EC_SUCCESS or error + */ + int (*set_polarity)(int port, int polarity); + + /** + * Set Vconn. + * + * @param port Type-C port number + * @param polarity Polarity of the CC line to read + * + * @return EC_SUCCESS or error + */ + int (*set_vconn)(int port, int enable); + + /** + * Set PD message header to use for goodCRC + * + * @param port Type-C port number + * @param power_role Power role to use in header + * @param data_role Data role to use in header + * + * @return EC_SUCCESS or error + */ + int (*set_msg_header)(int port, int power_role, int data_role); + + /** + * Set RX enable flag + * + * @param port Type-C port number + * @enable true for enable, false for disable + * + * @return EC_SUCCESS or error + */ + int (*set_rx_enable)(int port, int enable); + + /** + * Read last received PD message. + * + * @param port Type-C port number + * @param payload Pointer to location to copy payload of message + * @param header of message + * + * @return EC_SUCCESS or error + */ + int (*get_message)(int port, uint32_t *payload, int *head); + + /** + * Transmit PD message + * + * @param port Type-C port number + * @param type Transmit type + * @param header Packet header + * @param cnt Number of bytes in payload + * @param data Payload + * + * @return EC_SUCCESS or error + */ + int (*transmit)(int port, enum tcpm_transmit_type type, uint16_t header, + const uint32_t *data); + + /** + * TCPC is asserting alert + * + * @param port Type-C port number + */ + void (*tcpc_alert)(int port); + + /** + * Discharge PD VBUS on src/sink disconnect & power role swap + * + * @param port Type-C port number + * @param enable Discharge enable or disable + */ + void (*tcpc_discharge_vbus)(int port, int enable); + +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE + /** + * Enable TCPC auto DRP toggling. + * + * @param port Type-C port number + * @param enable 1: Enable 0: Disable + * + * @return EC_SUCCESS or error + */ + int (*drp_toggle)(int port, int enable); +#endif + + /** + * Get firmware version. + * + * @param port Type-C port number + * @param renew Force renewal + * @param info Pointer to pointer to PD chip info + * + * @return EC_SUCCESS or error + */ + int (*get_chip_info)(int port, int renew, + struct ec_response_pd_chip_info **info); +}; + +enum tcpc_alert_polarity { + TCPC_ALERT_ACTIVE_LOW, + TCPC_ALERT_ACTIVE_HIGH, +}; + +struct tcpc_config_t { + int i2c_host_port; + int i2c_slave_addr; + const struct tcpm_drv *drv; + enum tcpc_alert_polarity pol; +}; + +/** + * Returns the PD_STATUS_TCPC_ALERT_* mask corresponding to the TCPC ports + * that are currently asserting ALERT. + * + * @return PD_STATUS_TCPC_ALERT_* mask. + */ +uint16_t tcpc_get_alert_status(void); + +/** + * Optional, set the TCPC power mode. + * + * @param port Type-C port number + * @param mode 0: off/sleep, 1: on/awake + */ +void board_set_tcpc_power_mode(int port, int mode) __attribute__((weak)); + +/** + * Initialize TCPC. + * + * @param port Type-C port number + */ +void tcpc_init(int port); + +/** + * TCPC is asserting alert + * + * @param port Type-C port number + */ +void tcpc_alert_clear(int port); + +/** + * Run TCPC task once. This checks for incoming messages, processes + * any outgoing messages, and reads CC lines. + * + * @param port Type-C port number + * @param evt Event type that woke up this task + */ +int tcpc_run(int port, int evt); + +/** + * Initialize board specific TCPC functions post TCPC initialization. + * + * @param port Type-C port number + * + * @return EC_SUCCESS or error + */ +int board_tcpc_post_init(int port) __attribute__((weak)); + +#endif /* __CROS_EC_USB_PD_TCPM_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp b/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp new file mode 100644 index 00000000..b32d7075 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp @@ -0,0 +1,69 @@ +/* + * tcpm_driver.c + * + * Created: 11/11/2017 18:42:26 + * Author: jason + */ + +#include "tcpm_driver.h" +#include "I2C_Wrapper.hpp" +extern const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT]; +#define STATUS_OK 0 +/* I2C wrapper functions - get I2C port / slave addr from config struct. */ +int tcpc_write(int port, int reg, int val) { + + FRToSI2C::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) &val, + 1); + return STATUS_OK; +} + +int tcpc_write16(int port, int reg, int val) { + uint8_t data[2]; + data[0] = (0xFF) & val; + data[1] = (0xFF) & (val >> 8); + FRToSI2C::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, + 2); + return STATUS_OK; +} + +int tcpc_read(int port, int reg, int *val) { + uint8_t data[1]; + + FRToSI2C::Mem_Read(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, + 1); + + *val = data[0]; + + return STATUS_OK; +} + +int tcpc_read16(int port, int reg, int *val) { + uint8_t data[2]; + FRToSI2C::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, + 2); + + *val = data[0]; + *val |= (data[1] << 8); + + return STATUS_OK; +} + +int tcpc_xfer(int port, const uint8_t *out, int out_size, uint8_t *in, + int in_size, int flags) { + // Write out the I2C port to the given slave address + // Write out the out byte array to the device (sending a stop if the flag is set) + // Then issue a read from the device + + if (flags & I2C_XFER_STOP) { + //Issuing a stop between the requests + //Send as a Tx followed by a Rx + FRToSI2C::Transmit(tcpc_config[port].i2c_slave_addr, (uint8_t*)out, out_size); + FRToSI2C::Receive(tcpc_config[port].i2c_slave_addr, in, in_size); + } else { + //issue as a continious transmit & recieve + FRToSI2C::TransmitReceive(tcpc_config[port].i2c_slave_addr, (uint8_t*)out, + out_size, in, in_size); + } + + return STATUS_OK; +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.h b/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.h new file mode 100644 index 00000000..f3180f9f --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.h @@ -0,0 +1,22 @@ +/* + * tcpm_driver.h + * + * Created: 11/11/2017 18:42:39 + * Author: jason + */ + + +#ifndef TCPM_DRIVER_H_ +#define TCPM_DRIVER_H_ + +#include + +// USB-C Stuff +#include "USBC_TCPM/tcpm.h" +#include "FUSB302.h" +#define CONFIG_USB_PD_PORT_COUNT 1 +extern struct i2c_master_module i2c_master_instance; + + + +#endif /* TCPM_DRIVER_H_ */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp new file mode 100644 index 00000000..772bc52a --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp @@ -0,0 +1,414 @@ +/* + * usb_pd_driver.c + * + * Created: 11/11/2017 23:55:12 + * Author: jason + */ + +#include "usb_pd_driver.h" +#include "USBC_PD/usb_pd.h" +#include +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(t) (sizeof(t) / sizeof(t[0])) +#endif + +extern struct tc_module tc_instance; +extern uint32_t g_us_timestamp_upper_32bit; + +uint32_t pd_task_set_event(uint32_t event, int wait_for_reply) { + switch (event) { + case PD_EVENT_TX: + break; + default: + break; + } + return 0; +} + +const uint32_t pd_src_pdo[] = { PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), }; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); + +const uint32_t pd_snk_pdo[] = { PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), + PDO_FIXED(9000, 500, PDO_FIXED_FLAGS), PDO_FIXED(20000, 500, + PDO_FIXED_FLAGS), }; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); + +void pd_set_input_current_limit(int port, uint32_t max_ma, + uint32_t supply_voltage) { + +} + +int pd_is_valid_input_voltage(int mv) { + return 1; +} + +int pd_snk_is_vbus_provided(int port) { + return 1; +} + +timestamp_t get_time(void) { + timestamp_t t; + //TODO +// +// system_interrupt_enter_critical_section(); +// t.le.lo = tc_get_count_value(&tc_instance); +// t.le.hi = g_us_timestamp_upper_32bit; +// system_interrupt_leave_critical_section(); + + return t; +} + +void pd_power_supply_reset(int port) { + return; +} + +void pd_execute_data_swap(int port, int data_role) { + /* Do nothing */ +} + +int pd_check_data_swap(int port, int data_role) { + // Never allow data swap + return 0; +} + +int pd_check_power_swap(int port) { + /* Always refuse power swap */ + return 0; +} + +int pd_board_checks(void) { + return EC_SUCCESS; +} + +int pd_set_power_supply_ready(int port) { +#if 0 + /* Disable charging */ + gpio_set_level(GPIO_USB_C0_CHARGE_L, 1); + + /* Enable VBUS source */ + gpio_set_level(GPIO_USB_C0_5V_EN, 1); + + /* notify host of power info change */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +#endif // if 0 + return EC_SUCCESS; /* we are ready */ +} + +void pd_transition_voltage(int idx) { + /* No-operation: we are always 5V */ + +#if 0 + timestamp_t deadline; + uint32_t mv = src_pdo_charge[idx - 1].mv; + + /* Is this a transition to a new voltage? */ + if (charge_port_is_active() && vbus[CHG].mv != mv) { + /* + * Alter voltage limit on charge port, this should cause + * the port to select the desired PDO. + */ + pd_set_external_voltage_limit(CHG, mv); + + /* Wait for CHG transition */ + deadline.val = get_time().val + PD_T_PS_TRANSITION; + CPRINTS("Waiting for CHG port transition"); + while (charge_port_is_active() && + vbus[CHG].mv != mv && + get_time().val < deadline.val) + msleep(10); + + if (vbus[CHG].mv != mv) { + CPRINTS("Missed CHG transition, resetting DUT"); + pd_power_supply_reset(DUT); + return; + } + + CPRINTS("CHG transitioned"); + } + + vbus[DUT].mv = vbus[CHG].mv; + vbus[DUT].ma = vbus[CHG].ma; +#endif // if 0 + +} + +void pd_check_dr_role(int port, int dr_role, int flags) { +#if 0 + /* If UFP, try to switch to DFP */ + if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP) + pd_request_data_swap(port); +#endif +} + +void pd_check_pr_role(int port, int pr_role, int flags) { +#if 0 + /* + * If partner is dual-role power and dualrole toggling is on, consider + * if a power swap is necessary. + */ + if ((flags & PD_FLAGS_PARTNER_DR_POWER) && + pd_get_dual_role() == PD_DRP_TOGGLE_ON) { + /* + * If we are a sink and partner is not externally powered, then + * swap to become a source. If we are source and partner is + * externally powered, swap to become a sink. + */ + int partner_extpower = flags & PD_FLAGS_PARTNER_EXTPOWER; + + if ((!partner_extpower && pr_role == PD_ROLE_SINK) || + (partner_extpower && pr_role == PD_ROLE_SOURCE)) + pd_request_power_swap(port); + } +#endif // if 0 +} + +void pd_process_source_cap_callback(int port, int cnt, uint32_t *src_caps) { +// char str[256]; +// int i; +// uint32_t ma, mv, pdo; +// uint8_t old_display; +// +// old_display = display_screen; +// display_screen = SCREEN_POWER; +// memset(display_buffer[SCREEN_POWER], 0x00, DISP_MEM_SIZE); +// +// sprintf(str, "Has Power Delivery"); +// UG_PutString(0, 8, str); +// +// for (i = 0; i < cnt; i++) +// { +// pd_extract_pdo_power(src_caps[i], &ma, &mv); +// sprintf(str, "%5.2f V, %5.2f A", (float)mv/1000, (float)ma/1000); +// UG_PutString(0, 8*(i+2), str); +// } +// +// display_screen = old_display; +// display_needs_update = 1; + +//TODO Handle information on supported voltages? +} + +/* ----------------- Vendor Defined Messages ------------------ */ +/* Holds valid object position (opos) for entered mode */ +static int alt_mode[PD_AMODE_COUNT]; + +const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ +1, /* data caps as USB device */ +IDH_PTYPE_AMA, /* Alternate mode */ +1, /* supports alt modes */ +USB_VID_GOOGLE); + +const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); + +const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS, + CONFIG_USB_PD_IDENTITY_SW_VERS, 0, 0, 0, 0, /* SS[TR][12] */ + 0, /* Vconn power */ + 0, /* Vconn power required */ + 1, /* Vbus power required */ + AMA_USBSS_BBONLY /* USB SS support */); + +static int svdm_response_identity(int port, uint32_t *payload) { + payload[VDO_I(IDH)] = vdo_idh; + /* TODO(tbroch): Do we plan to obtain TID (test ID) */ + payload[VDO_I(CSTAT)] = VDO_CSTAT(0); + payload[VDO_I(PRODUCT)] = vdo_product; + payload[VDO_I(AMA)] = vdo_ama; + return VDO_I(AMA) + 1; +} + +static int svdm_response_svids(int port, uint32_t *payload) { + payload[1] = VDO_SVID(USB_SID_DISPLAYPORT, USB_VID_GOOGLE); + payload[2] = 0; + return 3; +} + +#define OPOS_DP 1 +#define OPOS_GFU 1 + +const uint32_t vdo_dp_modes[1] = { VDO_MODE_DP(0, /* UFP pin cfg supported : none */ +MODE_DP_PIN_C, /* DFP pin cfg supported */ +1, /* no usb2.0 signalling in AMode */ +CABLE_PLUG, /* its a plug */ +MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ +MODE_DP_SNK) /* Its a sink only */ +}; + +const uint32_t vdo_goog_modes[1] = { VDO_MODE_GOOGLE(MODE_GOOGLE_FU) }; + +static int svdm_response_modes(int port, uint32_t *payload) { + if (PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) { + memcpy(payload + 1, vdo_dp_modes, sizeof(vdo_dp_modes)); + return ARRAY_SIZE(vdo_dp_modes) + 1; + } else if (PD_VDO_VID(payload[0]) == USB_VID_GOOGLE) { + memcpy(payload + 1, vdo_goog_modes, sizeof(vdo_goog_modes)); + return ARRAY_SIZE(vdo_goog_modes) + 1; + } else { + return 0; /* nak */ + } +} + +static int dp_status(int port, uint32_t *payload) { + int opos = PD_VDO_OPOS(payload[0]); + int hpd = 0; // gpio_get_level(GPIO_DP_HPD); + if (opos != OPOS_DP) + return 0; /* nak */ + + payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ + (hpd == 1), /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ + 0, //gpio_get_level(GPIO_PD_SBU_ENABLE), + 0, /* power low */ + 0x2); + return 2; +} + +static int dp_config(int port, uint32_t *payload) { + if (PD_DP_CFG_DPON(payload[1])) + 0; //gpio_set_level(GPIO_PD_SBU_ENABLE, 1); + return 1; +} + +static int svdm_enter_mode(int port, uint32_t *payload) { + int rv = 0; /* will generate a NAK */ + char str[256]; + uint8_t old_display; + + /* SID & mode request is valid */ + if ((PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) + && (PD_VDO_OPOS(payload[0]) == OPOS_DP)) { + alt_mode[PD_AMODE_DISPLAYPORT] = OPOS_DP; + rv = 1; + //pd_log_event(PD_EVENT_VIDEO_DP_MODE, 0, 1, NULL); + } else if ((PD_VDO_VID(payload[0]) == USB_VID_GOOGLE) + && (PD_VDO_OPOS(payload[0]) == OPOS_GFU)) { + alt_mode[PD_AMODE_GOOGLE] = OPOS_GFU; + rv = 1; + } + +// if (rv) + /* + * If we failed initial mode entry we'll have enumerated the USB + * Billboard class. If so we should disconnect. + */ + //usb_disconnect(); +// old_display = display_screen; +// display_screen = SCREEN_ALTMODE; +// memset(display_buffer[SCREEN_ALTMODE], 0x00, DISP_MEM_SIZE); +// +// sprintf(str, "Requested Alt Mode"); +// UG_PutString(0, 8, str); +// +// display_screen = old_display; +// display_needs_update = 1; +//TODO handle alt mode ? + return rv; +} + +int pd_alt_mode(int port, uint16_t svid) { + if (svid == USB_SID_DISPLAYPORT) + return alt_mode[PD_AMODE_DISPLAYPORT]; + else if (svid == USB_VID_GOOGLE) + return alt_mode[PD_AMODE_GOOGLE]; + return 0; +} + +static int svdm_exit_mode(int port, uint32_t *payload) { + return 1; /* Must return ACK */ +} + +static struct amode_fx dp_fx = { .status = &dp_status, .config = &dp_config, }; + +const struct svdm_response svdm_rsp = { &svdm_response_identity, + &svdm_response_svids, &svdm_response_modes, &svdm_enter_mode, + &svdm_exit_mode, &dp_fx, }; + +int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { + int rsize; + + if (PD_VDO_VID(payload[0]) != USB_VID_GOOGLE || !alt_mode[PD_AMODE_GOOGLE]) + return 0; + + *rpayload = payload; + + rsize = pd_custom_flash_vdm(port, cnt, payload); + if (!rsize) { + int cmd = PD_VDO_CMD(payload[0]); + switch (cmd) { + case VDO_CMD_GET_LOG: + rsize = pd_vdm_get_log_entry(payload); + break; + default: + /* Unknown : do not answer */ + return 0; + } + } + + /* respond (positively) to the request */ + payload[0] |= VDO_SRC_RESPONDER; + + return rsize; +} + +int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload) { + static int flash_offset; + int rsize = 1; /* default is just VDM header returned */ + + switch (PD_VDO_CMD(payload[0])) { +#if 0 + case VDO_CMD_VERSION: + memcpy(payload + 1, ¤t_image_data.version, 24); + rsize = 7; + break; + case VDO_CMD_REBOOT: + /* ensure the power supply is in a safe state */ + pd_power_supply_reset(0); + system_reset(0); + break; + case VDO_CMD_READ_INFO: + /* copy info into response */ + pd_get_info(payload + 1); + rsize = 7; + break; + case VDO_CMD_FLASH_ERASE: + /* do not kill the code under our feet */ + if (system_get_image_copy() != SYSTEM_IMAGE_RO) + break; + pd_log_event(PD_EVENT_ACC_RW_ERASE, 0, 0, NULL); + flash_offset = CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_STORAGE_OFF; + flash_physical_erase(CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_STORAGE_OFF, CONFIG_RW_SIZE); + rw_flash_changed = 1; + break; + case VDO_CMD_FLASH_WRITE: + /* do not kill the code under our feet */ + if ((system_get_image_copy() != SYSTEM_IMAGE_RO) || + (flash_offset < CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_STORAGE_OFF)) + break; + flash_physical_write(flash_offset, 4*(cnt - 1), + (const char *)(payload+1)); + flash_offset += 4*(cnt - 1); + rw_flash_changed = 1; + break; + case VDO_CMD_ERASE_SIG: + /* this is not touching the code area */ + { + uint32_t zero = 0; + int offset; + /* zeroes the area containing the RSA signature */ + for (offset = FW_RW_END - RSANUMBYTES; + offset < FW_RW_END; offset += 4) + flash_physical_write(offset, 4, + (const char *)&zero); + } + break; +#endif // 0 + default: + /* Unknown : do not answer */ + return 0; + } + return rsize; +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h new file mode 100644 index 00000000..1cb14e60 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h @@ -0,0 +1,104 @@ +/* + * usb_pd_driver.h + * + * Created: 11/11/2017 23:55:25 + * Author: jason + */ + + +#ifndef USB_PD_DRIVER_H_ +#define USB_PD_DRIVER_H_ + +#include "USBC_PD/usb_pd.h" + +#include + +//#define CONFIG_BBRAM +#define CONFIG_CHARGE_MANAGER +//#define CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP +//#define CONFIG_USBC_VCONN_SWAP +#define CONFIG_USB_PD_ALT_MODE +//#define CONFIG_USB_PD_CHROMEOS +#define CONFIG_USB_PD_DUAL_ROLE +//#define CONFIG_USB_PD_GIVE_BACK +//#define CONFIG_USB_PD_SIMPLE_DFP +//#define CONFIG_USB_PD_TCPM_TCPCI +#define PD_PREFER_HIGH_VOLTAGE + +/* Default pull-up value on the USB-C ports when they are used as source. */ +#define CONFIG_USB_PD_PULLUP TYPEC_RP_USB + +/* Override PD_ROLE_DEFAULT in usb_pd.h */ +#define PD_ROLE_DEFAULT(port) (PD_ROLE_SINK) + +/* Don't automatically change roles */ +#undef CONFIG_USB_PD_INITIAL_DRP_STATE +#define CONFIG_USB_PD_INITIAL_DRP_STATE PD_DRP_FREEZE + +/* Prefer higher voltage, and more importantly, lower current */ +#define PD_PREFER_HIGH_VOLTAGE +//#define PD_PREFER_LOW_VOLTAGE + +/* board specific type-C power constants */ +/* + * delay to turn on the power supply max is ~16ms. + * delay to turn off the power supply max is about ~180ms. + */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 10000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 20000 /* us */ + +/* Define typical operating power and max power */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ +PDO_FIXED_COMM_CAP) + +/* USB configuration */ +#define CONFIG_USB_PID 0x502f // Stolen, so should change for anything useful +#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */ + +/* Optional features */ +#define CONFIG_USB_PD_IDENTITY_HW_VERS 1 +#define CONFIG_USB_PD_IDENTITY_SW_VERS 1 + +#define usleep(us) (delay_us(us)) +#define msleep(us) (delay_ms(us)) + +typedef union { + uint64_t val; + struct { + uint32_t lo; + uint32_t hi; + } le /* little endian words */; + } timestamp_t; + +uint32_t pd_task_set_event(uint32_t event, int wait_for_reply); +void pd_power_supply_reset(int port); + +// Get the current timestamp from the system timer. +timestamp_t get_time(void); + +/* Standard macros / definitions */ +#ifndef MAX +#define MAX(a, b) \ +({ \ + __typeof__(a) temp_a = (a); \ + __typeof__(b) temp_b = (b); \ + \ + temp_a > temp_b ? temp_a : temp_b; \ +}) +#endif +#ifndef MIN +#define MIN(a, b) \ +({ \ + __typeof__(a) temp_a = (a); \ + __typeof__(b) temp_b = (b); \ + \ + temp_a < temp_b ? temp_a : temp_b; \ +}) +#endif + +#endif /* USB_PD_DRIVER_H_ */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_tcpm.h b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_tcpm.h new file mode 100644 index 00000000..947a88c9 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_tcpm.h @@ -0,0 +1,354 @@ +/* Copyright 2015 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 Power delivery port management */ + +#ifndef __CROS_EC_USB_PD_TCPM_H +#define __CROS_EC_USB_PD_TCPM_H + +/* List of common error codes that can be returned */ +enum ec_error_list { + /* Success - no error */ + EC_SUCCESS = 0, + /* Unknown error */ + EC_ERROR_UNKNOWN = 1, + /* Function not implemented yet */ + EC_ERROR_UNIMPLEMENTED = 2, + /* Overflow error; too much input provided. */ + EC_ERROR_OVERFLOW = 3, + /* Timeout */ + EC_ERROR_TIMEOUT = 4, + /* Invalid argument */ + EC_ERROR_INVAL = 5, + /* Already in use, or not ready yet */ + EC_ERROR_BUSY = 6, + /* Access denied */ + EC_ERROR_ACCESS_DENIED = 7, + /* Failed because component does not have power */ + EC_ERROR_NOT_POWERED = 8, + /* Failed because component is not calibrated */ + EC_ERROR_NOT_CALIBRATED = 9, + /* Failed because CRC error */ + EC_ERROR_CRC = 10, + /* Invalid console command param (PARAMn means parameter n is bad) */ + EC_ERROR_PARAM1 = 11, + EC_ERROR_PARAM2 = 12, + EC_ERROR_PARAM3 = 13, + EC_ERROR_PARAM4 = 14, + EC_ERROR_PARAM5 = 15, + EC_ERROR_PARAM6 = 16, + EC_ERROR_PARAM7 = 17, + EC_ERROR_PARAM8 = 18, + EC_ERROR_PARAM9 = 19, + /* Wrong number of params */ + EC_ERROR_PARAM_COUNT = 20, + /* Interrupt event not handled */ + EC_ERROR_NOT_HANDLED = 21, + /* Data has not changed */ + EC_ERROR_UNCHANGED = 22, + /* Memory allocation */ + EC_ERROR_MEMORY_ALLOCATION = 23, + + /* Verified boot errors */ + EC_ERROR_VBOOT_SIGNATURE = 0x1000, /* 4096 */ + EC_ERROR_VBOOT_SIG_MAGIC = 0x1001, + EC_ERROR_VBOOT_SIG_SIZE = 0x1002, + EC_ERROR_VBOOT_SIG_ALGORITHM = 0x1003, + EC_ERROR_VBOOT_HASH_ALGORITHM = 0x1004, + EC_ERROR_VBOOT_SIG_OFFSET = 0x1005, + EC_ERROR_VBOOT_DATA_SIZE = 0x1006, + + /* Verified boot key errors */ + EC_ERROR_VBOOT_KEY = 0x1100, + EC_ERROR_VBOOT_KEY_MAGIC = 0x1101, + EC_ERROR_VBOOT_KEY_SIZE = 0x1102, + + /* Verified boot data errors */ + EC_ERROR_VBOOT_DATA = 0x1200, + EC_ERROR_VBOOT_DATA_VERIFY = 0x1201, + + /* Module-internal error codes may use this range. */ + EC_ERROR_INTERNAL_FIRST = 0x10000, + EC_ERROR_INTERNAL_LAST = 0x1FFFF +}; + +/* Flags for i2c_xfer() */ +#define I2C_XFER_START (1 << 0) /* Start smbus session from idle state */ +#define I2C_XFER_STOP (1 << 1) /* Terminate smbus session with stop bit */ +#define I2C_XFER_SINGLE (I2C_XFER_START | I2C_XFER_STOP) /* One transaction */ + +/* Default retry count for transmitting */ +#define PD_RETRY_COUNT 3 + +/* Time to wait for TCPC to complete transmit */ +#define PD_T_TCPC_TX_TIMEOUT (100*MSEC) + +enum tcpc_cc_voltage_status { + TYPEC_CC_VOLT_OPEN = 0, + TYPEC_CC_VOLT_RA = 1, + TYPEC_CC_VOLT_RD = 2, + TYPEC_CC_VOLT_SNK_DEF = 5, + TYPEC_CC_VOLT_SNK_1_5 = 6, + TYPEC_CC_VOLT_SNK_3_0 = 7, +}; + +enum tcpc_cc_pull { + TYPEC_CC_RA = 0, + TYPEC_CC_RP = 1, + TYPEC_CC_RD = 2, + TYPEC_CC_OPEN = 3, +}; + +enum tcpc_rp_value { + TYPEC_RP_USB = 0, + TYPEC_RP_1A5 = 1, + TYPEC_RP_3A0 = 2, + TYPEC_RP_RESERVED = 3, +}; + +enum tcpm_transmit_type { + TCPC_TX_SOP = 0, + TCPC_TX_SOP_PRIME = 1, + TCPC_TX_SOP_PRIME_PRIME = 2, + TCPC_TX_SOP_DEBUG_PRIME = 3, + TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4, + TCPC_TX_HARD_RESET = 5, + TCPC_TX_CABLE_RESET = 6, + TCPC_TX_BIST_MODE_2 = 7 +}; + +enum tcpc_transmit_complete { + TCPC_TX_COMPLETE_SUCCESS = 0, + TCPC_TX_COMPLETE_DISCARDED = 1, + TCPC_TX_COMPLETE_FAILED = 2, +}; + +struct tcpm_drv { + /** + * Initialize TCPM driver and wait for TCPC readiness. + * + * @param port Type-C port number + * + * @return EC_SUCCESS or error + */ + int (*init)(int port); + + /** + * Release the TCPM hardware and disconnect the driver. + * Only .init() can be called after .release(). + * + * @param port Type-C port number + * + * @return EC_SUCCESS or error + */ + int (*release)(int port); + + /** + * Read the CC line status. + * + * @param port Type-C port number + * @param cc1 pointer to CC status for CC1 + * @param cc2 pointer to CC status for CC2 + * + * @return EC_SUCCESS or error + */ + int (*get_cc)(int port, int *cc1, int *cc2); + + /** + * Read VBUS + * + * @param port Type-C port number + * + * @return 0 => VBUS not detected, 1 => VBUS detected + */ + int (*get_vbus_level)(int port); + + /** + * Set the value of the CC pull-up used when we are a source. + * + * @param port Type-C port number + * @param rp One of enum tcpc_rp_value + * + * @return EC_SUCCESS or error + */ + int (*select_rp_value)(int port, int rp); + + /** + * Set the CC pull resistor. This sets our role as either source or sink. + * + * @param port Type-C port number + * @param pull One of enum tcpc_cc_pull + * + * @return EC_SUCCESS or error + */ + int (*set_cc)(int port, int pull); + + /** + * Set polarity + * + * @param port Type-C port number + * @param polarity 0=> transmit on CC1, 1=> transmit on CC2 + * + * @return EC_SUCCESS or error + */ + int (*set_polarity)(int port, int polarity); + + /** + * Set Vconn. + * + * @param port Type-C port number + * @param polarity Polarity of the CC line to read + * + * @return EC_SUCCESS or error + */ + int (*set_vconn)(int port, int enable); + + /** + * Set PD message header to use for goodCRC + * + * @param port Type-C port number + * @param power_role Power role to use in header + * @param data_role Data role to use in header + * + * @return EC_SUCCESS or error + */ + int (*set_msg_header)(int port, int power_role, int data_role); + + /** + * Set RX enable flag + * + * @param port Type-C port number + * @enable true for enable, false for disable + * + * @return EC_SUCCESS or error + */ + int (*set_rx_enable)(int port, int enable); + + /** + * Read last received PD message. + * + * @param port Type-C port number + * @param payload Pointer to location to copy payload of message + * @param header of message + * + * @return EC_SUCCESS or error + */ + int (*get_message)(int port, uint32_t *payload, int *head); + + /** + * Transmit PD message + * + * @param port Type-C port number + * @param type Transmit type + * @param header Packet header + * @param cnt Number of bytes in payload + * @param data Payload + * + * @return EC_SUCCESS or error + */ + int (*transmit)(int port, enum tcpm_transmit_type type, uint16_t header, + const uint32_t *data); + + /** + * TCPC is asserting alert + * + * @param port Type-C port number + */ + void (*tcpc_alert)(int port); + + /** + * Discharge PD VBUS on src/sink disconnect & power role swap + * + * @param port Type-C port number + * @param enable Discharge enable or disable + */ + void (*tcpc_discharge_vbus)(int port, int enable); + +#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE + /** + * Enable TCPC auto DRP toggling. + * + * @param port Type-C port number + * @param enable 1: Enable 0: Disable + * + * @return EC_SUCCESS or error + */ + int (*drp_toggle)(int port, int enable); +#endif + + /** + * Get firmware version. + * + * @param port Type-C port number + * @param renew Force renewal + * @param info Pointer to pointer to PD chip info + * + * @return EC_SUCCESS or error + */ + int (*get_chip_info)(int port, int renew, + struct ec_response_pd_chip_info **info); +}; + +enum tcpc_alert_polarity { + TCPC_ALERT_ACTIVE_LOW, + TCPC_ALERT_ACTIVE_HIGH, +}; + +struct tcpc_config_t { + int i2c_host_port; + int i2c_slave_addr; + const struct tcpm_drv *drv; + enum tcpc_alert_polarity pol; +}; + +/** + * Returns the PD_STATUS_TCPC_ALERT_* mask corresponding to the TCPC ports + * that are currently asserting ALERT. + * + * @return PD_STATUS_TCPC_ALERT_* mask. + */ +uint16_t tcpc_get_alert_status(void); + +/** + * Optional, set the TCPC power mode. + * + * @param port Type-C port number + * @param mode 0: off/sleep, 1: on/awake + */ +void board_set_tcpc_power_mode(int port, int mode) __attribute__((weak)); + +/** + * Initialize TCPC. + * + * @param port Type-C port number + */ +void tcpc_init(int port); + +/** + * TCPC is asserting alert + * + * @param port Type-C port number + */ +void tcpc_alert_clear(int port); + +/** + * Run TCPC task once. This checks for incoming messages, processes + * any outgoing messages, and reads CC lines. + * + * @param port Type-C port number + * @param evt Event type that woke up this task + */ +int tcpc_run(int port, int evt); + +/** + * Initialize board specific TCPC functions post TCPC initialization. + * + * @param port Type-C port number + * + * @return EC_SUCCESS or error + */ +int board_tcpc_post_init(int port) __attribute__((weak)); + +#endif /* __CROS_EC_USB_PD_TCPM_H */ diff --git a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp index 3753a481..779ddc20 100644 --- a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp +++ b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp @@ -40,6 +40,9 @@ public: static bool probe(uint16_t DevAddress); static void Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size); + static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size); + static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, + uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); static void I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data); static uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg); From 34ae57ee58ea2cb1be3241f1bb505baa8fb5656c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 12 Jun 2020 21:10:03 +1000 Subject: [PATCH 03/53] Bitbang I2C setup + detect test --- workspace/TS100/Core/BSP/BSP.h | 4 +- workspace/TS100/Core/BSP/Miniware/I2CBB.cpp | 232 ++++ workspace/TS100/Core/BSP/Miniware/I2CBB.hpp | 42 + workspace/TS100/Core/BSP/Miniware/Pins.h | 4 + workspace/TS100/Core/BSP/Miniware/Power.cpp | 13 +- workspace/TS100/Core/BSP/Miniware/preRTOS.cpp | 3 +- .../FUSB302/{FUSB302.c => FUSB302.cpp} | 81 +- .../TS100/Core/Drivers/FUSB302/FUSB302.h | 47 +- ...{usb_pd_protocol.c => usb_pd_protocol.cpp} | 1042 ++++++-------- .../Core/Drivers/FUSB302/tcpm_driver.cpp | 25 +- .../Core/Drivers/FUSB302/usb_pd_driver.h | 6 +- .../TS100/Core/Drivers/FUSB302/usb_pd_tcpm.h | 354 ----- workspace/TS100/Core/Inc/main.hpp | 2 +- workspace/TS100/Core/Src/main.cpp | 5 +- workspace/TS100/Core/Threads/GUIThread.cpp | 1205 +++++++++-------- 15 files changed, 1435 insertions(+), 1630 deletions(-) create mode 100644 workspace/TS100/Core/BSP/Miniware/I2CBB.cpp create mode 100644 workspace/TS100/Core/BSP/Miniware/I2CBB.hpp rename workspace/TS100/Core/Drivers/FUSB302/{FUSB302.c => FUSB302.cpp} (93%) rename workspace/TS100/Core/Drivers/FUSB302/USBC_PD/{usb_pd_protocol.c => usb_pd_protocol.cpp} (84%) delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/usb_pd_tcpm.h diff --git a/workspace/TS100/Core/BSP/BSP.h b/workspace/TS100/Core/BSP/BSP.h index a558baad..8c8ce624 100644 --- a/workspace/TS100/Core/BSP/BSP.h +++ b/workspace/TS100/Core/BSP/BSP.h @@ -47,8 +47,10 @@ void reboot(); // If the user has programmed in a bootup logo, draw it to the screen from flash // Returns 1 if the logo was printed so that the unit waits for the timeout or button uint8_t showBootLogoIfavailable(); - +//delay wrapper for delay using the hardware timer (used before RTOS) void delay_ms(uint16_t count); +//Used to allow knowledge of if usb_pd is being used +uint8_t usb_pd_detect(); #ifdef __cplusplus } #endif diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp new file mode 100644 index 00000000..44db8cb2 --- /dev/null +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp @@ -0,0 +1,232 @@ +/* + * I2CBB.cpp + * + * Created on: 12 Jun 2020 + * Author: Ralim + */ + +#include + +#define SCL_HIGH() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_SET) +#define SCL_LOW() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_RESET) +#define SDA_HIGH() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_SET) +#define SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET) +#define SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0) +#define SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0) +#define I2C_DELAY() HAL_Delay(1); +void I2CBB::init() { + //Set GPIO's to output open drain + GPIO_InitTypeDef GPIO_InitStruct; + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + GPIO_InitStruct.Pin = SDA2_Pin | SCL2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(SDA2_GPIO_Port, &GPIO_InitStruct); + SDA_HIGH(); + SCL_HIGH(); +} + +bool I2CBB::probe(uint8_t address) { + start(); + bool ack = send(address); + stop(); + return ack; +} + +bool I2CBB::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, + uint16_t Size) { + start(); + bool ack = send(DevAddress | 1); + if (!ack) { + stop(); + return false; + } + ack = send(MemAddress); + if (!ack) { + stop(); + return false; + } + while (Size) { + pData[0] = read(Size > 1); + pData++; + Size--; + } + stop(); + return true; +} + +bool I2CBB::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, + uint16_t Size) { + start(); + bool ack = send(DevAddress); + if (!ack) { + stop(); + return false; + } + ack = send(MemAddress); + if (!ack) { + stop(); + return false; + } + while (Size) { + bool ack = send(pData[0]); + if (!ack) { + stop(); + return false; + } + pData++; + Size--; + } + stop(); + return true; +} + +void I2CBB::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { + start(); + bool ack = send(DevAddress); + if (!ack) { + stop(); + return; + } + while (Size) { + bool ack = send(pData[0]); + if (!ack) { + stop(); + return; + } + pData++; + Size--; + } + stop(); + +} + +void I2CBB::Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { + start(); + bool ack = send(DevAddress | 1); + if (!ack) { + stop(); + return; + } + while (Size) { + pData[0] = read(Size > 1); + pData++; + Size--; + } + stop(); +} + +void I2CBB::TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, + uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx) { + if (Size_tx == 0 && Size_rx == 0) + return; + if (Size_tx) { + start(); + bool ack = send(DevAddress); + if (!ack) { + stop(); + return; + } + while (Size_tx) { + bool ack = send(pData_tx[0]); + if (!ack) { + stop(); + return; + } + pData_tx++; + Size_tx--; + } + } + if (Size_rx) { + start(); + bool ack = send(DevAddress | 1); + if (!ack) { + stop(); + return; + } + while (Size_rx) { + pData_rx[0] = read(Size_rx > 1); + pData_rx++; + Size_rx--; + } + } + stop(); +} + +void I2CBB::start() { + /* I2C Start condition, data line goes low when clock is high */ + SCL_HIGH(); + SDA_HIGH(); + I2C_DELAY(); + SDA_LOW(); + I2C_DELAY(); + SCL_LOW(); + I2C_DELAY(); +} + +void I2CBB::stop() { + /* I2C Stop condition, clock goes high when data is low */ + SDA_LOW(); + I2C_DELAY(); + SCL_HIGH(); + I2C_DELAY(); + SDA_HIGH(); + I2C_DELAY(); +} + +bool I2CBB::send(uint8_t value) { + + for (uint8_t i = 0; i < 8; i++) { + write_bit(value & 0x80); // write the most-significant bit + value <<= 1; + } + + bool ack = read_bit()==0; + return ack; +} + +uint8_t I2CBB::read(bool ack) { + uint8_t B = 0; + + uint8_t i; + for (i = 0; i < 8; i++) { + B <<= 1; + B |= read_bit(); + } + + if (ack) + write_bit(0); + else + write_bit(1); + return B; +} + +uint8_t I2CBB::read_bit() { + uint8_t b; + + SDA_HIGH(); + I2C_DELAY(); + SCL_HIGH(); + I2C_DELAY(); + + if (SDA_READ()) + b = 1; + else + b = 0; + + SCL_LOW(); + return b; +} + +void I2CBB::write_bit(uint8_t val) { + if (val > 0) + SDA_HIGH(); + else + SDA_LOW(); + + I2C_DELAY(); + SCL_HIGH(); + I2C_DELAY(); + SCL_LOW(); +} diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp new file mode 100644 index 00000000..5be764d8 --- /dev/null +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp @@ -0,0 +1,42 @@ +/* + * I2CBB.hpp + * + * Created on: 12 Jun 2020 + * Author: Ralim + */ + +#ifndef BSP_MINIWARE_I2CBB_HPP_ +#define BSP_MINIWARE_I2CBB_HPP_ +#include "BSP.h" +#include "Setup.h" +#include "Pins.h" +/* + * Simple static I2C bit-bang class used on the TS80P + * SCL = PA5 + * SDA = PA1 + */ +class I2CBB { +public: + static void init(); + //Probe if device ACK's address or not + static bool probe(uint8_t address); + //Issues a complete 8bit register read + static bool Mem_Read(uint16_t DevAddress, uint16_t MemAddress, + uint8_t *pData, uint16_t Size); + //Implements a register write + static bool Mem_Write(uint16_t DevAddress, uint16_t MemAddress, + uint8_t *pData, uint16_t Size); + static void Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size); + static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size); + static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, + uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); +private: + static void start(); + static void stop(); + static bool send(uint8_t value); + static uint8_t read(bool ack); + static uint8_t read_bit(); + static void write_bit(uint8_t val); +}; + +#endif /* BSP_MINIWARE_I2CBB_HPP_ */ diff --git a/workspace/TS100/Core/BSP/Miniware/Pins.h b/workspace/TS100/Core/BSP/Miniware/Pins.h index 1f0ddfa9..ea30222f 100644 --- a/workspace/TS100/Core/BSP/Miniware/Pins.h +++ b/workspace/TS100/Core/BSP/Miniware/Pins.h @@ -77,6 +77,10 @@ #define SCL_GPIO_Port GPIOB #define SDA_Pin GPIO_PIN_7 #define SDA_GPIO_Port GPIOB +#define SCL2_Pin GPIO_PIN_5 +#define SCL2_GPIO_Port GPIOA +#define SDA2_Pin GPIO_PIN_1 +#define SDA2_GPIO_Port GPIOA #endif diff --git a/workspace/TS100/Core/BSP/Miniware/Power.cpp b/workspace/TS100/Core/BSP/Miniware/Power.cpp index 30386c83..c72e6207 100644 --- a/workspace/TS100/Core/BSP/Miniware/Power.cpp +++ b/workspace/TS100/Core/BSP/Miniware/Power.cpp @@ -2,10 +2,14 @@ #include "BSP_Power.h" #include "QC3.h" #include "Settings.h" +#include "FUSB302.h" +bool FUSB302_present = false; void power_probe() { // If TS80 probe for QC // If TS100 - noop #ifdef MODEL_TS80 + + startQC(systemSettings.voltageDiv); seekQC((systemSettings.cutoutSetting) ? 120 : 90, @@ -18,4 +22,11 @@ void power_check() { #ifdef MODEL_TS80 QC_resync(); #endif -} \ No newline at end of file +} +uint8_t usb_pd_detect(){ +#ifdef MODEL_TS80 + FUSB302_present=fusb302_detect(); + return FUSB302_present; +#endif + return false; +} diff --git a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp index 6a16c44f..674a850c 100644 --- a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp +++ b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp @@ -9,6 +9,7 @@ #include "BSP.h" #include "Setup.h" #include "Pins.h" +#include "I2CBB.hpp" void preRToSInit() { /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ @@ -18,5 +19,5 @@ void preRToSInit() { HAL_Delay(50); HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET); HAL_Delay(50); - + I2CBB::init(); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.c b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.cpp similarity index 93% rename from workspace/TS100/Core/Drivers/FUSB302/FUSB302.c rename to workspace/TS100/Core/Drivers/FUSB302/FUSB302.cpp index 2d9a0c3a..44739e8d 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.c +++ b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.cpp @@ -6,13 +6,16 @@ */ #include "FUSB302.h" -#include "usb_pd_tcpm.h" +#include "USBC_TCPM/usb_pd_tcpm.h" #include "USBC_TCPM/tcpm.h" #include "USBC_PD/usb_pd.h" - +#include +#include "cmsis_os.h" +#include "I2C_Wrapper.hpp" #define PACKET_IS_GOOD_CRC(head) (PD_HEADER_TYPE(head) == PD_CTRL_GOOD_CRC && \ PD_HEADER_CNT(head) == 0) - +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT] = { { 0, + fusb302_I2C_SLAVE_ADDR, &fusb302_tcpm_drv, TCPC_ALERT_ACTIVE_LOW }, }; static struct fusb302_chip_state { int cc_polarity; int vconn_enabled; @@ -44,7 +47,7 @@ static void fusb302_flush_rx_fifo(int port) { * then we'll have to keep a shadow of what this register * value should be so we don't clobber it here! */ - i2c_master_lock(tcpc_config[port].i2c_host_port); + tcpc_write(port, TCPC_REG_CONTROL1, TCPC_REG_CONTROL1_RX_FLUSH); } @@ -52,7 +55,6 @@ static void fusb302_flush_rx_fifo(int port) { static void fusb302_flush_tx_fifo(int port) { int reg; - i2c_master_lock(tcpc_config[port].i2c_host_port); tcpc_read(port, TCPC_REG_CONTROL0, ®); reg |= TCPC_REG_CONTROL0_TX_FLUSH; tcpc_write(port, TCPC_REG_CONTROL0, reg); @@ -62,7 +64,6 @@ static void fusb302_flush_tx_fifo(int port) { static void fusb302_auto_goodcrc_enable(int port, int enable) { int reg; - i2c_master_lock(tcpc_config[port].i2c_host_port); tcpc_read(port, TCPC_REG_SWITCHES1, ®); if (enable) @@ -101,8 +102,6 @@ static int measure_cc_pin_source(int port, int cc_measure) { int reg; int cc_lvl; - i2c_master_lock(tcpc_config[port].i2c_host_port); - /* Read status register */ tcpc_read(port, TCPC_REG_SWITCHES0, ®); /* Save current value */ @@ -181,8 +180,6 @@ static void detect_cc_pin_sink(int port, int *cc1, int *cc2) { int bc_lvl_cc1; int bc_lvl_cc2; - i2c_master_lock(tcpc_config[port].i2c_host_port); - /* * Measure CC1 first. */ @@ -317,7 +314,7 @@ static int fusb302_send_message(int port, uint16_t header, const uint32_t *data, buf[buf_pos++] = fusb302_TKN_TXON; /* burst write for speed! */ - i2c_master_lock(tcpc_config[port].i2c_host_port); + rv = tcpc_xfer(port, buf, buf_pos, 0, 0, I2C_XFER_SINGLE); return rv; @@ -328,8 +325,6 @@ static int fusb302_tcpm_select_rp_value(int port, int rp) { int rv; uint8_t vnc, rd; - i2c_master_lock(tcpc_config[port].i2c_host_port); - rv = tcpc_read(port, TCPC_REG_CONTROL0, ®); if (rv) return rv; @@ -373,8 +368,6 @@ static int fusb302_tcpm_init(int port) { /* all other variables assumed to default to 0 */ - i2c_master_lock(tcpc_config[port].i2c_host_port); - /* Restore default settings */ tcpc_write(port, TCPC_REG_RESET, TCPC_REG_RESET_SW_RESET); @@ -448,8 +441,6 @@ static int fusb302_tcpm_get_cc(int port, int *cc1, int *cc2) { static int fusb302_tcpm_set_cc(int port, int pull) { int reg; - i2c_master_lock(tcpc_config[port].i2c_host_port); - /* NOTE: FUSB302 toggles a single pull-up between CC1 and CC2 */ /* NOTE: FUSB302 Does not support Ra. */ switch (pull) { @@ -523,8 +514,6 @@ static int fusb302_tcpm_set_polarity(int port, int polarity) { /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */ int reg; - i2c_master_lock(tcpc_config[port].i2c_host_port); - tcpc_read(port, TCPC_REG_SWITCHES0, ®); /* clear VCONN switch bits */ @@ -590,8 +579,6 @@ static int fusb302_tcpm_set_vconn(int port, int enable) { tcpm_set_polarity(port, state[port].cc_polarity); } else { - i2c_master_lock(tcpc_config[port].i2c_host_port); - tcpc_read(port, TCPC_REG_SWITCHES0, ®); /* clear VCONN switch bits */ @@ -605,7 +592,8 @@ static int fusb302_tcpm_set_vconn(int port, int enable) { return 0; } -static int fusb302_tcpm_set_msg_header(int port, int power_role, int data_role) { +static int fusb302_tcpm_set_msg_header(int port, int power_role, + int data_role) { int reg; tcpc_read(port, TCPC_REG_SWITCHES1, ®); @@ -628,8 +616,6 @@ static int fusb302_tcpm_set_rx_enable(int port, int enable) { state[port].rx_enable = enable; - i2c_master_lock(tcpc_config[port].i2c_host_port); - /* Get current switch state */ tcpc_read(port, TCPC_REG_SWITCHES0, ®); @@ -678,8 +664,6 @@ static int fusb302_tcpm_set_rx_enable(int port, int enable) { static int fusb302_rx_fifo_is_empty(int port) { int reg, ret; - i2c_master_lock(tcpc_config[port].i2c_host_port); - ret = (!tcpc_read(port, TCPC_REG_STATUS1, ®)) && (reg & TCPC_REG_STATUS1_RX_EMPTY); @@ -705,7 +689,6 @@ static int fusb302_tcpm_get_message(int port, uint32_t *payload, int *head) { /* Read until we have a non-GoodCRC packet or an empty FIFO */ do { buf[0] = TCPC_REG_FIFOS; - i2c_master_lock(tcpc_config[port].i2c_host_port); /* * PART 1 OF BURST READ: Write in register address. @@ -794,10 +777,11 @@ static int fusb302_tcpm_transmit(int port, enum tcpm_transmit_type type, fusb302_send_message(port, header, data, buf, buf_pos); // wait for the GoodCRC to come back before we let the rest // of the code do stuff like change polarity and miss it - delay_us(600); - return; +// delay_us(600); + osDelay(1); + break; case TCPC_TX_HARD_RESET: - i2c_master_lock(tcpc_config[port].i2c_host_port); + /* Simply hit the SEND_HARD_RESET bit */ tcpc_read(port, TCPC_REG_CONTROL3, ®); reg |= TCPC_REG_CONTROL3_SEND_HARDRESET; @@ -805,7 +789,7 @@ static int fusb302_tcpm_transmit(int port, enum tcpm_transmit_type type, break; case TCPC_TX_BIST_MODE_2: - i2c_master_lock(tcpc_config[port].i2c_host_port); + /* Hit the BIST_MODE2 bit and start TX */ tcpc_read(port, TCPC_REG_CONTROL1, ®); reg |= TCPC_REG_CONTROL1_BIST_MODE2; @@ -836,7 +820,7 @@ static int fusb302_tcpm_get_vbus_level(int port) int reg; /* Read status register */ - i2c_master_lock(tcpc_config[port].i2c_host_port); + tcpc_read(port, TCPC_REG_STATUS0, ®); @@ -852,7 +836,6 @@ void fusb302_tcpc_alert(int port) { /* reading interrupt registers clears them */ - i2c_master_lock(tcpc_config[port].i2c_host_port); tcpc_read(port, TCPC_REG_INTERRUPT, &interrupt); tcpc_read(port, TCPC_REG_INTERRUPTA, &interrupta); tcpc_read(port, TCPC_REG_INTERRUPTB, &interruptb); @@ -924,8 +907,6 @@ void fusb302_tcpc_alert(int port) { void tcpm_set_bist_test_data(int port) { int reg; - i2c_master_lock(tcpc_config[port].i2c_host_port); - /* Read control3 register */ tcpc_read(port, TCPC_REG_CONTROL3, ®); @@ -937,16 +918,20 @@ void tcpm_set_bist_test_data(int port) { } -const struct tcpm_drv fusb302_tcpm_drv = { .init = &fusb302_tcpm_init, - .release = &fusb302_tcpm_release, .get_cc = &fusb302_tcpm_get_cc, -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - .get_vbus_level = &fusb302_tcpm_get_vbus_level, -#endif - .select_rp_value = &fusb302_tcpm_select_rp_value, .set_cc = - &fusb302_tcpm_set_cc, - .set_polarity = &fusb302_tcpm_set_polarity, .set_vconn = - &fusb302_tcpm_set_vconn, .set_msg_header = - &fusb302_tcpm_set_msg_header, .set_rx_enable = - &fusb302_tcpm_set_rx_enable, .get_message = - &fusb302_tcpm_get_message, .transmit = &fusb302_tcpm_transmit, - .tcpc_alert = &fusb302_tcpc_alert, }; +const struct tcpm_drv fusb302_tcpm_drv = { &fusb302_tcpm_init, //init + &fusb302_tcpm_release, //.release + &fusb302_tcpm_get_cc, //get_cc + NULL, //get_vbus_level + &fusb302_tcpm_select_rp_value, //select_rp_value + &fusb302_tcpm_set_cc, //set_cc + &fusb302_tcpm_set_polarity, //set_polarity + &fusb302_tcpm_set_vconn, //set_vconn + &fusb302_tcpm_set_msg_header, //set_msg_header + &fusb302_tcpm_set_rx_enable, //set_rx_enable + &fusb302_tcpm_get_message, //get_message + &fusb302_tcpm_transmit, //transmit + &fusb302_tcpc_alert, //tcpc_alert + NULL, //tcpc_discharge_vbus + NULL, //get_chip_info + }; + diff --git a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.h b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.h index b6404659..5a0455aa 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.h +++ b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.h @@ -9,7 +9,7 @@ #define fusb302_H #include -#include "usb_pd_tcpm.h" +#include "USBC_TCPM/usb_pd_tcpm.h" #include "USBC_PD/usb_pd.h" /* Chip Device ID - 302A or 302B */ @@ -18,13 +18,13 @@ /* I2C slave address varies by part number */ /* FUSB302BUCX / FUSB302BMPX */ -#define fusb302_I2C_SLAVE_ADDR 0x22 // 7-bit address for Arduino +#define fusb302_I2C_SLAVE_ADDR 0x22<<1 // 7-bit address /* FUSB302B01MPX */ -#define fusb302_I2C_SLAVE_ADDR_B01 0x23 +#define fusb302_I2C_SLAVE_ADDR_B01 0x23<<1 /* FUSB302B10MPX */ -#define fusb302_I2C_SLAVE_ADDR_B10 0x24 +#define fusb302_I2C_SLAVE_ADDR_B10 0x24<<1 /* FUSB302B11MPX */ -#define fusb302_I2C_SLAVE_ADDR_B11 0x25 +#define fusb302_I2C_SLAVE_ADDR_B11 0x25<<1 /* Default retry count for transmitting */ #define PD_RETRY_COUNT 3 @@ -210,41 +210,8 @@ enum fusb302_txfifo_tokens { extern const struct tcpm_drv fusb302_tcpm_drv; -/* -// Common methods for TCPM implementations -int fusb302_init(void); -int fusb302_get_cc(int *cc1, int *cc2); -int fusb302_get_vbus_level(void); -int fusb302_select_rp_value(int rp); -int fusb302_set_cc(int pull); -int fusb302_set_polarity(int polarity); -int fusb302_set_vconn(int enable); -int fusb302_set_msg_header(int power_role, int data_role); -int fusb302_set_rx_enable(int enable); -int fusb302_get_message(uint32_t *payload, int *head); -int fusb302_transmit(enum tcpm_transmit_type type, - uint16_t header, const uint32_t *data); -//int alert(void); -void fusb302_pd_reset(int port); -void fusb302_auto_goodcrc_enable(int enable); -int fusb302_convert_bc_lvl(int bc_lvl); -void fusb302_detect_cc_pin_source_manual(int *cc1_lvl, int *cc2_lvl); -int fusb302_measure_cc_pin_source(int cc_measure); -void fusb302_detect_cc_pin_sink(int *cc1, int *cc2); -int fusb302_send_message(uint16_t header, const uint32_t *data, - uint8_t *buf, int buf_pos); -void fusb302_flush_rx_fifo(int port); -void fusb302_flush_tx_fifo(int port); -void fusb302_clear_int_pin(void); -void fusb302_set_bist_test_data(void); -int fusb302_get_chip_id(int *id); -uint32_t fusb302_get_interrupt_reason(void); -int fusb302_tcpc_write(int reg, int val); -int fusb302_tcpc_read(int reg, int *val); -int fusb302_tcpc_xfer(const uint8_t *out, - int out_size, uint8_t *in, - int in_size, int flags); -*/ +//returns 1 if the FUSB302 is on the I2C bus +uint8_t fusb302_detect(); #endif /* fusb302_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.c b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.cpp similarity index 84% rename from workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.c rename to workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.cpp index d08379ba..1b1cc383 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.c +++ b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.cpp @@ -4,11 +4,11 @@ */ #include "usb_pd.h" -#include "usb_pd_tcpm.h" +#include "USBC_TCPM/usb_pd_tcpm.h" #include "USBC_TCPM/tcpm.h" #include "usb_pd_driver.h" #include - +#include #ifdef CONFIG_COMMON_RUNTIME #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) @@ -42,7 +42,7 @@ static uint8_t pd_comm_enabled[CONFIG_USB_PD_PORT_COUNT]; #else /* CONFIG_COMMON_RUNTIME */ #define CPRINTF(format, args...) #define CPRINTS(format, args...) -static const int debug_level; +static const int debug_level=0; #endif #ifdef CONFIG_USB_PD_DUAL_ROLE @@ -116,7 +116,7 @@ static const uint8_t vdo_ver[] = { static int head; static int port = TASK_ID_TO_PD_PORT(task_get_current()); static uint32_t payload[7]; -static int timeout = 10*MSEC; +static int timeout = 10 * MSEC; static int cc1, cc2; static int res, incoming_packet = 0; static int hard_reset_count = 0; @@ -248,8 +248,7 @@ BUILD_ASSERT(ARRAY_SIZE(pd_state_names) == PD_STATE_COUNT); static struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES]; #endif -int pd_comm_is_enabled(int port) -{ +int pd_comm_is_enabled(int port) { #ifdef CONFIG_COMMON_RUNTIME return pd_comm_enabled[port]; #else @@ -257,10 +256,8 @@ int pd_comm_is_enabled(int port) #endif } -static inline void set_state_timeout(int port, - uint64_t timeout, - enum pd_states timeout_state) -{ +static inline void set_state_timeout(int port, uint64_t timeout, + enum pd_states timeout_state) { pd[port].timeout = timeout; pd[port].timeout_state = timeout_state; } @@ -278,8 +275,7 @@ int pd_get_vdo_ver(int port) #endif /* Return flag for pd state is connected */ -int pd_is_connected(int port) -{ +int pd_is_connected(int port) { if (pd[port].task_state == PD_STATE_DISABLED) return 0; @@ -289,31 +285,26 @@ int pd_is_connected(int port) #endif return DUAL_ROLE_IF_ELSE(port, - /* sink */ - pd[port].task_state != PD_STATE_SNK_DISCONNECTED && - pd[port].task_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE, - /* source */ - pd[port].task_state != PD_STATE_SRC_DISCONNECTED && - pd[port].task_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE); + /* sink */ + pd[port].task_state != PD_STATE_SNK_DISCONNECTED && pd[port].task_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE, + /* source */ + pd[port].task_state != PD_STATE_SRC_DISCONNECTED && pd[port].task_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE); } /* * Return true if partner port is a DTS or TS capable of entering debug * mode (eg. is presenting Rp/Rp or Rd/Rd). */ -int pd_ts_dts_plugged(int port) -{ +int pd_ts_dts_plugged(int port) { return pd[port].flags & PD_FLAGS_TS_DTS_PARTNER; } #ifdef CONFIG_USB_PD_DUAL_ROLE -void pd_vbus_low(int port) -{ +void pd_vbus_low(int port) { pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW; } -static inline int pd_is_vbus_present(int port) -{ +static inline int pd_is_vbus_present(int port) { #ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC return tcpm_get_vbus_level(port); #else @@ -322,14 +313,13 @@ static inline int pd_is_vbus_present(int port) } #endif -static inline void set_state(int port, enum pd_states next_state) -{ +static inline void set_state(int port, enum pd_states next_state) { enum pd_states last_state = pd[port].task_state; #ifdef CONFIG_LOW_POWER_IDLE int i; #endif - set_state_timeout(port, 0, 0); + set_state_timeout(port, 0, PD_STATE_DISABLED); pd[port].task_state = next_state; if (last_state == next_state) @@ -343,14 +333,14 @@ static inline void set_state(int port, enum pd_states next_state) #endif /* Ignore dual-role toggling between sink and source */ - if ((last_state == PD_STATE_SNK_DISCONNECTED && - next_state == PD_STATE_SRC_DISCONNECTED) || - (last_state == PD_STATE_SRC_DISCONNECTED && - next_state == PD_STATE_SNK_DISCONNECTED)) + if ((last_state == PD_STATE_SNK_DISCONNECTED + && next_state == PD_STATE_SRC_DISCONNECTED) + || (last_state == PD_STATE_SRC_DISCONNECTED + && next_state == PD_STATE_SNK_DISCONNECTED)) return; - if (next_state == PD_STATE_SRC_DISCONNECTED || - next_state == PD_STATE_SNK_DISCONNECTED) { + if (next_state == PD_STATE_SRC_DISCONNECTED + || next_state == PD_STATE_SNK_DISCONNECTED) { /* Clear the input current limit */ pd_set_input_current_limit(port, 0, 0); #ifdef CONFIG_CHARGE_MANAGER @@ -418,14 +408,13 @@ static inline void set_state(int port, enum pd_states next_state) if (debug_level >= 1) CPRINTF("C%d st%d %s\n", port, next_state, - pd_state_names[next_state]); + pd_state_names[next_state]); else CPRINTF("C%d st%d\n", port, next_state); } /* increment message ID counter */ -static void inc_id(int port) -{ +static void inc_id(int port) { pd[port].msg_id = (pd[port].msg_id + 1) & PD_MESSAGE_ID_COUNT; } @@ -442,8 +431,7 @@ static inline void pd_ca_reset(int port) } #endif -void pd_transmit_complete(int port, int status) -{ +void pd_transmit_complete(int port, int status) { if (status == TCPC_TX_COMPLETE_SUCCESS) inc_id(port); @@ -452,9 +440,8 @@ void pd_transmit_complete(int port, int status) pd_task_set_event(PD_EVENT_TX, 0); } -static int pd_transmit(int port, enum tcpm_transmit_type type, - uint16_t header, const uint32_t *data) -{ +static int pd_transmit(int port, enum tcpm_transmit_type type, uint16_t header, + const uint32_t *data) { int evt; /* If comms are disabled, do not transmit, return error */ @@ -518,7 +505,6 @@ static int pd_transmit(int port, enum tcpm_transmit_type type, /* Wait until TX is complete */ // Would wait, except that we're making tcpm_transmit blocking //evt = task_wait_event_mask(PD_EVENT_TX, PD_T_TCPC_TX_TIMEOUT); - #ifdef CONFIG_USB_PD_REV30 /* * If the source just completed a transmit, tell @@ -533,7 +519,7 @@ static int pd_transmit(int port, enum tcpm_transmit_type type, // removing task-based stuff from the library //if (evt & TASK_EVENT_TIMER) - // return -1; + // return -1; /* TODO: give different error condition for failed vs discarded */ return pd[port].tx_status == TCPC_TX_COMPLETE_SUCCESS ? 1 : -1; @@ -562,18 +548,15 @@ static void pd_ca_send_pending(int port) } #endif -static void pd_update_roles(int port) -{ +static void pd_update_roles(int port) { /* Notify TCPC of role update */ tcpm_set_msg_header(port, pd[port].power_role, pd[port].data_role); } -static int send_control(int port, int type) -{ +static int send_control(int port, int type) { int bit_len; - uint16_t header = PD_HEADER(type, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, 0, - pd_get_rev(port), 0); + uint16_t header = PD_HEADER(type, pd[port].power_role, pd[port].data_role, + pd[port].msg_id, 0, pd_get_rev(port), 0); bit_len = pd_transmit(port, TCPC_TX_SOP, header, NULL); if (debug_level >= 2) @@ -582,8 +565,7 @@ static int send_control(int port, int type) return bit_len; } -static int send_source_cap(int port) -{ +static int send_source_cap(int port) { int bit_len; #if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) @@ -598,12 +580,11 @@ static int send_source_cap(int port) if (src_pdo_cnt == 0) /* No source capabilities defined, sink only */ header = PD_HEADER(PD_CTRL_REJECT, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, 0, - pd_get_rev(port), 0); + pd[port].data_role, pd[port].msg_id, 0, pd_get_rev(port), 0); else header = PD_HEADER(PD_DATA_SOURCE_CAP, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, src_pdo_cnt, - pd_get_rev(port), 0); + pd[port].data_role, pd[port].msg_id, src_pdo_cnt, + pd_get_rev(port), 0); bit_len = pd_transmit(port, TCPC_TX_SOP, header, src_pdo); if (debug_level >= 2) @@ -768,8 +749,7 @@ static int send_battery_status(int port, uint32_t *payload) #endif #ifdef CONFIG_USB_PD_DUAL_ROLE -static void send_sink_cap(int port) -{ +static void send_sink_cap(int port) { int bit_len; uint16_t header = PD_HEADER(PD_DATA_SINK_CAP, pd[port].power_role, pd[port].data_role, pd[port].msg_id, pd_snk_pdo_cnt, @@ -780,12 +760,10 @@ static void send_sink_cap(int port) CPRINTF("snkCAP>%d\n", bit_len); } -static int send_request(int port, uint32_t rdo) -{ +static int send_request(int port, uint32_t rdo) { int bit_len; uint16_t header = PD_HEADER(PD_DATA_REQUEST, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, 1, - pd_get_rev(port), 0); + pd[port].data_role, pd[port].msg_id, 1, pd_get_rev(port), 0); bit_len = pd_transmit(port, TCPC_TX_SOP, header, &rdo); if (debug_level >= 2) @@ -833,8 +811,7 @@ static int send_bist_cmd(int port) #endif static void queue_vdm(int port, uint32_t *header, const uint32_t *data, - int data_cnt) -{ + int data_cnt) { pd[port].vdo_count = data_cnt + 1; pd[port].vdo_data[0] = header[0]; memcpy(&pd[port].vdo_data[1], data, sizeof(uint32_t) * data_cnt); @@ -842,8 +819,7 @@ static void queue_vdm(int port, uint32_t *header, const uint32_t *data, pd[port].vdm_state = VDM_STATE_READY; } -static void handle_vdm_request(int port, int cnt, uint32_t *payload) -{ +static void handle_vdm_request(int port, int cnt, uint32_t *payload) { int rlen = 0; uint32_t *rdata; @@ -851,10 +827,10 @@ static void handle_vdm_request(int port, int cnt, uint32_t *payload) /* If UFP responded busy retry after timeout */ if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_BUSY) { pd[port].vdm_timeout.val = get_time().val + - PD_T_VDM_BUSY; + PD_T_VDM_BUSY; pd[port].vdm_state = VDM_STATE_WAIT_RSP_BUSY; pd[port].vdo_retry = (payload[0] & ~VDO_CMDT_MASK) | - CMDT_INIT; + CMDT_INIT; return; } else { pd[port].vdm_state = VDM_STATE_DONE; @@ -872,11 +848,10 @@ static void handle_vdm_request(int port, int cnt, uint32_t *payload) } if (debug_level >= 2) CPRINTF("Unhandled VDM VID %04x CMD %04x\n", - PD_VDO_VID(payload[0]), payload[0] & 0xFFFF); + PD_VDO_VID(payload[0]), payload[0] & 0xFFFF); } -void pd_execute_hard_reset(int port) -{ +void pd_execute_hard_reset(int port) { if (pd[port].last_state == PD_STATE_HARD_RESET_SEND) CPRINTF("C%d HARD RST TX\n", port); else @@ -902,8 +877,8 @@ void pd_execute_hard_reset(int port) * If we are swapping to a source and have changed to Rp, restore back * to Rd and turn off vbus to match our power_role. */ - if (pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY || - pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE) { + if (pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY + || pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE) { tcpm_set_cc(port, TYPEC_CC_RD); pd_power_supply_reset(port); } @@ -928,16 +903,15 @@ void pd_execute_hard_reset(int port) set_state(port, PD_STATE_SRC_HARD_RESET_RECOVER); } -static void execute_soft_reset(int port) -{ +static void execute_soft_reset(int port) { pd[port].msg_id = 0; - set_state(port, DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_DISCOVERY, - PD_STATE_SRC_DISCOVERY)); + set_state(port, + DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_DISCOVERY, + PD_STATE_SRC_DISCOVERY)); CPRINTF("C%d Soft Rst\n", port); } -void pd_soft_reset(void) -{ +void pd_soft_reset(void) { int i; for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; ++i) @@ -953,8 +927,7 @@ void pd_soft_reset(void) * Request desired charge voltage from source. * Returns EC_SUCCESS on success or non-zero on failure. */ -static int pd_send_request_msg(int port, int always_send_request) -{ +static int pd_send_request_msg(int port, int always_send_request) { uint32_t rdo, curr_limit, supply_voltage; int res; @@ -980,7 +953,7 @@ static int pd_send_request_msg(int port, int always_send_request) * request the max voltage, then select vSafe5V */ res = pd_build_request(port, &rdo, &curr_limit, &supply_voltage, - charging && max_request_allowed ? + charging && max_request_allowed ? PD_REQUEST_MAX : PD_REQUEST_VSAFE5V); if (res != EC_SUCCESS) @@ -1002,10 +975,9 @@ static int pd_send_request_msg(int port, int always_send_request) } CPRINTF("Req C%d [%d] %dmV %dmA", port, RDO_POS(rdo), - supply_voltage, curr_limit); + supply_voltage, curr_limit); if (rdo & RDO_CAP_MISMATCH) - CPRINTF(" Mismatch"); - CPRINTF("\n"); + CPRINTF(" Mismatch"); CPRINTF("\n"); pd[port].curr_limit = curr_limit; pd[port].supply_voltage = supply_voltage; @@ -1018,8 +990,7 @@ static int pd_send_request_msg(int port, int always_send_request) } #endif -static void pd_update_pdo_flags(int port, uint32_t pdo) -{ +static void pd_update_pdo_flags(int port, uint32_t pdo) { #ifdef CONFIG_CHARGE_MANAGER #ifdef CONFIG_USB_PD_ALT_MODE_DFP int charge_whitelisted = @@ -1065,19 +1036,17 @@ static void pd_update_pdo_flags(int port, uint32_t pdo) * charging white-list. */ /* - if (!(pd[port].flags & PD_FLAGS_PARTNER_DR_POWER) || - (pd[port].flags & PD_FLAGS_PARTNER_EXTPOWER) || - charge_whitelisted) - charge_manager_update_dualrole(port, CAP_DEDICATED); - else - charge_manager_update_dualrole(port, CAP_DUALROLE); - */ + if (!(pd[port].flags & PD_FLAGS_PARTNER_DR_POWER) || + (pd[port].flags & PD_FLAGS_PARTNER_EXTPOWER) || + charge_whitelisted) + charge_manager_update_dualrole(port, CAP_DEDICATED); + else + charge_manager_update_dualrole(port, CAP_DUALROLE); + */ #endif } -static void handle_data_request(int port, uint16_t head, - uint32_t *payload) -{ +static void handle_data_request(int port, uint16_t head, uint32_t *payload) { int type = PD_HEADER_TYPE(head); int cnt = PD_HEADER_CNT(head); @@ -1085,12 +1054,12 @@ static void handle_data_request(int port, uint16_t head, #ifdef CONFIG_USB_PD_DUAL_ROLE case PD_DATA_SOURCE_CAP: if ((pd[port].task_state == PD_STATE_SNK_DISCOVERY) - || (pd[port].task_state == PD_STATE_SNK_TRANSITION) + || (pd[port].task_state == PD_STATE_SNK_TRANSITION) #ifdef CONFIG_USB_PD_VBUS_DETECT_NONE || (pd[port].task_state == PD_STATE_SNK_HARD_RESET_RECOVER) #endif - || (pd[port].task_state == PD_STATE_SNK_READY)) { + || (pd[port].task_state == PD_STATE_SNK_READY)) { #ifdef CONFIG_USB_PD_REV30 /* * Only adjust sink rev if source rev is higher. @@ -1108,7 +1077,7 @@ static void handle_data_request(int port, uint16_t head, /* Source will resend source cap on failure */ pd_send_request_msg(port, 1); - + // We call the callback after we send the request // because the timing on Request seems to be sensitive // User code can take the time until PS_RDY to do stuff @@ -1162,18 +1131,17 @@ static void handle_data_request(int port, uint16_t head, break; case PD_DATA_BIST: /* If not in READY state, then don't start BIST */ - if (DUAL_ROLE_IF_ELSE(port, - pd[port].task_state == PD_STATE_SNK_READY, + if (DUAL_ROLE_IF_ELSE(port, pd[port].task_state == PD_STATE_SNK_READY, pd[port].task_state == PD_STATE_SRC_READY)) { /* currently only support sending bist carrier mode 2 */ if ((payload[0] >> 28) == 5) { /* bist data object mode is 2 */ pd_transmit(port, TCPC_TX_BIST_MODE_2, 0, - NULL); + NULL); /* Set to appropriate port disconnected state */ - set_state(port, DUAL_ROLE_IF_ELSE(port, - PD_STATE_SNK_DISCONNECTED, - PD_STATE_SRC_DISCONNECTED)); + set_state(port, + DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_DISCONNECTED, + PD_STATE_SRC_DISCONNECTED)); } } break; @@ -1197,8 +1165,7 @@ static void handle_data_request(int port, uint16_t head, } #ifdef CONFIG_USB_PD_DUAL_ROLE -void pd_request_power_swap(int port) -{ +void pd_request_power_swap(int port) { if (pd[port].task_state == PD_STATE_SRC_READY) set_state(port, PD_STATE_SRC_SWAP_INIT); else if (pd[port].task_state == PD_STATE_SNK_READY) @@ -1231,18 +1198,15 @@ void pd_try_vconn_src(int port) #endif #endif /* CONFIG_USB_PD_DUAL_ROLE */ -void pd_request_data_swap(int port) -{ - if (DUAL_ROLE_IF_ELSE(port, - pd[port].task_state == PD_STATE_SNK_READY, - pd[port].task_state == PD_STATE_SRC_READY)) +void pd_request_data_swap(int port) { + if (DUAL_ROLE_IF_ELSE(port, pd[port].task_state == PD_STATE_SNK_READY, + pd[port].task_state == PD_STATE_SRC_READY)) set_state(port, PD_STATE_DR_SWAP); // getting rid of task stuff //task_wake(PD_PORT_TO_TASK_ID(port)); } -static void pd_set_data_role(int port, int role) -{ +static void pd_set_data_role(int port, int role) { pd[port].data_role = role; pd_execute_data_swap(port, role); @@ -1266,15 +1230,12 @@ static void pd_set_data_role(int port, int role) pd_update_roles(port); } -static void pd_dr_swap(int port) -{ +static void pd_dr_swap(int port) { pd_set_data_role(port, !pd[port].data_role); pd[port].flags |= PD_FLAGS_CHECK_IDENTITY; } -static void handle_ctrl_request(int port, uint16_t head, - uint32_t *payload) -{ +static void handle_ctrl_request(int port, uint16_t head, uint32_t *payload) { int type = PD_HEADER_TYPE(head); int res; @@ -1287,8 +1248,7 @@ static void handle_ctrl_request(int port, uint16_t head, break; case PD_CTRL_GET_SOURCE_CAP: res = send_source_cap(port); - if ((res >= 0) && - (pd[port].task_state == PD_STATE_SRC_DISCOVERY)) + if ((res >= 0) && (pd[port].task_state == PD_STATE_SRC_DISCOVERY)) set_state(port, PD_STATE_SRC_NEGOCIATE); break; case PD_CTRL_GET_SINK_CAP: @@ -1342,7 +1302,7 @@ static void handle_ctrl_request(int port, uint16_t head, } else if (pd[port].power_role == PD_ROLE_SINK) { set_state(port, PD_STATE_SNK_READY); pd_set_input_current_limit(port, pd[port].curr_limit, - pd[port].supply_voltage); + pd[port].supply_voltage); #ifdef CONFIG_CHARGE_MANAGER /* Set ceiling based on what's negotiated */ //charge_manager_set_ceil(port, @@ -1401,8 +1361,7 @@ static void handle_ctrl_request(int port, uint16_t head, * after PD_T_SINK_REQUEST ms. */ set_state_timeout(port, get_time().val + - PD_T_SINK_REQUEST, - PD_STATE_SNK_READY); + PD_T_SINK_REQUEST, PD_STATE_SNK_READY); } else { /* The request was rejected */ set_state(port, PD_STATE_SNK_READY); @@ -1465,9 +1424,8 @@ static void handle_ctrl_request(int port, uint16_t head, */ pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE; set_state(port, - DUAL_ROLE_IF_ELSE(port, - PD_STATE_SNK_SWAP_SNK_DISABLE, - PD_STATE_SRC_SWAP_SNK_DISABLE)); + DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_SWAP_SNK_DISABLE, + PD_STATE_SRC_SWAP_SNK_DISABLE)); } else { send_control(port, REFUSE(pd[port].rev)); } @@ -1534,19 +1492,16 @@ static void handle_ext_request(int port, uint16_t head, uint32_t *payload) } #endif -static void handle_request(int port, uint16_t head, - uint32_t *payload) -{ +static void handle_request(int port, uint16_t head, uint32_t *payload) { int cnt = PD_HEADER_CNT(head); int p; /* dump received packet content (only dump ping at debug level 3) */ - if ((debug_level == 2 && PD_HEADER_TYPE(head) != PD_CTRL_PING) || - debug_level >= 3) { + if ((debug_level == 2 && PD_HEADER_TYPE(head) != PD_CTRL_PING) + || debug_level >= 3) { CPRINTF("RECV %04x/%d ", head, cnt); for (p = 0; p < cnt; p++) - CPRINTF("[%d]%08x ", p, payload[p]); - CPRINTF("\n"); + CPRINTF("[%d]%08x ", p, payload[p]); CPRINTF("\n"); } /* @@ -1570,16 +1525,17 @@ static void handle_request(int port, uint16_t head, } void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data, - int count) -{ + int count) { if (count > VDO_MAX_SIZE - 1) { CPRINTF("VDM over max size\n"); return; } /* set VDM header with VID & CMD */ - pd[port].vdo_data[0] = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ? - 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), cmd); + pd[port].vdo_data[0] = + VDO(vid, + ((vid & USB_SID_PD) == USB_SID_PD) ? 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), + cmd); #ifdef CONFIG_USB_PD_REV30 pd[port].vdo_data[0] |= VDO_SVDM_VERS(vdo_ver[pd[port].rev]); #endif @@ -1589,8 +1545,7 @@ void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data, //task_wake(PD_PORT_TO_TASK_ID(port)); } -static inline int pdo_busy(int port) -{ +static inline int pdo_busy(int port) { /* * Note, main PDO state machine (pd_task) uses READY state exclusively * to denote port partners have successfully negociated a contract. All @@ -1603,14 +1558,13 @@ static inline int pdo_busy(int port) return rv; } -static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr) -{ +static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr) { uint64_t timeout; int cmd = PD_VDO_CMD(vdm_hdr); /* its not a structured VDM command */ if (!PD_VDO_SVDM(vdm_hdr)) - return 500*MSEC; + return 500 * MSEC; switch (PD_VDO_CMDT(vdm_hdr)) { case CMDT_INIT: @@ -1629,8 +1583,7 @@ static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr) return timeout; } -static void pd_vdm_send_state_machine(int port) -{ +static void pd_vdm_send_state_machine(int port) { int res; uint16_t header; @@ -1651,17 +1604,15 @@ static void pd_vdm_send_state_machine(int port) /* Prepare and send VDM */ header = PD_HEADER(PD_DATA_VENDOR_DEF, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, - (int)pd[port].vdo_count, - pd_get_rev(port), 0); - res = pd_transmit(port, TCPC_TX_SOP, header, - pd[port].vdo_data); + pd[port].data_role, pd[port].msg_id, (int )pd[port].vdo_count, + pd_get_rev(port), 0); + res = pd_transmit(port, TCPC_TX_SOP, header, pd[port].vdo_data); if (res < 0) { pd[port].vdm_state = VDM_STATE_ERR_SEND; } else { pd[port].vdm_state = VDM_STATE_BUSY; - pd[port].vdm_timeout.val = get_time().val + - vdm_get_ready_timeout(pd[port].vdo_data[0]); + pd[port].vdm_timeout.val = get_time().val + + vdm_get_ready_timeout(pd[port].vdo_data[0]); } break; case VDM_STATE_WAIT_RSP_BUSY: @@ -1674,8 +1625,8 @@ static void pd_vdm_send_state_machine(int port) break; case VDM_STATE_BUSY: /* Wait for VDM response or timeout */ - if (pd[port].vdm_timeout.val && - (get_time().val > pd[port].vdm_timeout.val)) { + if (pd[port].vdm_timeout.val + && (get_time().val > pd[port].vdm_timeout.val)) { pd[port].vdm_state = VDM_STATE_ERR_TMOUT; } break; @@ -1699,8 +1650,7 @@ static inline void pd_dev_dump_info(uint16_t dev_id, uint8_t *hash) #endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */ int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash, - uint32_t current_image) -{ + uint32_t current_image) { #ifdef CONFIG_COMMON_RUNTIME int i; #endif @@ -1729,8 +1679,7 @@ int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash, } #ifdef CONFIG_USB_PD_DUAL_ROLE -enum pd_dual_role_states pd_get_dual_role(void) -{ +enum pd_dual_role_states pd_get_dual_role(void) { return drp_state; } @@ -1773,8 +1722,7 @@ static void pd_update_try_source(void) DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pd_update_try_source, HOOK_PRIO_DEFAULT); #endif -void pd_set_dual_role(enum pd_dual_role_states state) -{ +void pd_set_dual_role(enum pd_dual_role_states state) { int i; drp_state = state; @@ -1790,18 +1738,17 @@ void pd_set_dual_role(enum pd_dual_role_states state) ; } -void pd_update_dual_role_config(int port) -{ +void pd_update_dual_role_config(int port) { /* * Change to sink if port is currently a source AND (new DRP * state is force sink OR new DRP state is either toggle off * or debug accessory toggle only and we are in the source * disconnected state). */ - if (pd[port].power_role == PD_ROLE_SOURCE && - ((drp_state == PD_DRP_FORCE_SINK && !pd_ts_dts_plugged(port)) || - (drp_state == PD_DRP_TOGGLE_OFF - && pd[port].task_state == PD_STATE_SRC_DISCONNECTED))) { + if (pd[port].power_role == PD_ROLE_SOURCE + && ((drp_state == PD_DRP_FORCE_SINK && !pd_ts_dts_plugged(port)) + || (drp_state == PD_DRP_TOGGLE_OFF + && pd[port].task_state == PD_STATE_SRC_DISCONNECTED))) { pd[port].power_role = PD_ROLE_SINK; set_state(port, PD_STATE_SNK_DISCONNECTED); tcpm_set_cc(port, TYPEC_CC_RD); @@ -1813,8 +1760,8 @@ void pd_update_dual_role_config(int port) * Change to source if port is currently a sink and the * new DRP state is force source. */ - if (pd[port].power_role == PD_ROLE_SINK && - drp_state == PD_DRP_FORCE_SOURCE) { + if (pd[port].power_role == PD_ROLE_SINK + && drp_state == PD_DRP_FORCE_SOURCE) { pd[port].power_role = PD_ROLE_SOURCE; set_state(port, PD_STATE_SRC_DISCONNECTED); tcpm_set_cc(port, TYPEC_CC_RP); @@ -1827,29 +1774,26 @@ void pd_update_dual_role_config(int port) #endif } -int pd_get_role(int port) -{ +int pd_get_role(int port) { return pd[port].power_role; } -static int pd_is_power_swapping(int port) -{ +static int pd_is_power_swapping(int port) { /* return true if in the act of swapping power roles */ - return pd[port].task_state == PD_STATE_SNK_SWAP_SNK_DISABLE || - pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE || - pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY || - pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE || - pd[port].task_state == PD_STATE_SRC_SWAP_SNK_DISABLE || - pd[port].task_state == PD_STATE_SRC_SWAP_SRC_DISABLE || - pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY; + return pd[port].task_state == PD_STATE_SNK_SWAP_SNK_DISABLE + || pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE + || pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY + || pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE + || pd[port].task_state == PD_STATE_SRC_SWAP_SNK_DISABLE + || pd[port].task_state == PD_STATE_SRC_SWAP_SRC_DISABLE + || pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY; } /* * Provide Rp to ensure the partner port is in a known state (eg. not * PD negotiated, not sourcing 20V). */ -static void pd_partner_port_reset(int port) -{ +static void pd_partner_port_reset(int port) { uint64_t timeout; #ifdef CONFIG_BBRAM @@ -1876,13 +1820,11 @@ static void pd_partner_port_reset(int port) } #endif /* CONFIG_USB_PD_DUAL_ROLE */ -int pd_get_polarity(int port) -{ +int pd_get_polarity(int port) { return pd[port].polarity; } -int pd_get_partner_data_swap_capable(int port) -{ +int pd_get_partner_data_swap_capable(int port) { /* return data swap capable status of port partner */ return pd[port].flags & PD_FLAGS_PARTNER_DR_DATA; } @@ -1910,8 +1852,7 @@ void pd_comm_enable(int port, int enable) } #endif -void pd_ping_enable(int port, int enable) -{ +void pd_ping_enable(int port, int enable) { if (enable) pd[port].flags |= PD_FLAGS_PING_ENABLED; else @@ -1921,10 +1862,9 @@ void pd_ping_enable(int port, int enable) /** * 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_SNK_DEF) || (cc == TYPEC_CC_VOLT_SNK_1_5) || - (cc == TYPEC_CC_VOLT_SNK_3_0); +static inline int cc_is_rp(int cc) { + return (cc == TYPEC_CC_VOLT_SNK_DEF) || (cc == TYPEC_CC_VOLT_SNK_1_5) + || (cc == TYPEC_CC_VOLT_SNK_3_0); } /* @@ -1938,13 +1878,12 @@ static inline int cc_is_rp(int cc) * 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 int get_snk_polarity(int cc1, int cc2) -{ +static inline int get_snk_polarity(int cc1, int cc2) { /* the following assumes: * TYPEC_CC_VOLT_SNK_3_0 > TYPEC_CC_VOLT_SNK_1_5 * TYPEC_CC_VOLT_SNK_1_5 > TYPEC_CC_VOLT_SNK_DEF @@ -1957,8 +1896,7 @@ static inline int get_snk_polarity(int cc1, int cc2) /** * Returns type C current limit (mA) based upon cc_voltage (mV). */ -static typec_current_t get_typec_current_limit(int polarity, int cc1, int cc2) -{ +static typec_current_t get_typec_current_limit(int polarity, int cc1, int cc2) { typec_current_t charge; int cc = polarity ? cc2 : cc1; int cc_alt = polarity ? cc1 : cc2; @@ -1979,8 +1917,7 @@ static typec_current_t get_typec_current_limit(int polarity, int cc1, int cc2) /** * Signal power request to indicate a charger update that affects the port. */ -void pd_set_new_power_request(int port) -{ +void pd_set_new_power_request(int port) { pd[port].new_power_request = 1; // getting rid of task stuff //task_wake(PD_PORT_TO_TASK_ID(port)); @@ -2035,8 +1972,7 @@ static void pd_init_tasks(void) #endif /* CONFIG_COMMON_RUNTIME */ #ifndef CONFIG_USB_PD_TCPC -static int pd_restart_tcpc(int port) -{ +static int pd_restart_tcpc(int port) { if (board_set_tcpc_power_mode) { /* force chip reset */ board_set_tcpc_power_mode(port, 0); @@ -2045,8 +1981,7 @@ static int pd_restart_tcpc(int port) } #endif -void pd_init(int port) -{ +void pd_init(int port) { #ifdef CONFIG_COMMON_RUNTIME pd_init_tasks(); #endif @@ -2073,8 +2008,8 @@ void pd_init(int port) struct ec_response_pd_chip_info *info; tcpm_get_chip_info(port, 0, &info); CPRINTS("TCPC p%d VID:0x%x PID:0x%x DID:0x%x FWV:0x%lx", - port, info->vendor_id, info->product_id, - info->device_id, info->fw_version_number); + port, info->vendor_id, info->product_id, + info->device_id, info->fw_version_number); } #endif @@ -2112,8 +2047,9 @@ void pd_init(int port) #else tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP); #endif - tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE ? - TYPEC_CC_RP : TYPEC_CC_RD); + tcpm_set_cc(port, + PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE ? + TYPEC_CC_RP : TYPEC_CC_RD); #ifdef CONFIG_USB_PD_ALT_MODE_DFP /* Initialize PD Policy engine */ @@ -2128,8 +2064,7 @@ void pd_init(int port) #endif } -void pd_run_state_machine(int port) -{ +void pd_run_state_machine(int port) { #ifdef CONFIG_USB_PD_REV30 /* send any pending messages */ pd_ca_send_pending(port); @@ -2149,7 +2084,6 @@ void pd_run_state_machine(int port) /* wait for next event/packet or timeout expiration */ // getting rid of task stuff //evt = task_wait_event(timeout); - #ifdef CONFIG_USB_PD_DUAL_ROLE if (evt & PD_EVENT_UPDATE_DUAL_ROLE) pd_update_dual_role_config(port); @@ -2175,25 +2109,26 @@ void pd_run_state_machine(int port) #endif /* Ensure CC termination is default */ tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == - PD_ROLE_SOURCE ? TYPEC_CC_RP : TYPEC_CC_RD); + PD_ROLE_SOURCE ? TYPEC_CC_RP : TYPEC_CC_RD); /* - * If we have a stable contract in the default role, - * then simply update TCPC with some missing info - * so that we can continue without resetting PD comms. - * Otherwise, go to the default disconnected state - * and force renegotiation. - */ - if (pd[port].vdm_state == VDM_STATE_DONE && ( + * If we have a stable contract in the default role, + * then simply update TCPC with some missing info + * so that we can continue without resetting PD comms. + * Otherwise, go to the default disconnected state + * and force renegotiation. + */ + if (pd[port].vdm_state == VDM_STATE_DONE + && ( #ifdef CONFIG_USB_PD_DUAL_ROLE - (PD_ROLE_DEFAULT(port) == PD_ROLE_SINK && - pd[port].task_state == PD_STATE_SNK_READY) || + (PD_ROLE_DEFAULT(port) == PD_ROLE_SINK + && pd[port].task_state == PD_STATE_SNK_READY) + || #endif - (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE && - pd[port].task_state == PD_STATE_SRC_READY))) { + (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE + && pd[port].task_state == PD_STATE_SRC_READY))) { tcpm_set_polarity(port, pd[port].polarity); - tcpm_set_msg_header(port, pd[port].power_role, - pd[port].data_role); + tcpm_set_msg_header(port, pd[port].power_role, pd[port].data_role); tcpm_set_rx_enable(port, 1); } else { /* Ensure state variables are at default */ @@ -2207,8 +2142,8 @@ void pd_run_state_machine(int port) /* process any potential incoming message */ incoming_packet = evt & PD_EVENT_RX; //if (incoming_packet) { - if (!tcpm_get_message(port, payload, &head)) - handle_request(port, head, payload); + if (!tcpm_get_message(port, payload, &head)) + handle_request(port, head, payload); //} if (pd[port].req_suspend_state) @@ -2216,13 +2151,13 @@ void pd_run_state_machine(int port) /* if nothing to do, verify the state of the world in 500ms */ this_state = pd[port].task_state; - timeout = 500*MSEC; + timeout = 500 * MSEC; switch (this_state) { case PD_STATE_DISABLED: /* Nothing to do */ break; case PD_STATE_SRC_DISCONNECTED: - timeout = 10*MSEC; + timeout = 10 * MSEC; tcpm_get_cc(port, &cc1, &cc2); #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE /* @@ -2241,66 +2176,59 @@ void pd_run_state_machine(int port) #endif /* Vnc monitoring */ - if ((cc1 == TYPEC_CC_VOLT_RD || - cc2 == TYPEC_CC_VOLT_RD) || - (cc1 == TYPEC_CC_VOLT_RA && - cc2 == TYPEC_CC_VOLT_RA)) { + if ((cc1 == TYPEC_CC_VOLT_RD || cc2 == TYPEC_CC_VOLT_RD) + || (cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_RA)) { #ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP /* Enable VBUS */ if (pd_set_power_supply_ready(port)) break; #endif pd[port].cc_state = PD_CC_NONE; - set_state(port, - PD_STATE_SRC_DISCONNECTED_DEBOUNCE); + set_state(port, PD_STATE_SRC_DISCONNECTED_DEBOUNCE); } #if defined(CONFIG_USB_PD_DUAL_ROLE) /* - * Try.SRC state is embedded here. Wait for SNK - * detect, or if timer expires, transition to - * SNK_DISCONNETED. - * - * If Try.SRC state is not active, then this block - * handles the normal DRP toggle from SRC->SNK - */ - else if ((pd[port].flags & PD_FLAGS_TRY_SRC && - get_time().val >= pd[port].try_src_marker) || - (!(pd[port].flags & PD_FLAGS_TRY_SRC) && - drp_state != PD_DRP_FORCE_SOURCE && - drp_state != PD_DRP_FREEZE && - get_time().val >= next_role_swap)) { + * Try.SRC state is embedded here. Wait for SNK + * detect, or if timer expires, transition to + * SNK_DISCONNETED. + * + * If Try.SRC state is not active, then this block + * handles the normal DRP toggle from SRC->SNK + */ + else if ((pd[port].flags & PD_FLAGS_TRY_SRC + && get_time().val >= pd[port].try_src_marker) + || (!(pd[port].flags & PD_FLAGS_TRY_SRC) + && drp_state != PD_DRP_FORCE_SOURCE + && drp_state != PD_DRP_FREEZE + && get_time().val >= next_role_swap)) { pd[port].power_role = PD_ROLE_SINK; set_state(port, PD_STATE_SNK_DISCONNECTED); tcpm_set_cc(port, TYPEC_CC_RD); next_role_swap = get_time().val + PD_T_DRP_SNK; - pd[port].try_src_marker = get_time().val - + PD_T_TRY_WAIT; + pd[port].try_src_marker = get_time().val + PD_T_TRY_WAIT; /* Swap states quickly */ - timeout = 2*MSEC; + timeout = 2 * MSEC; } #endif break; case PD_STATE_SRC_DISCONNECTED_DEBOUNCE: - timeout = 20*MSEC; + timeout = 20 * MSEC; tcpm_get_cc(port, &cc1, &cc2); - if (cc1 == TYPEC_CC_VOLT_RD && - cc2 == TYPEC_CC_VOLT_RD) { + if (cc1 == TYPEC_CC_VOLT_RD && cc2 == TYPEC_CC_VOLT_RD) { /* Debug accessory */ new_cc_state = PD_CC_DEBUG_ACC; - } else if (cc1 == TYPEC_CC_VOLT_RD || - cc2 == TYPEC_CC_VOLT_RD) { + } else if (cc1 == TYPEC_CC_VOLT_RD || cc2 == TYPEC_CC_VOLT_RD) { /* UFP attached */ new_cc_state = PD_CC_UFP_ATTACHED; - } else if (cc1 == TYPEC_CC_VOLT_RA && - cc2 == TYPEC_CC_VOLT_RA) { + } else if (cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_RA) { /* Audio accessory */ new_cc_state = PD_CC_AUDIO_ACC; } else { /* No UFP */ set_state(port, PD_STATE_SRC_DISCONNECTED); - timeout = 5*MSEC; + timeout = 5 * MSEC; break; } /* If in Try.SRC state, then don't need to debounce */ @@ -2308,19 +2236,18 @@ void pd_run_state_machine(int port) /* Debounce the cc state */ if (new_cc_state != pd[port].cc_state) { pd[port].cc_debounce = get_time().val + - PD_T_CC_DEBOUNCE; + PD_T_CC_DEBOUNCE; pd[port].cc_state = new_cc_state; break; - } else if (get_time().val < - pd[port].cc_debounce) { + } else if (get_time().val < pd[port].cc_debounce) { break; } } /* Debounce complete */ /* UFP is attached */ - if (new_cc_state == PD_CC_UFP_ATTACHED || - new_cc_state == PD_CC_DEBUG_ACC) { + if (new_cc_state == PD_CC_UFP_ATTACHED + || new_cc_state == PD_CC_DEBUG_ACC) { pd[port].polarity = (cc1 != TYPEC_CC_VOLT_RD); tcpm_set_polarity(port, pd[port].polarity); @@ -2329,7 +2256,7 @@ void pd_run_state_machine(int port) if (new_cc_state == PD_CC_DEBUG_ACC) pd[port].flags |= - PD_FLAGS_TS_DTS_PARTNER; + PD_FLAGS_TS_DTS_PARTNER; #ifndef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP /* Enable VBUS */ @@ -2352,25 +2279,25 @@ void pd_run_state_machine(int port) #endif pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE | - PD_FLAGS_CHECK_DR_ROLE; + PD_FLAGS_CHECK_DR_ROLE; hard_reset_count = 0; - timeout = 5*MSEC; + timeout = 5 * MSEC; set_state(port, PD_STATE_SRC_STARTUP); } /* - * AUDIO_ACC will remain in this state indefinitely - * until disconnect. - */ + * AUDIO_ACC will remain in this state indefinitely + * until disconnect. + */ break; case PD_STATE_SRC_HARD_RESET_RECOVER: /* Do not continue until hard reset recovery time */ if (get_time().val < pd[port].src_recover) { - timeout = 50*MSEC; + timeout = 50 * MSEC; break; } /* Enable VBUS */ - timeout = 10*MSEC; + timeout = 10 * MSEC; if (pd_set_power_supply_ready(port)) { set_state(port, PD_STATE_SRC_DISCONNECTED); break; @@ -2395,8 +2322,7 @@ void pd_run_state_machine(int port) caps_count = 0; pd[port].msg_id = 0; snk_cap_count = 0; - set_state_timeout( - port, + set_state_timeout(port, #ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP /* * delay for power supply to start up. @@ -2410,26 +2336,25 @@ void pd_run_state_machine(int port) PD_STATE_SRC_DISCONNECTED_DEBOUNCE ? PD_T_CC_DEBOUNCE : 0), #else - get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY, + get_time().val + + PD_POWER_SUPPLY_TURN_ON_DELAY, #endif - PD_STATE_SRC_DISCOVERY); + PD_STATE_SRC_DISCOVERY); } break; case PD_STATE_SRC_DISCOVERY: if (pd[port].last_state != pd[port].task_state) { /* - * If we have had PD connection with this port - * partner, then start NoResponseTimer. - */ + * If we have had PD connection with this port + * partner, then start NoResponseTimer. + */ if (pd[port].flags & PD_FLAGS_PREVIOUS_PD_CONN) - set_state_timeout(port, - get_time().val + - PD_T_NO_RESPONSE, - hard_reset_count < + set_state_timeout(port, get_time().val + + PD_T_NO_RESPONSE, + hard_reset_count < PD_HARD_RESET_COUNT ? - PD_STATE_HARD_RESET_SEND : - PD_STATE_SRC_DISCONNECTED); + PD_STATE_HARD_RESET_SEND : + PD_STATE_SRC_DISCONNECTED); } /* Send source cap some minimum number of times */ @@ -2438,14 +2363,13 @@ void pd_run_state_machine(int port) res = send_source_cap(port); /* packet was acked => PD capable device) */ if (res >= 0) { - set_state(port, - PD_STATE_SRC_NEGOCIATE); - timeout = 10*MSEC; + set_state(port, PD_STATE_SRC_NEGOCIATE); + timeout = 10 * MSEC; hard_reset_count = 0; caps_count = 0; /* Port partner is PD capable */ pd[port].flags |= - PD_FLAGS_PREVIOUS_PD_CONN; + PD_FLAGS_PREVIOUS_PD_CONN; } else { /* failed, retry later */ timeout = PD_T_SEND_SOURCE_CAP; caps_count++; @@ -2455,36 +2379,28 @@ void pd_run_state_machine(int port) case PD_STATE_SRC_NEGOCIATE: /* wait for a "Request" message */ if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, - get_time().val + - PD_T_SENDER_RESPONSE, - PD_STATE_HARD_RESET_SEND); + set_state_timeout(port, get_time().val + + PD_T_SENDER_RESPONSE, PD_STATE_HARD_RESET_SEND); break; case PD_STATE_SRC_ACCEPTED: /* Accept sent, wait for enabling the new voltage */ if (pd[port].last_state != pd[port].task_state) - set_state_timeout( - port, - get_time().val + - PD_T_SINK_TRANSITION, - PD_STATE_SRC_POWERED); + set_state_timeout(port, get_time().val + + PD_T_SINK_TRANSITION, PD_STATE_SRC_POWERED); break; case PD_STATE_SRC_POWERED: /* Switch to the new requested voltage */ if (pd[port].last_state != pd[port].task_state) { pd_transition_voltage(pd[port].requested_idx); - set_state_timeout( - port, - get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY, - PD_STATE_SRC_TRANSITION); + set_state_timeout(port, get_time().val + + PD_POWER_SUPPLY_TURN_ON_DELAY, PD_STATE_SRC_TRANSITION); } break; case PD_STATE_SRC_TRANSITION: /* the voltage output is good, notify the source */ res = send_control(port, PD_CTRL_PS_RDY); if (res >= 0) { - timeout = 10*MSEC; + timeout = 10 * MSEC; /* it'a time to ping regularly the sink */ set_state(port, PD_STATE_SRC_READY); } else { @@ -2496,22 +2412,19 @@ void pd_run_state_machine(int port) timeout = PD_T_SOURCE_ACTIVITY; /* - * Don't send any PD traffic if we woke up due to - * incoming packet or if VDO response pending to avoid - * collisions. - */ - if (incoming_packet || - (pd[port].vdm_state == VDM_STATE_BUSY)) + * Don't send any PD traffic if we woke up due to + * incoming packet or if VDO response pending to avoid + * collisions. + */ + if (incoming_packet || (pd[port].vdm_state == VDM_STATE_BUSY)) break; /* Send updated source capabilities to our partner */ if (pd[port].flags & PD_FLAGS_UPDATE_SRC_CAPS) { res = send_source_cap(port); if (res >= 0) { - set_state(port, - PD_STATE_SRC_NEGOCIATE); - pd[port].flags &= - ~PD_FLAGS_UPDATE_SRC_CAPS; + set_state(port, PD_STATE_SRC_NEGOCIATE); + pd[port].flags &= ~PD_FLAGS_UPDATE_SRC_CAPS; } break; } @@ -2523,34 +2436,32 @@ void pd_run_state_machine(int port) send_control(port, PD_CTRL_GET_SINK_CAP); set_state(port, PD_STATE_SRC_GET_SINK_CAP); break; - } else if (debug_level >= 2 && - snk_cap_count == PD_SNK_CAP_RETRIES+1) { + } else if (debug_level >= 2 + && snk_cap_count == PD_SNK_CAP_RETRIES + 1) { CPRINTF("ERR SNK_CAP\n"); } } /* Check power role policy, which may trigger a swap */ if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) { - pd_check_pr_role(port, PD_ROLE_SOURCE, - pd[port].flags); + pd_check_pr_role(port, PD_ROLE_SOURCE, pd[port].flags); pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE; break; } /* Check data role policy, which may trigger a swap */ if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) { - pd_check_dr_role(port, pd[port].data_role, - pd[port].flags); + pd_check_dr_role(port, pd[port].data_role, pd[port].flags); pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE; break; } /* Send discovery SVDMs last */ - if (pd[port].data_role == PD_ROLE_DFP && - (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) { + if (pd[port].data_role == PD_ROLE_DFP + && (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) { #ifndef CONFIG_USB_PD_SIMPLE_DFP pd_send_vdm(port, USB_SID_PD, - CMD_DISCOVER_IDENT, NULL, 0); + CMD_DISCOVER_IDENT, NULL, 0); #endif pd[port].flags &= ~PD_FLAGS_CHECK_IDENTITY; break; @@ -2570,31 +2481,27 @@ void pd_run_state_machine(int port) break; case PD_STATE_SRC_GET_SINK_CAP: if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, - get_time().val + - PD_T_SENDER_RESPONSE, - PD_STATE_SRC_READY); + set_state_timeout(port, get_time().val + + PD_T_SENDER_RESPONSE, PD_STATE_SRC_READY); break; case PD_STATE_DR_SWAP: if (pd[port].last_state != pd[port].task_state) { res = send_control(port, PD_CTRL_DR_SWAP); if (res < 0) { - timeout = 10*MSEC; + timeout = 10 * MSEC; /* - * If failed to get goodCRC, send - * soft reset, otherwise ignore - * failure. - */ - set_state(port, res == -1 ? - PD_STATE_SOFT_RESET : - READY_RETURN_STATE(port)); + * If failed to get goodCRC, send + * soft reset, otherwise ignore + * failure. + */ + set_state(port, + res == -1 ? + PD_STATE_SOFT_RESET : READY_RETURN_STATE(port)); break; } /* Wait for accept or reject */ - set_state_timeout(port, - get_time().val + - PD_T_SENDER_RESPONSE, - READY_RETURN_STATE(port)); + set_state_timeout(port, get_time().val + + PD_T_SENDER_RESPONSE, READY_RETURN_STATE(port)); } break; #ifdef CONFIG_USB_PD_DUAL_ROLE @@ -2602,40 +2509,33 @@ void pd_run_state_machine(int port) if (pd[port].last_state != pd[port].task_state) { res = send_control(port, PD_CTRL_PR_SWAP); if (res < 0) { - timeout = 10*MSEC; + timeout = 10 * MSEC; /* - * If failed to get goodCRC, send - * soft reset, otherwise ignore - * failure. - */ - set_state(port, res == -1 ? - PD_STATE_SOFT_RESET : - PD_STATE_SRC_READY); + * If failed to get goodCRC, send + * soft reset, otherwise ignore + * failure. + */ + set_state(port, + res == -1 ? PD_STATE_SOFT_RESET : PD_STATE_SRC_READY); break; } /* Wait for accept or reject */ - set_state_timeout(port, - get_time().val + - PD_T_SENDER_RESPONSE, - PD_STATE_SRC_READY); + set_state_timeout(port, get_time().val + + PD_T_SENDER_RESPONSE, PD_STATE_SRC_READY); } break; case PD_STATE_SRC_SWAP_SNK_DISABLE: /* Give time for sink to stop drawing current */ if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, - get_time().val + - PD_T_SINK_TRANSITION, - PD_STATE_SRC_SWAP_SRC_DISABLE); + set_state_timeout(port, get_time().val + + PD_T_SINK_TRANSITION, PD_STATE_SRC_SWAP_SRC_DISABLE); break; case PD_STATE_SRC_SWAP_SRC_DISABLE: /* Turn power off */ if (pd[port].last_state != pd[port].task_state) { pd_power_supply_reset(port); - set_state_timeout(port, - get_time().val + - PD_POWER_SUPPLY_TURN_OFF_DELAY, - PD_STATE_SRC_SWAP_STANDBY); + set_state_timeout(port, get_time().val + + PD_POWER_SUPPLY_TURN_OFF_DELAY, PD_STATE_SRC_SWAP_STANDBY); } break; case PD_STATE_SRC_SWAP_STANDBY: @@ -2644,19 +2544,16 @@ void pd_run_state_machine(int port) /* Send PS_RDY */ res = send_control(port, PD_CTRL_PS_RDY); if (res < 0) { - timeout = 10*MSEC; - set_state(port, - PD_STATE_SRC_DISCONNECTED); + timeout = 10 * MSEC; + set_state(port, PD_STATE_SRC_DISCONNECTED); break; } /* Switch to Rd and swap roles to sink */ tcpm_set_cc(port, TYPEC_CC_RD); pd[port].power_role = PD_ROLE_SINK; /* Wait for PS_RDY from new source */ - set_state_timeout(port, - get_time().val + - PD_T_PS_SOURCE_ON, - PD_STATE_SNK_DISCONNECTED); + set_state_timeout(port, get_time().val + + PD_T_PS_SOURCE_ON, PD_STATE_SNK_DISCONNECTED); } break; case PD_STATE_SUSPENDED: { @@ -2682,8 +2579,7 @@ void pd_run_state_machine(int port) pd_hw_init(port, PD_ROLE_DEFAULT(port)); CPRINTS("TCPC p%d resumed!", port); #else - if (rstatus != EC_ERROR_UNIMPLEMENTED && - pd_restart_tcpc(port) != 0) { + if (rstatus != EC_ERROR_UNIMPLEMENTED && pd_restart_tcpc(port) != 0) { /* stay in PD_STATE_SUSPENDED */ CPRINTS("TCPC p%d restart failed!", port); break; @@ -2698,7 +2594,7 @@ void pd_run_state_machine(int port) timeout = drp_state != PD_DRP_TOGGLE_ON ? SECOND : 10*MSEC; #else - timeout = 10*MSEC; + timeout = 10 * MSEC; #endif tcpm_get_cc(port, &cc1, &cc2); @@ -2719,25 +2615,23 @@ void pd_run_state_machine(int port) #endif /* Source connection monitoring */ - if (cc1 != TYPEC_CC_VOLT_OPEN || - cc2 != TYPEC_CC_VOLT_OPEN) { + if (cc1 != TYPEC_CC_VOLT_OPEN || cc2 != TYPEC_CC_VOLT_OPEN) { pd[port].cc_state = PD_CC_NONE; hard_reset_count = 0; new_cc_state = PD_CC_NONE; pd[port].cc_debounce = get_time().val + - PD_T_CC_DEBOUNCE; - set_state(port, - PD_STATE_SNK_DISCONNECTED_DEBOUNCE); - timeout = 10*MSEC; + PD_T_CC_DEBOUNCE; + set_state(port, PD_STATE_SNK_DISCONNECTED_DEBOUNCE); + timeout = 10 * MSEC; break; } /* - * If Try.SRC is active and failed to detect a SNK, - * then it transitions to TryWait.SNK. Need to prevent - * normal dual role toggle until tDRPTryWait timer - * expires. - */ + * If Try.SRC is active and failed to detect a SNK, + * then it transitions to TryWait.SNK. Need to prevent + * normal dual role toggle until tDRPTryWait timer + * expires. + */ if (pd[port].flags & PD_FLAGS_TRY_SRC) { if (get_time().val > pd[port].try_src_marker) pd[port].flags &= ~PD_FLAGS_TRY_SRC; @@ -2745,8 +2639,7 @@ void pd_run_state_machine(int port) } /* If no source detected, check for role toggle. */ - if (drp_state == PD_DRP_TOGGLE_ON && - get_time().val >= next_role_swap) { + if (drp_state == PD_DRP_TOGGLE_ON && get_time().val >= next_role_swap) { /* Swap roles to source */ pd[port].power_role = PD_ROLE_SOURCE; set_state(port, PD_STATE_SRC_DISCONNECTED); @@ -2754,7 +2647,7 @@ void pd_run_state_machine(int port) next_role_swap = get_time().val + PD_T_DRP_SRC; /* Swap states quickly */ - timeout = 2*MSEC; + timeout = 2 * MSEC; } break; case PD_STATE_SNK_DISCONNECTED_DEBOUNCE: @@ -2768,36 +2661,33 @@ void pd_run_state_machine(int port) } else { /* No connection any more */ set_state(port, PD_STATE_SNK_DISCONNECTED); - timeout = 5*MSEC; + timeout = 5 * MSEC; break; } - timeout = 20*MSEC; + timeout = 20 * MSEC; /* Debounce the cc state */ if (new_cc_state != pd[port].cc_state) { pd[port].cc_debounce = get_time().val + - PD_T_CC_DEBOUNCE; + PD_T_CC_DEBOUNCE; pd[port].cc_state = new_cc_state; break; } /* Wait for CC debounce and VBUS present */ - if (get_time().val < pd[port].cc_debounce || - !pd_is_vbus_present(port)) + if (get_time().val < pd[port].cc_debounce || !pd_is_vbus_present(port)) break; - if (pd_try_src_enable && - !(pd[port].flags & PD_FLAGS_TRY_SRC)) { + if (pd_try_src_enable && !(pd[port].flags & PD_FLAGS_TRY_SRC)) { /* - * If TRY_SRC is enabled, but not active, - * then force attempt to connect as source. - */ - pd[port].try_src_marker = get_time().val - + PD_T_TRY_SRC; + * If TRY_SRC is enabled, but not active, + * then force attempt to connect as source. + */ + pd[port].try_src_marker = get_time().val + PD_T_TRY_SRC; /* Swap roles to source */ pd[port].power_role = PD_ROLE_SOURCE; tcpm_set_cc(port, TYPEC_CC_RP); - timeout = 2*MSEC; + timeout = 2 * MSEC; set_state(port, PD_STATE_SRC_DISCONNECTED); /* Set flag after the state change */ pd[port].flags |= PD_FLAGS_TRY_SRC; @@ -2812,8 +2702,7 @@ void pd_run_state_machine(int port) /* initial data role for sink is UFP */ pd_set_data_role(port, PD_ROLE_UFP); #if defined(CONFIG_CHARGE_MANAGER) - typec_curr = get_typec_current_limit(pd[port].polarity, - cc1, cc2); + typec_curr = get_typec_current_limit(pd[port].polarity, cc1, cc2); //typec_set_input_current_limit( // port, typec_curr, TYPE_C_VOLTAGE); #endif @@ -2822,17 +2711,17 @@ void pd_run_state_machine(int port) tcpm_set_rx_enable(port, 1); /* DFP is attached */ - if (new_cc_state == PD_CC_DFP_ATTACHED || - new_cc_state == PD_CC_DEBUG_ACC) { + if (new_cc_state == PD_CC_DFP_ATTACHED + || new_cc_state == PD_CC_DEBUG_ACC) { pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE | - PD_FLAGS_CHECK_DR_ROLE | - PD_FLAGS_CHECK_IDENTITY; + PD_FLAGS_CHECK_DR_ROLE | + PD_FLAGS_CHECK_IDENTITY; if (new_cc_state == PD_CC_DEBUG_ACC) pd[port].flags |= - PD_FLAGS_TS_DTS_PARTNER; + PD_FLAGS_TS_DTS_PARTNER; send_control(port, PD_CTRL_GET_SOURCE_CAP); set_state(port, PD_STATE_SNK_DISCOVERY); - timeout = 10*MSEC; + timeout = 10 * MSEC; //hook_call_deferred( // &pd_usb_billboard_deferred_data, // PD_T_AME); @@ -2856,27 +2745,21 @@ void pd_run_state_machine(int port) /* Wait for VBUS to go low and then high*/ if (pd[port].last_state != pd[port].task_state) { snk_hard_reset_vbus_off = 0; - set_state_timeout(port, - get_time().val + - PD_T_SAFE_0V, - hard_reset_count < - PD_HARD_RESET_COUNT ? - PD_STATE_HARD_RESET_SEND : - PD_STATE_SNK_DISCOVERY); + set_state_timeout(port, get_time().val + + PD_T_SAFE_0V, + hard_reset_count < + PD_HARD_RESET_COUNT ? + PD_STATE_HARD_RESET_SEND : PD_STATE_SNK_DISCOVERY); } - if (!pd_is_vbus_present(port) && - !snk_hard_reset_vbus_off) { + if (!pd_is_vbus_present(port) && !snk_hard_reset_vbus_off) { /* VBUS has gone low, reset timeout */ snk_hard_reset_vbus_off = 1; - set_state_timeout(port, - get_time().val + - PD_T_SRC_RECOVER_MAX + - PD_T_SRC_TURN_ON, - PD_STATE_SNK_DISCONNECTED); + set_state_timeout(port, get_time().val + + PD_T_SRC_RECOVER_MAX + + PD_T_SRC_TURN_ON, PD_STATE_SNK_DISCONNECTED); } - if (pd_is_vbus_present(port) && - snk_hard_reset_vbus_off) { + if (pd_is_vbus_present(port) && snk_hard_reset_vbus_off) { #ifdef CONFIG_USB_PD_TCPM_TCPCI /* * After transmitting hard reset, TCPM writes @@ -2889,56 +2772,49 @@ void pd_run_state_machine(int port) /* VBUS went high again */ set_state(port, PD_STATE_SNK_DISCOVERY); - timeout = 10*MSEC; + timeout = 10 * MSEC; } /* - * Don't need to set timeout because VBUS changing - * will trigger an interrupt and wake us up. - */ + * Don't need to set timeout because VBUS changing + * will trigger an interrupt and wake us up. + */ #endif break; case PD_STATE_SNK_DISCOVERY: /* Wait for source cap expired only if we are enabled */ if ((pd[port].last_state != pd[port].task_state) - && pd_comm_is_enabled(port)) { + && pd_comm_is_enabled(port)) { /* - * If VBUS has never been low, and we timeout - * waiting for source cap, try a soft reset - * first, in case we were already in a stable - * contract before this boot. - */ + * If VBUS has never been low, and we timeout + * waiting for source cap, try a soft reset + * first, in case we were already in a stable + * contract before this boot. + */ if (pd[port].flags & PD_FLAGS_VBUS_NEVER_LOW) - set_state_timeout(port, - get_time().val + - PD_T_SINK_WAIT_CAP, - PD_STATE_SOFT_RESET); + set_state_timeout(port, get_time().val + + PD_T_SINK_WAIT_CAP, PD_STATE_SOFT_RESET); /* - * If we haven't passed hard reset counter, - * start SinkWaitCapTimer, otherwise start - * NoResponseTimer. - */ + * If we haven't passed hard reset counter, + * start SinkWaitCapTimer, otherwise start + * NoResponseTimer. + */ else if (hard_reset_count < PD_HARD_RESET_COUNT) - set_state_timeout(port, - get_time().val + - PD_T_SINK_WAIT_CAP, - PD_STATE_HARD_RESET_SEND); + set_state_timeout(port, get_time().val + + PD_T_SINK_WAIT_CAP, PD_STATE_HARD_RESET_SEND); else if (pd[port].flags & - PD_FLAGS_PREVIOUS_PD_CONN) + PD_FLAGS_PREVIOUS_PD_CONN) /* ErrorRecovery */ - set_state_timeout(port, - get_time().val + - PD_T_NO_RESPONSE, - PD_STATE_SNK_DISCONNECTED); + set_state_timeout(port, get_time().val + + PD_T_NO_RESPONSE, PD_STATE_SNK_DISCONNECTED); #if defined(CONFIG_CHARGE_MANAGER) /* - * If we didn't come from disconnected, must - * have come from some path that did not set - * typec current limit. So, set to 0 so that - * we guarantee this is revised below. - */ - if (pd[port].last_state != - PD_STATE_SNK_DISCONNECTED_DEBOUNCE) + * If we didn't come from disconnected, must + * have come from some path that did not set + * typec current limit. So, set to 0 so that + * we guarantee this is revised below. + */ + if (pd[port].last_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE) typec_curr = 0; #endif } @@ -2948,13 +2824,13 @@ void pd_run_state_machine(int port) /* Check if CC pull-up has changed */ tcpm_get_cc(port, &cc1, &cc2); - if (typec_curr != get_typec_current_limit( - pd[port].polarity, cc1, cc2)) { + if (typec_curr + != get_typec_current_limit(pd[port].polarity, cc1, cc2)) { /* debounce signal by requiring two reads */ if (typec_curr_change) { /* set new input current limit */ - typec_curr = get_typec_current_limit( - pd[port].polarity, cc1, cc2); + typec_curr = get_typec_current_limit(pd[port].polarity, cc1, + cc2); //typec_set_input_current_limit( // port, typec_curr, TYPE_C_VOLTAGE); } else { @@ -2971,30 +2847,25 @@ void pd_run_state_machine(int port) /* Wait for ACCEPT or REJECT */ if (pd[port].last_state != pd[port].task_state) { hard_reset_count = 0; - set_state_timeout(port, - get_time().val + - PD_T_SENDER_RESPONSE, - PD_STATE_HARD_RESET_SEND); + set_state_timeout(port, get_time().val + + PD_T_SENDER_RESPONSE, PD_STATE_HARD_RESET_SEND); } break; case PD_STATE_SNK_TRANSITION: /* Wait for PS_RDY */ if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, - get_time().val + - PD_T_PS_TRANSITION, - PD_STATE_HARD_RESET_SEND); + set_state_timeout(port, get_time().val + + PD_T_PS_TRANSITION, PD_STATE_HARD_RESET_SEND); break; case PD_STATE_SNK_READY: - timeout = 20*MSEC; + timeout = 20 * MSEC; /* - * Don't send any PD traffic if we woke up due to - * incoming packet or if VDO response pending to avoid - * collisions. - */ - if (incoming_packet || - (pd[port].vdm_state == VDM_STATE_BUSY)) + * Don't send any PD traffic if we woke up due to + * incoming packet or if VDO response pending to avoid + * collisions. + */ + if (incoming_packet || (pd[port].vdm_state == VDM_STATE_BUSY)) break; /* Check for new power to request */ @@ -3006,52 +2877,47 @@ void pd_run_state_machine(int port) /* Check power role policy, which may trigger a swap */ if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) { - pd_check_pr_role(port, PD_ROLE_SINK, - pd[port].flags); + pd_check_pr_role(port, PD_ROLE_SINK, pd[port].flags); pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE; break; } /* Check data role policy, which may trigger a swap */ if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) { - pd_check_dr_role(port, pd[port].data_role, - pd[port].flags); + pd_check_dr_role(port, pd[port].data_role, pd[port].flags); pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE; break; } /* If DFP, send discovery SVDMs */ - if (pd[port].data_role == PD_ROLE_DFP && - (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) { + if (pd[port].data_role == PD_ROLE_DFP + && (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) { pd_send_vdm(port, USB_SID_PD, - CMD_DISCOVER_IDENT, NULL, 0); + CMD_DISCOVER_IDENT, NULL, 0); pd[port].flags &= ~PD_FLAGS_CHECK_IDENTITY; break; } /* Sent all messages, don't need to wake very often */ - timeout = 200*MSEC; + timeout = 200 * MSEC; break; case PD_STATE_SNK_SWAP_INIT: if (pd[port].last_state != pd[port].task_state) { res = send_control(port, PD_CTRL_PR_SWAP); if (res < 0) { - timeout = 10*MSEC; + timeout = 10 * MSEC; /* - * If failed to get goodCRC, send - * soft reset, otherwise ignore - * failure. - */ - set_state(port, res == -1 ? - PD_STATE_SOFT_RESET : - PD_STATE_SNK_READY); + * If failed to get goodCRC, send + * soft reset, otherwise ignore + * failure. + */ + set_state(port, + res == -1 ? PD_STATE_SOFT_RESET : PD_STATE_SNK_READY); break; } /* Wait for accept or reject */ - set_state_timeout(port, - get_time().val + - PD_T_SENDER_RESPONSE, - PD_STATE_SNK_READY); + set_state_timeout(port, get_time().val + + PD_T_SENDER_RESPONSE, PD_STATE_SNK_READY); } break; case PD_STATE_SNK_SWAP_SNK_DISABLE: @@ -3064,15 +2930,13 @@ void pd_run_state_machine(int port) // CHARGE_CEIL_NONE); #endif set_state(port, PD_STATE_SNK_SWAP_SRC_DISABLE); - timeout = 10*MSEC; + timeout = 10 * MSEC; break; case PD_STATE_SNK_SWAP_SRC_DISABLE: /* Wait for PS_RDY */ if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, - get_time().val + - PD_T_PS_SOURCE_OFF, - PD_STATE_HARD_RESET_SEND); + set_state_timeout(port, get_time().val + + PD_T_PS_SOURCE_OFF, PD_STATE_HARD_RESET_SEND); break; case PD_STATE_SNK_SWAP_STANDBY: if (pd[port].last_state != pd[port].task_state) { @@ -3081,17 +2945,13 @@ void pd_run_state_machine(int port) if (pd_set_power_supply_ready(port)) { /* Restore Rd */ tcpm_set_cc(port, TYPEC_CC_RD); - timeout = 10*MSEC; - set_state(port, - PD_STATE_SNK_DISCONNECTED); + timeout = 10 * MSEC; + set_state(port, PD_STATE_SNK_DISCONNECTED); break; } /* Wait for power supply to turn on */ - set_state_timeout( - port, - get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY, - PD_STATE_SNK_SWAP_COMPLETE); + set_state_timeout(port, get_time().val + + PD_POWER_SUPPLY_TURN_ON_DELAY, PD_STATE_SNK_SWAP_COMPLETE); } break; case PD_STATE_SNK_SWAP_COMPLETE: @@ -3107,13 +2967,13 @@ void pd_run_state_machine(int port) } /* Don't send GET_SINK_CAP on swap */ - snk_cap_count = PD_SNK_CAP_RETRIES+1; + snk_cap_count = PD_SNK_CAP_RETRIES + 1; caps_count = 0; pd[port].msg_id = 0; pd[port].power_role = PD_ROLE_SOURCE; pd_update_roles(port); set_state(port, PD_STATE_SRC_DISCOVERY); - timeout = 10*MSEC; + timeout = 10 * MSEC; break; #ifdef CONFIG_USBC_VCONN_SWAP case PD_STATE_VCONN_SWAP_SEND: @@ -3192,16 +3052,13 @@ void pd_run_state_machine(int port) /* if soft reset failed, try hard reset. */ if (res < 0) { - set_state(port, - PD_STATE_HARD_RESET_SEND); - timeout = 5*MSEC; + set_state(port, PD_STATE_HARD_RESET_SEND); + timeout = 5 * MSEC; break; } - set_state_timeout( - port, - get_time().val + PD_T_SENDER_RESPONSE, - PD_STATE_HARD_RESET_SEND); + set_state_timeout(port, get_time().val + PD_T_SENDER_RESPONSE, + PD_STATE_HARD_RESET_SEND); } break; case PD_STATE_HARD_RESET_SEND: @@ -3209,19 +3066,19 @@ void pd_run_state_machine(int port) if (pd[port].last_state != pd[port].task_state) hard_reset_sent = 0; #ifdef CONFIG_CHARGE_MANAGER - if (pd[port].last_state == PD_STATE_SNK_DISCOVERY || - (pd[port].last_state == PD_STATE_SOFT_RESET && - (pd[port].flags & PD_FLAGS_VBUS_NEVER_LOW))) { + if (pd[port].last_state == PD_STATE_SNK_DISCOVERY + || (pd[port].last_state == PD_STATE_SOFT_RESET + && (pd[port].flags & PD_FLAGS_VBUS_NEVER_LOW))) { pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW; /* - * If discovery timed out, assume that we - * have a dedicated charger attached. This - * may not be a correct assumption according - * to the specification, but it generally - * works in practice and the harmful - * effects of a wrong assumption here - * are minimal. - */ + * If discovery timed out, assume that we + * have a dedicated charger attached. This + * may not be a correct assumption according + * to the specification, but it generally + * works in practice and the harmful + * effects of a wrong assumption here + * are minimal. + */ //charge_manager_update_dualrole(port, // CAP_DEDICATED); } @@ -3229,42 +3086,39 @@ void pd_run_state_machine(int port) /* try sending hard reset until it succeeds */ if (!hard_reset_sent) { - if (pd_transmit(port, TCPC_TX_HARD_RESET, - 0, NULL) < 0) { - timeout = 10*MSEC; + if (pd_transmit(port, TCPC_TX_HARD_RESET, 0, NULL) < 0) { + timeout = 10 * MSEC; break; } /* successfully sent hard reset */ hard_reset_sent = 1; /* - * If we are source, delay before cutting power - * to allow sink time to get hard reset. - */ + * If we are source, delay before cutting power + * to allow sink time to get hard reset. + */ if (pd[port].power_role == PD_ROLE_SOURCE) { - set_state_timeout(port, - get_time().val + PD_T_PS_HARD_RESET, - PD_STATE_HARD_RESET_EXECUTE); - } else { - set_state(port, + set_state_timeout(port, get_time().val + PD_T_PS_HARD_RESET, PD_STATE_HARD_RESET_EXECUTE); - timeout = 10*MSEC; + } else { + set_state(port, PD_STATE_HARD_RESET_EXECUTE); + timeout = 10 * MSEC; } } break; case PD_STATE_HARD_RESET_EXECUTE: #ifdef CONFIG_USB_PD_DUAL_ROLE /* - * If hard reset while in the last stages of power - * swap, then we need to restore our CC resistor. - */ + * If hard reset while in the last stages of power + * swap, then we need to restore our CC resistor. + */ if (pd[port].last_state == PD_STATE_SNK_SWAP_STANDBY) tcpm_set_cc(port, TYPEC_CC_RD); #endif /* reset our own state machine */ pd_execute_hard_reset(port); - timeout = 10*MSEC; + timeout = 10 * MSEC; break; #ifdef CONFIG_COMMON_RUNTIME case PD_STATE_BIST_RX: @@ -3352,15 +3206,15 @@ void pd_run_state_machine(int port) pd[port].last_state = this_state; /* - * Check for state timeout, and if not check if need to adjust - * timeout value to wake up on the next state timeout. - */ + * Check for state timeout, and if not check if need to adjust + * timeout value to wake up on the next state timeout. + */ now = get_time(); if (pd[port].timeout) { if (now.val >= pd[port].timeout) { set_state(port, pd[port].timeout_state); /* On a state timeout, run next state soon */ - timeout = timeout < 10*MSEC ? timeout : 10*MSEC; + timeout = timeout < 10 * MSEC ? timeout : 10 * MSEC; } else if (pd[port].timeout - now.val < timeout) { timeout = pd[port].timeout - now.val; } @@ -3381,23 +3235,21 @@ void pd_run_state_machine(int port) if (cc1 == TYPEC_CC_VOLT_OPEN) { set_state(port, PD_STATE_SRC_DISCONNECTED); /* Debouncing */ - timeout = 10*MSEC; + timeout = 10 * MSEC; #ifdef CONFIG_USB_PD_DUAL_ROLE /* - * If Try.SRC is configured, then ATTACHED_SRC - * needs to transition to TryWait.SNK. Change - * power role to SNK and start state timer. - */ + * If Try.SRC is configured, then ATTACHED_SRC + * needs to transition to TryWait.SNK. Change + * power role to SNK and start state timer. + */ if (pd_try_src_enable) { /* Swap roles to sink */ pd[port].power_role = PD_ROLE_SINK; tcpm_set_cc(port, TYPEC_CC_RD); /* Set timer for TryWait.SNK state */ - pd[port].try_src_marker = get_time().val - + PD_T_TRY_WAIT; + pd[port].try_src_marker = get_time().val + PD_T_TRY_WAIT; /* Advance to TryWait.SNK state */ - set_state(port, - PD_STATE_SNK_DISCONNECTED); + set_state(port, PD_STATE_SNK_DISCONNECTED); /* Mark state as TryWait.SNK */ pd[port].flags |= PD_FLAGS_TRY_SRC; } @@ -3406,55 +3258,53 @@ void pd_run_state_machine(int port) } #ifdef CONFIG_USB_PD_DUAL_ROLE /* - * Sink disconnect if VBUS is low and we are not recovering - * a hard reset. - */ - if (pd[port].power_role == PD_ROLE_SINK && - !pd_is_vbus_present(port) && - pd[port].task_state != PD_STATE_SNK_HARD_RESET_RECOVER && - pd[port].task_state != PD_STATE_HARD_RESET_EXECUTE) { + * Sink disconnect if VBUS is low and we are not recovering + * a hard reset. + */ + if (pd[port].power_role == PD_ROLE_SINK && !pd_is_vbus_present(port) + && pd[port].task_state != PD_STATE_SNK_HARD_RESET_RECOVER + && pd[port].task_state != PD_STATE_HARD_RESET_EXECUTE) { /* Sink: detect disconnect by monitoring VBUS */ set_state(port, PD_STATE_SNK_DISCONNECTED); /* set timeout small to reconnect fast */ - timeout = 5*MSEC; + timeout = 5 * MSEC; } #endif /* CONFIG_USB_PD_DUAL_ROLE */ } #ifdef CONFIG_USB_PD_DUAL_ROLE -static void dual_role_on(void) -{ - int i; - - for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) { -#ifdef CONFIG_CHARGE_MANAGER - //if (charge_manager_get_active_charge_port() != i) -#endif - pd[i].flags |= PD_FLAGS_CHECK_PR_ROLE | - PD_FLAGS_CHECK_DR_ROLE; - - pd[i].flags |= PD_FLAGS_CHECK_IDENTITY; - } - - pd_set_dual_role(PD_DRP_TOGGLE_ON); - CPRINTS("chipset -> S0"); -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, dual_role_on, HOOK_PRIO_DEFAULT); - -static void dual_role_off(void) -{ - pd_set_dual_role(PD_DRP_TOGGLE_OFF); - CPRINTS("chipset -> S3"); -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, dual_role_off, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, dual_role_off, HOOK_PRIO_DEFAULT); - -static void dual_role_force_sink(void) -{ - pd_set_dual_role(PD_DRP_FORCE_SINK); - CPRINTS("chipset -> S5"); -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, dual_role_force_sink, HOOK_PRIO_DEFAULT); +//extern "C" { +//static void dual_role_on(void) { +// int i; +// +// for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) { +//#ifdef CONFIG_CHARGE_MANAGER +// //if (charge_manager_get_active_charge_port() != i) +//#endif +// pd[i].flags |= PD_FLAGS_CHECK_PR_ROLE | +// PD_FLAGS_CHECK_DR_ROLE; +// +// pd[i].flags |= PD_FLAGS_CHECK_IDENTITY; +// } +// +// pd_set_dual_role(PD_DRP_TOGGLE_ON); +// CPRINTS("chipset -> S0"); +//} +//} +//DECLARE_HOOK(HOOK_CHIPSET_RESUME, dual_role_on, HOOK_PRIO_DEFAULT); +// +//static void dual_role_off(void) { +// pd_set_dual_role(PD_DRP_TOGGLE_OFF); +// CPRINTS("chipset -> S3"); +//} +//DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, dual_role_off, HOOK_PRIO_DEFAULT); +//DECLARE_HOOK(HOOK_CHIPSET_STARTUP, dual_role_off, HOOK_PRIO_DEFAULT); +// +//static void dual_role_force_sink(void) { +// pd_set_dual_role(PD_DRP_FORCE_SINK); +// CPRINTS("chipset -> S5"); +//} +//DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, dual_role_force_sink, HOOK_PRIO_DEFAULT); #endif /* CONFIG_USB_PD_DUAL_ROLE */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp b/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp index b32d7075..d133ebb4 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp @@ -7,13 +7,13 @@ #include "tcpm_driver.h" #include "I2C_Wrapper.hpp" +#include "I2CBB.hpp" extern const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT]; #define STATUS_OK 0 /* I2C wrapper functions - get I2C port / slave addr from config struct. */ int tcpc_write(int port, int reg, int val) { - FRToSI2C::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) &val, - 1); + I2CBB::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) &val, 1); return STATUS_OK; } @@ -21,16 +21,14 @@ int tcpc_write16(int port, int reg, int val) { uint8_t data[2]; data[0] = (0xFF) & val; data[1] = (0xFF) & (val >> 8); - FRToSI2C::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, - 2); + I2CBB::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, 2); return STATUS_OK; } int tcpc_read(int port, int reg, int *val) { uint8_t data[1]; - FRToSI2C::Mem_Read(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, - 1); + I2CBB::Mem_Read(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, 1); *val = data[0]; @@ -39,8 +37,7 @@ int tcpc_read(int port, int reg, int *val) { int tcpc_read16(int port, int reg, int *val) { uint8_t data[2]; - FRToSI2C::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, - 2); + I2CBB::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, 2); *val = data[0]; *val |= (data[1] << 8); @@ -57,13 +54,19 @@ int tcpc_xfer(int port, const uint8_t *out, int out_size, uint8_t *in, if (flags & I2C_XFER_STOP) { //Issuing a stop between the requests //Send as a Tx followed by a Rx - FRToSI2C::Transmit(tcpc_config[port].i2c_slave_addr, (uint8_t*)out, out_size); - FRToSI2C::Receive(tcpc_config[port].i2c_slave_addr, in, in_size); + I2CBB::Transmit(tcpc_config[port].i2c_slave_addr, (uint8_t*) out, + out_size); + I2CBB::Receive(tcpc_config[port].i2c_slave_addr, in, in_size); } else { //issue as a continious transmit & recieve - FRToSI2C::TransmitReceive(tcpc_config[port].i2c_slave_addr, (uint8_t*)out, + I2CBB::TransmitReceive(tcpc_config[port].i2c_slave_addr, (uint8_t*) out, out_size, in, in_size); } return STATUS_OK; } + +uint8_t fusb302_detect() { + //Probe the I2C bus for its address + return I2CBB::probe(fusb302_I2C_SLAVE_ADDR); +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h index 1cb14e60..1a560b1a 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h +++ b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h @@ -10,7 +10,7 @@ #define USB_PD_DRIVER_H_ #include "USBC_PD/usb_pd.h" - +#include "cmsis_os.h" #include //#define CONFIG_BBRAM @@ -64,8 +64,8 @@ PDO_FIXED_COMM_CAP) #define CONFIG_USB_PD_IDENTITY_HW_VERS 1 #define CONFIG_USB_PD_IDENTITY_SW_VERS 1 -#define usleep(us) (delay_us(us)) -#define msleep(us) (delay_ms(us)) +#define usleep(us) (osDelay(1)) +#define msleep(us) (osDelay(us)) typedef union { uint64_t val; diff --git a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_tcpm.h b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_tcpm.h deleted file mode 100644 index 947a88c9..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_tcpm.h +++ /dev/null @@ -1,354 +0,0 @@ -/* Copyright 2015 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 Power delivery port management */ - -#ifndef __CROS_EC_USB_PD_TCPM_H -#define __CROS_EC_USB_PD_TCPM_H - -/* List of common error codes that can be returned */ -enum ec_error_list { - /* Success - no error */ - EC_SUCCESS = 0, - /* Unknown error */ - EC_ERROR_UNKNOWN = 1, - /* Function not implemented yet */ - EC_ERROR_UNIMPLEMENTED = 2, - /* Overflow error; too much input provided. */ - EC_ERROR_OVERFLOW = 3, - /* Timeout */ - EC_ERROR_TIMEOUT = 4, - /* Invalid argument */ - EC_ERROR_INVAL = 5, - /* Already in use, or not ready yet */ - EC_ERROR_BUSY = 6, - /* Access denied */ - EC_ERROR_ACCESS_DENIED = 7, - /* Failed because component does not have power */ - EC_ERROR_NOT_POWERED = 8, - /* Failed because component is not calibrated */ - EC_ERROR_NOT_CALIBRATED = 9, - /* Failed because CRC error */ - EC_ERROR_CRC = 10, - /* Invalid console command param (PARAMn means parameter n is bad) */ - EC_ERROR_PARAM1 = 11, - EC_ERROR_PARAM2 = 12, - EC_ERROR_PARAM3 = 13, - EC_ERROR_PARAM4 = 14, - EC_ERROR_PARAM5 = 15, - EC_ERROR_PARAM6 = 16, - EC_ERROR_PARAM7 = 17, - EC_ERROR_PARAM8 = 18, - EC_ERROR_PARAM9 = 19, - /* Wrong number of params */ - EC_ERROR_PARAM_COUNT = 20, - /* Interrupt event not handled */ - EC_ERROR_NOT_HANDLED = 21, - /* Data has not changed */ - EC_ERROR_UNCHANGED = 22, - /* Memory allocation */ - EC_ERROR_MEMORY_ALLOCATION = 23, - - /* Verified boot errors */ - EC_ERROR_VBOOT_SIGNATURE = 0x1000, /* 4096 */ - EC_ERROR_VBOOT_SIG_MAGIC = 0x1001, - EC_ERROR_VBOOT_SIG_SIZE = 0x1002, - EC_ERROR_VBOOT_SIG_ALGORITHM = 0x1003, - EC_ERROR_VBOOT_HASH_ALGORITHM = 0x1004, - EC_ERROR_VBOOT_SIG_OFFSET = 0x1005, - EC_ERROR_VBOOT_DATA_SIZE = 0x1006, - - /* Verified boot key errors */ - EC_ERROR_VBOOT_KEY = 0x1100, - EC_ERROR_VBOOT_KEY_MAGIC = 0x1101, - EC_ERROR_VBOOT_KEY_SIZE = 0x1102, - - /* Verified boot data errors */ - EC_ERROR_VBOOT_DATA = 0x1200, - EC_ERROR_VBOOT_DATA_VERIFY = 0x1201, - - /* Module-internal error codes may use this range. */ - EC_ERROR_INTERNAL_FIRST = 0x10000, - EC_ERROR_INTERNAL_LAST = 0x1FFFF -}; - -/* Flags for i2c_xfer() */ -#define I2C_XFER_START (1 << 0) /* Start smbus session from idle state */ -#define I2C_XFER_STOP (1 << 1) /* Terminate smbus session with stop bit */ -#define I2C_XFER_SINGLE (I2C_XFER_START | I2C_XFER_STOP) /* One transaction */ - -/* Default retry count for transmitting */ -#define PD_RETRY_COUNT 3 - -/* Time to wait for TCPC to complete transmit */ -#define PD_T_TCPC_TX_TIMEOUT (100*MSEC) - -enum tcpc_cc_voltage_status { - TYPEC_CC_VOLT_OPEN = 0, - TYPEC_CC_VOLT_RA = 1, - TYPEC_CC_VOLT_RD = 2, - TYPEC_CC_VOLT_SNK_DEF = 5, - TYPEC_CC_VOLT_SNK_1_5 = 6, - TYPEC_CC_VOLT_SNK_3_0 = 7, -}; - -enum tcpc_cc_pull { - TYPEC_CC_RA = 0, - TYPEC_CC_RP = 1, - TYPEC_CC_RD = 2, - TYPEC_CC_OPEN = 3, -}; - -enum tcpc_rp_value { - TYPEC_RP_USB = 0, - TYPEC_RP_1A5 = 1, - TYPEC_RP_3A0 = 2, - TYPEC_RP_RESERVED = 3, -}; - -enum tcpm_transmit_type { - TCPC_TX_SOP = 0, - TCPC_TX_SOP_PRIME = 1, - TCPC_TX_SOP_PRIME_PRIME = 2, - TCPC_TX_SOP_DEBUG_PRIME = 3, - TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4, - TCPC_TX_HARD_RESET = 5, - TCPC_TX_CABLE_RESET = 6, - TCPC_TX_BIST_MODE_2 = 7 -}; - -enum tcpc_transmit_complete { - TCPC_TX_COMPLETE_SUCCESS = 0, - TCPC_TX_COMPLETE_DISCARDED = 1, - TCPC_TX_COMPLETE_FAILED = 2, -}; - -struct tcpm_drv { - /** - * Initialize TCPM driver and wait for TCPC readiness. - * - * @param port Type-C port number - * - * @return EC_SUCCESS or error - */ - int (*init)(int port); - - /** - * Release the TCPM hardware and disconnect the driver. - * Only .init() can be called after .release(). - * - * @param port Type-C port number - * - * @return EC_SUCCESS or error - */ - int (*release)(int port); - - /** - * Read the CC line status. - * - * @param port Type-C port number - * @param cc1 pointer to CC status for CC1 - * @param cc2 pointer to CC status for CC2 - * - * @return EC_SUCCESS or error - */ - int (*get_cc)(int port, int *cc1, int *cc2); - - /** - * Read VBUS - * - * @param port Type-C port number - * - * @return 0 => VBUS not detected, 1 => VBUS detected - */ - int (*get_vbus_level)(int port); - - /** - * Set the value of the CC pull-up used when we are a source. - * - * @param port Type-C port number - * @param rp One of enum tcpc_rp_value - * - * @return EC_SUCCESS or error - */ - int (*select_rp_value)(int port, int rp); - - /** - * Set the CC pull resistor. This sets our role as either source or sink. - * - * @param port Type-C port number - * @param pull One of enum tcpc_cc_pull - * - * @return EC_SUCCESS or error - */ - int (*set_cc)(int port, int pull); - - /** - * Set polarity - * - * @param port Type-C port number - * @param polarity 0=> transmit on CC1, 1=> transmit on CC2 - * - * @return EC_SUCCESS or error - */ - int (*set_polarity)(int port, int polarity); - - /** - * Set Vconn. - * - * @param port Type-C port number - * @param polarity Polarity of the CC line to read - * - * @return EC_SUCCESS or error - */ - int (*set_vconn)(int port, int enable); - - /** - * Set PD message header to use for goodCRC - * - * @param port Type-C port number - * @param power_role Power role to use in header - * @param data_role Data role to use in header - * - * @return EC_SUCCESS or error - */ - int (*set_msg_header)(int port, int power_role, int data_role); - - /** - * Set RX enable flag - * - * @param port Type-C port number - * @enable true for enable, false for disable - * - * @return EC_SUCCESS or error - */ - int (*set_rx_enable)(int port, int enable); - - /** - * Read last received PD message. - * - * @param port Type-C port number - * @param payload Pointer to location to copy payload of message - * @param header of message - * - * @return EC_SUCCESS or error - */ - int (*get_message)(int port, uint32_t *payload, int *head); - - /** - * Transmit PD message - * - * @param port Type-C port number - * @param type Transmit type - * @param header Packet header - * @param cnt Number of bytes in payload - * @param data Payload - * - * @return EC_SUCCESS or error - */ - int (*transmit)(int port, enum tcpm_transmit_type type, uint16_t header, - const uint32_t *data); - - /** - * TCPC is asserting alert - * - * @param port Type-C port number - */ - void (*tcpc_alert)(int port); - - /** - * Discharge PD VBUS on src/sink disconnect & power role swap - * - * @param port Type-C port number - * @param enable Discharge enable or disable - */ - void (*tcpc_discharge_vbus)(int port, int enable); - -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - /** - * Enable TCPC auto DRP toggling. - * - * @param port Type-C port number - * @param enable 1: Enable 0: Disable - * - * @return EC_SUCCESS or error - */ - int (*drp_toggle)(int port, int enable); -#endif - - /** - * Get firmware version. - * - * @param port Type-C port number - * @param renew Force renewal - * @param info Pointer to pointer to PD chip info - * - * @return EC_SUCCESS or error - */ - int (*get_chip_info)(int port, int renew, - struct ec_response_pd_chip_info **info); -}; - -enum tcpc_alert_polarity { - TCPC_ALERT_ACTIVE_LOW, - TCPC_ALERT_ACTIVE_HIGH, -}; - -struct tcpc_config_t { - int i2c_host_port; - int i2c_slave_addr; - const struct tcpm_drv *drv; - enum tcpc_alert_polarity pol; -}; - -/** - * Returns the PD_STATUS_TCPC_ALERT_* mask corresponding to the TCPC ports - * that are currently asserting ALERT. - * - * @return PD_STATUS_TCPC_ALERT_* mask. - */ -uint16_t tcpc_get_alert_status(void); - -/** - * Optional, set the TCPC power mode. - * - * @param port Type-C port number - * @param mode 0: off/sleep, 1: on/awake - */ -void board_set_tcpc_power_mode(int port, int mode) __attribute__((weak)); - -/** - * Initialize TCPC. - * - * @param port Type-C port number - */ -void tcpc_init(int port); - -/** - * TCPC is asserting alert - * - * @param port Type-C port number - */ -void tcpc_alert_clear(int port); - -/** - * Run TCPC task once. This checks for incoming messages, processes - * any outgoing messages, and reads CC lines. - * - * @param port Type-C port number - * @param evt Event type that woke up this task - */ -int tcpc_run(int port, int evt); - -/** - * Initialize board specific TCPC functions post TCPC initialization. - * - * @param port Type-C port number - * - * @return EC_SUCCESS or error - */ -int board_tcpc_post_init(int port) __attribute__((weak)); - -#endif /* __CROS_EC_USB_PD_TCPM_H */ diff --git a/workspace/TS100/Core/Inc/main.hpp b/workspace/TS100/Core/Inc/main.hpp index 606d920b..edfde783 100644 --- a/workspace/TS100/Core/Inc/main.hpp +++ b/workspace/TS100/Core/Inc/main.hpp @@ -6,7 +6,7 @@ extern uint8_t PCBVersion; extern uint32_t currentTempTargetDegC; extern bool settingsWereReset; - +extern bool usb_pd_available; #ifdef __cplusplus extern "C" { #endif diff --git a/workspace/TS100/Core/Src/main.cpp b/workspace/TS100/Core/Src/main.cpp index 3141a5d2..e8258523 100644 --- a/workspace/TS100/Core/Src/main.cpp +++ b/workspace/TS100/Core/Src/main.cpp @@ -13,7 +13,7 @@ #include "cmsis_os.h" uint8_t PCBVersion = 0; // File local variables - +bool usb_pd_available = false; bool settingsWereReset = false; // FreeRTOS variables @@ -57,7 +57,8 @@ int main(void) { systemSettings.ShutdownTime = 0; // No accel -> disable sleep systemSettings.sensitivity = 0; } - + resetWatchdog(); + usb_pd_available = usb_pd_detect(); resetWatchdog(); /* Create the thread(s) */ diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 13e94ea0..5ed33dc1 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -22,7 +22,7 @@ extern "C" { #include "stdlib.h" #include "string.h" #include "unit.h" - +#include "I2CBB.hpp" // File local variables extern uint32_t currentTempTargetDegC; extern uint8_t accelInit; @@ -36,720 +36,781 @@ extern osThreadId PIDTaskHandle; #define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ) static uint16_t min(uint16_t a, uint16_t b) { - if (a > b) - return b; - else - return a; + if (a > b) + return b; + else + return a; } void printVoltage() { - uint32_t volt = getInputVoltageX10(systemSettings.voltageDiv, 0); - OLED::printNumber(volt / 10, 2); - OLED::print(SymbolDot); - OLED::printNumber(volt % 10, 1); + uint32_t volt = getInputVoltageX10(systemSettings.voltageDiv, 0); + OLED::printNumber(volt / 10, 2); + OLED::print(SymbolDot); + OLED::printNumber(volt % 10, 1); } void GUIDelay() { - // Called in all UI looping tasks, - // This limits the re-draw rate to the LCD and also lets the DMA run - // As the gui task can very easily fill this bus with transactions, which will - // prevent the movement detection from running - osDelay(50); + // Called in all UI looping tasks, + // This limits the re-draw rate to the LCD and also lets the DMA run + // As the gui task can very easily fill this bus with transactions, which will + // prevent the movement detection from running + osDelay(50); } void gui_drawTipTemp(bool symbol) { - // Draw tip temp handling unit conversion & tolerance near setpoint - uint16_t Temp = 0; + // Draw tip temp handling unit conversion & tolerance near setpoint + uint16_t Temp = 0; #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) Temp = TipThermoModel::getTipInF(); else #endif - Temp = TipThermoModel::getTipInC(); + Temp = TipThermoModel::getTipInC(); - OLED::printNumber(Temp, 3); // Draw the tip temp out finally - if (symbol) { - if (OLED::getFont() == 0) { - // Big font, can draw nice symbols + OLED::printNumber(Temp, 3); // Draw the tip temp out finally + if (symbol) { + if (OLED::getFont() == 0) { + // Big font, can draw nice symbols #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) OLED::drawSymbol(0); else #endif - OLED::drawSymbol(1); - } else { - // Otherwise fall back to chars + OLED::drawSymbol(1); + } else { + // Otherwise fall back to chars #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) OLED::print(SymbolDegF); else #endif - OLED::print(SymbolDegC); - } - } + OLED::print(SymbolDegC); + } + } } #ifdef MODEL_TS100 // returns true if undervoltage has occured static bool checkVoltageForExit() { - uint16_t v = getInputVoltageX10(systemSettings.voltageDiv, 0); + uint16_t v = getInputVoltageX10(systemSettings.voltageDiv, 0); - // Dont check for first 1.5 seconds while the ADC stabilizes and the DMA fills the buffer - if (xTaskGetTickCount() > 150) { - if ((v < lookupVoltageLevel(systemSettings.cutoutSetting))) { - GUIDelay(); - OLED::clearScreen(); - OLED::setCursor(0, 0); - if (systemSettings.detailedSoldering) { - OLED::setFont(1); - OLED::print(UndervoltageString); - OLED::setCursor(0, 8); - OLED::print(InputVoltageString); - printVoltage(); - OLED::print(SymbolVolts); + // Dont check for first 1.5 seconds while the ADC stabilizes and the DMA fills the buffer + if (xTaskGetTickCount() > 150) { + if ((v < lookupVoltageLevel(systemSettings.cutoutSetting))) { + GUIDelay(); + OLED::clearScreen(); + OLED::setCursor(0, 0); + if (systemSettings.detailedSoldering) { + OLED::setFont(1); + OLED::print(UndervoltageString); + OLED::setCursor(0, 8); + OLED::print(InputVoltageString); + printVoltage(); + OLED::print(SymbolVolts); - } else { - OLED::setFont(0); - OLED::print(UVLOWarningString); - } + } else { + OLED::setFont(0); + OLED::print(UVLOWarningString); + } - OLED::refresh(); - currentTempTargetDegC = 0; - waitForButtonPress(); - return true; - } - } - return false; + OLED::refresh(); + currentTempTargetDegC = 0; + waitForButtonPress(); + return true; + } + } + return false; } #endif static void gui_drawBatteryIcon() { #ifdef MODEL_TS100 - if (systemSettings.cutoutSetting) { - // User is on a lithium battery - // we need to calculate which of the 10 levels they are on - uint8_t cellCount = systemSettings.cutoutSetting + 2; - uint32_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0) / cellCount; - // Should give us approx cell voltage X10 - // Range is 42 -> 33 = 9 steps therefore we will use battery 1-10 - if (cellV < 33) cellV = 33; - cellV -= 33; // Should leave us a number of 0-9 - if (cellV > 9) cellV = 9; - OLED::drawBattery(cellV + 1); - } else - OLED::drawSymbol(15); // Draw the DC Logo + if (systemSettings.cutoutSetting) { + // User is on a lithium battery + // we need to calculate which of the 10 levels they are on + uint8_t cellCount = systemSettings.cutoutSetting + 2; + uint32_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0) + / cellCount; + // Should give us approx cell voltage X10 + // Range is 42 -> 33 = 9 steps therefore we will use battery 1-10 + if (cellV < 33) + cellV = 33; + cellV -= 33; // Should leave us a number of 0-9 + if (cellV > 9) + cellV = 9; + OLED::drawBattery(cellV + 1); + } else + OLED::drawSymbol(15); // Draw the DC Logo #else - // On TS80 we replace this symbol with the voltage we are operating on - // If <9V then show single digit, if not show duals - uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); - if (V % 10 >= 5) - V = V / 10 + 1; // round up - else - V = V / 10; - if (V >= 10) { - int16_t xPos = OLED::getCursorX(); - OLED::setFont(1); - OLED::printNumber(1, 1); - OLED::setCursor(xPos, 8); - OLED::printNumber(V % 10, 1); - OLED::setFont(0); - OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char - } else { - OLED::printNumber(V, 1); - } + // On TS80 we replace this symbol with the voltage we are operating on + // If <9V then show single digit, if not show duals + uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); + if (V % 10 >= 5) + V = V / 10 + 1; // round up + else + V = V / 10; + if (V >= 10) { + int16_t xPos = OLED::getCursorX(); + OLED::setFont(1); + OLED::printNumber(1, 1); + OLED::setCursor(xPos, 8); + OLED::printNumber(V % 10, 1); + OLED::setFont(0); + OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char + } else { + OLED::printNumber(V, 1); + } #endif } static void gui_solderingTempAdjust() { - uint32_t lastChange = xTaskGetTickCount(); - currentTempTargetDegC = 0; - uint32_t autoRepeatTimer = 0; - uint8_t autoRepeatAcceleration = 0; - for (;;) { - OLED::setCursor(0, 0); - OLED::clearScreen(); - OLED::setFont(0); - ButtonState buttons = getButtonState(); - if (buttons) lastChange = xTaskGetTickCount(); - switch (buttons) { - case BUTTON_NONE: - // stay - break; - case BUTTON_BOTH: - // exit - return; - break; - case BUTTON_B_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp += systemSettings.TempChangeLongStep; - } else - systemSettings.SolderingTemp -= systemSettings.TempChangeLongStep; + uint32_t lastChange = xTaskGetTickCount(); + currentTempTargetDegC = 0; + uint32_t autoRepeatTimer = 0; + uint8_t autoRepeatAcceleration = 0; + for (;;) { + OLED::setCursor(0, 0); + OLED::clearScreen(); + OLED::setFont(0); + ButtonState buttons = getButtonState(); + if (buttons) + lastChange = xTaskGetTickCount(); + switch (buttons) { + case BUTTON_NONE: + // stay + break; + case BUTTON_BOTH: + // exit + return; + break; + case BUTTON_B_LONG: + if (xTaskGetTickCount() - autoRepeatTimer + + autoRepeatAcceleration> PRESS_ACCEL_INTERVAL_MAX) { + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp += + systemSettings.TempChangeLongStep; + } else + systemSettings.SolderingTemp -= + systemSettings.TempChangeLongStep; - autoRepeatTimer = xTaskGetTickCount(); - autoRepeatAcceleration += PRESS_ACCEL_STEP; - } - break; - case BUTTON_B_SHORT: - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp += systemSettings.TempChangeShortStep; - } else - systemSettings.SolderingTemp -= systemSettings.TempChangeShortStep; - break; - case BUTTON_F_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp -= systemSettings.TempChangeLongStep; - } else - systemSettings.SolderingTemp += systemSettings.TempChangeLongStep; - autoRepeatTimer = xTaskGetTickCount(); - autoRepeatAcceleration += PRESS_ACCEL_STEP; - } - break; - case BUTTON_F_SHORT: - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp -= systemSettings.TempChangeShortStep; // add 10 - } else - systemSettings.SolderingTemp += systemSettings.TempChangeShortStep; // add 10 - break; - default: - break; - } - if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) < PRESS_ACCEL_INTERVAL_MIN) { - autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; - } - // constrain between 10-450 C + autoRepeatTimer = xTaskGetTickCount(); + autoRepeatAcceleration += PRESS_ACCEL_STEP; + } + break; + case BUTTON_B_SHORT: + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp += + systemSettings.TempChangeShortStep; + } else + systemSettings.SolderingTemp -= + systemSettings.TempChangeShortStep; + break; + case BUTTON_F_LONG: + if (xTaskGetTickCount() - autoRepeatTimer + + autoRepeatAcceleration> PRESS_ACCEL_INTERVAL_MAX) { + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp -= + systemSettings.TempChangeLongStep; + } else + systemSettings.SolderingTemp += + systemSettings.TempChangeLongStep; + autoRepeatTimer = xTaskGetTickCount(); + autoRepeatAcceleration += PRESS_ACCEL_STEP; + } + break; + case BUTTON_F_SHORT: + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp -= + systemSettings.TempChangeShortStep; // add 10 + } else + systemSettings.SolderingTemp += + systemSettings.TempChangeShortStep; // add 10 + break; + default: + break; + } + if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) + < PRESS_ACCEL_INTERVAL_MIN) { + autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX + - PRESS_ACCEL_INTERVAL_MIN; + } + // constrain between 10-450 C #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { if (systemSettings.SolderingTemp > 850) systemSettings.SolderingTemp = 850; if (systemSettings.SolderingTemp < 60) systemSettings.SolderingTemp = 60; } else #endif - { - if (systemSettings.SolderingTemp > 450) systemSettings.SolderingTemp = 450; - if (systemSettings.SolderingTemp < 10) systemSettings.SolderingTemp = 10; - } + { + if (systemSettings.SolderingTemp > 450) + systemSettings.SolderingTemp = 450; + if (systemSettings.SolderingTemp < 10) + systemSettings.SolderingTemp = 10; + } - if (xTaskGetTickCount() - lastChange > 200) return; // exit if user just doesn't press anything for a bit + if (xTaskGetTickCount() - lastChange > 200) + return; // exit if user just doesn't press anything for a bit #ifdef MODEL_TS80 - if (!OLED::getRotation()) { + if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolPlus : SymbolMinus); - } else { - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolMinus : SymbolPlus); - } + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolPlus : SymbolMinus); + } else { + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolMinus : SymbolPlus); + } - OLED::print(SymbolSpace); - OLED::printNumber(systemSettings.SolderingTemp, 3); + OLED::print(SymbolSpace); + OLED::printNumber(systemSettings.SolderingTemp, 3); #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) OLED::drawSymbol(0); else #endif - { - OLED::drawSymbol(1); - } - OLED::print(SymbolSpace); + { + OLED::drawSymbol(1); + } + OLED::print(SymbolSpace); #ifdef MODEL_TS80 - if (!OLED::getRotation()) { + if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolMinus : SymbolPlus); - } else { - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolPlus : SymbolMinus); - } - OLED::refresh(); - GUIDelay(); - } + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolMinus : SymbolPlus); + } else { + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolPlus : SymbolMinus); + } + OLED::refresh(); + GUIDelay(); + } } static int gui_SolderingSleepingMode(bool stayOff) { - // Drop to sleep temperature and display until movement or button press + // Drop to sleep temperature and display until movement or button press - for (;;) { - ButtonState buttons = getButtonState(); - if (buttons) return 0; - if ((xTaskGetTickCount() > 100) && ((accelInit && (xTaskGetTickCount() - lastMovementTime < 100)) || (xTaskGetTickCount() - lastButtonTime < 100))) return 0; // user moved or pressed a button, go back to soldering + for (;;) { + ButtonState buttons = getButtonState(); + if (buttons) + return 0; + if ((xTaskGetTickCount() > 100) + && ((accelInit && (xTaskGetTickCount() - lastMovementTime < 100)) + || (xTaskGetTickCount() - lastButtonTime < 100))) + return 0; // user moved or pressed a button, go back to soldering #ifdef MODEL_TS100 - if (checkVoltageForExit()) return 1; // return non-zero on error + if (checkVoltageForExit()) + return 1; // return non-zero on error #endif #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { currentTempTargetDegC = stayOff ? 0 : TipThermoModel::convertFtoC(min(systemSettings.SleepTemp, systemSettings.SolderingTemp)); } else #endif - { - currentTempTargetDegC = stayOff ? 0 : min(systemSettings.SleepTemp, systemSettings.SolderingTemp); - } - // draw the lcd - uint16_t tipTemp; + { + currentTempTargetDegC = + stayOff ? + 0 : + min(systemSettings.SleepTemp, + systemSettings.SolderingTemp); + } + // draw the lcd + uint16_t tipTemp; #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) tipTemp = TipThermoModel::getTipInF(); else #endif - { - tipTemp = TipThermoModel::getTipInC(); - } + { + tipTemp = TipThermoModel::getTipInC(); + } - OLED::clearScreen(); - OLED::setCursor(0, 0); - if (systemSettings.detailedSoldering) { - OLED::setFont(1); - OLED::print(SleepingAdvancedString); - OLED::setCursor(0, 8); - OLED::print(SleepingTipAdvancedString); - OLED::printNumber(tipTemp, 3); + OLED::clearScreen(); + OLED::setCursor(0, 0); + if (systemSettings.detailedSoldering) { + OLED::setFont(1); + OLED::print(SleepingAdvancedString); + OLED::setCursor(0, 8); + OLED::print(SleepingTipAdvancedString); + OLED::printNumber(tipTemp, 3); #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) OLED::print(SymbolDegF); else #endif - { - OLED::print(SymbolDegC); - } + { + OLED::print(SymbolDegC); + } - OLED::print(SymbolSpace); - printVoltage(); - OLED::print(SymbolVolts); - } else { - OLED::setFont(0); - OLED::print(SleepingSimpleString); - OLED::printNumber(tipTemp, 3); + OLED::print(SymbolSpace); + printVoltage(); + OLED::print(SymbolVolts); + } else { + OLED::setFont(0); + OLED::print(SleepingSimpleString); + OLED::printNumber(tipTemp, 3); #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) OLED::drawSymbol(0); else #endif - { - OLED::drawSymbol(1); - } - } - if (systemSettings.ShutdownTime) // only allow shutdown exit if time > 0 - if (lastMovementTime) - if (((uint32_t)(xTaskGetTickCount() - lastMovementTime)) > (uint32_t)(systemSettings.ShutdownTime * 60 * 100)) { - // shutdown - currentTempTargetDegC = 0; - return 1; // we want to exit soldering mode - } - OLED::refresh(); - GUIDelay(); - } - return 0; + { + OLED::drawSymbol(1); + } + } + if (systemSettings.ShutdownTime) // only allow shutdown exit if time > 0 + if (lastMovementTime) + if (((uint32_t) (xTaskGetTickCount() - lastMovementTime)) + > (uint32_t) (systemSettings.ShutdownTime * 60 * 100)) { + // shutdown + currentTempTargetDegC = 0; + return 1; // we want to exit soldering mode + } + OLED::refresh(); + GUIDelay(); + } + return 0; } static void display_countdown(int sleepThres) { - /* - * Print seconds or minutes (if > 99 seconds) until sleep - * mode is triggered. - */ - int lastEventTime = lastButtonTime < lastMovementTime ? lastMovementTime : lastButtonTime; - int downCount = sleepThres - xTaskGetTickCount() + lastEventTime; - if (downCount > 9900) { - OLED::printNumber(downCount / 6000 + 1, 2); - OLED::print(SymbolMinutes); - } else { - OLED::printNumber(downCount / 100 + 1, 2); - OLED::print(SymbolSeconds); - } + /* + * Print seconds or minutes (if > 99 seconds) until sleep + * mode is triggered. + */ + int lastEventTime = + lastButtonTime < lastMovementTime ? + lastMovementTime : lastButtonTime; + int downCount = sleepThres - xTaskGetTickCount() + lastEventTime; + if (downCount > 9900) { + OLED::printNumber(downCount / 6000 + 1, 2); + OLED::print(SymbolMinutes); + } else { + OLED::printNumber(downCount / 100 + 1, 2); + OLED::print(SymbolSeconds); + } } static void gui_solderingMode(uint8_t jumpToSleep) { - /* - * * Soldering (gui_solderingMode) - * -> Main loop where we draw temp, and animations - * --> User presses buttons and they goto the temperature adjust screen - * ---> Display the current setpoint temperature - * ---> Use buttons to change forward and back on temperature - * ---> Both buttons or timeout for exiting - * --> Long hold front button to enter boost mode - * ---> Just temporarily sets the system into the alternate temperature for - * PID control - * --> Long hold back button to exit - * --> Double button to exit - */ - bool boostModeOn = false; + /* + * * Soldering (gui_solderingMode) + * -> Main loop where we draw temp, and animations + * --> User presses buttons and they goto the temperature adjust screen + * ---> Display the current setpoint temperature + * ---> Use buttons to change forward and back on temperature + * ---> Both buttons or timeout for exiting + * --> Long hold front button to enter boost mode + * ---> Just temporarily sets the system into the alternate temperature for + * PID control + * --> Long hold back button to exit + * --> Double button to exit + */ + bool boostModeOn = false; - uint32_t sleepThres = 0; - if (systemSettings.SleepTime < 6) - sleepThres = systemSettings.SleepTime * 10 * 100; - else - sleepThres = (systemSettings.SleepTime - 5) * 60 * 100; - if (jumpToSleep) { - if (gui_SolderingSleepingMode(jumpToSleep == 2)) { - lastButtonTime = xTaskGetTickCount(); - return; // If the function returns non-0 then exit - } - } - for (;;) { - ButtonState buttons = getButtonState(); - switch (buttons) { - case BUTTON_NONE: - // stay - boostModeOn = false; - break; - case BUTTON_BOTH: - // exit - return; - break; - case BUTTON_B_LONG: - return; // exit on back long hold - break; - case BUTTON_F_LONG: - // if boost mode is enabled turn it on - if (systemSettings.boostModeEnabled) boostModeOn = true; - break; - case BUTTON_F_SHORT: - case BUTTON_B_SHORT: { - uint16_t oldTemp = systemSettings.SolderingTemp; - gui_solderingTempAdjust(); // goto adjust temp mode - if (oldTemp != systemSettings.SolderingTemp) { - saveSettings(); // only save on change - } - } break; - default: - break; - } - // else we update the screen information - OLED::setCursor(0, 0); - OLED::clearScreen(); - OLED::setFont(0); - // Draw in the screen details - if (systemSettings.detailedSoldering) { - OLED::setFont(1); - OLED::print(SolderingAdvancedPowerPrompt); // Power: - OLED::printNumber(x10WattHistory.average() / 10, 2); - OLED::print(SymbolDot); - OLED::printNumber(x10WattHistory.average() % 10, 1); - OLED::print(SymbolWatts); + uint32_t sleepThres = 0; + if (systemSettings.SleepTime < 6) + sleepThres = systemSettings.SleepTime * 10 * 100; + else + sleepThres = (systemSettings.SleepTime - 5) * 60 * 100; + if (jumpToSleep) { + if (gui_SolderingSleepingMode(jumpToSleep == 2)) { + lastButtonTime = xTaskGetTickCount(); + return; // If the function returns non-0 then exit + } + } + for (;;) { + ButtonState buttons = getButtonState(); + switch (buttons) { + case BUTTON_NONE: + // stay + boostModeOn = false; + break; + case BUTTON_BOTH: + // exit + return; + break; + case BUTTON_B_LONG: + return; // exit on back long hold + break; + case BUTTON_F_LONG: + // if boost mode is enabled turn it on + if (systemSettings.boostModeEnabled) + boostModeOn = true; + break; + case BUTTON_F_SHORT: + case BUTTON_B_SHORT: { + uint16_t oldTemp = systemSettings.SolderingTemp; + gui_solderingTempAdjust(); // goto adjust temp mode + if (oldTemp != systemSettings.SolderingTemp) { + saveSettings(); // only save on change + } + } + break; + default: + break; + } + // else we update the screen information + OLED::setCursor(0, 0); + OLED::clearScreen(); + OLED::setFont(0); + // Draw in the screen details + if (systemSettings.detailedSoldering) { + OLED::setFont(1); + OLED::print(SolderingAdvancedPowerPrompt); // Power: + OLED::printNumber(x10WattHistory.average() / 10, 2); + OLED::print(SymbolDot); + OLED::printNumber(x10WattHistory.average() % 10, 1); + OLED::print(SymbolWatts); - if (systemSettings.sensitivity && systemSettings.SleepTime) { - OLED::print(SymbolSpace); - display_countdown(sleepThres); - } + if (systemSettings.sensitivity && systemSettings.SleepTime) { + OLED::print(SymbolSpace); + display_countdown(sleepThres); + } - OLED::setCursor(0, 8); - OLED::print(SleepingTipAdvancedString); - // OLED::printNumber( - // TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0)), 5); // Draw the tip temp out finally + OLED::setCursor(0, 8); + OLED::print(SleepingTipAdvancedString); + // OLED::printNumber( + // TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0)), 5); // Draw the tip temp out finally - gui_drawTipTemp(true); - OLED::print(SymbolSpace); - printVoltage(); - OLED::print(SymbolVolts); - } else { - // We switch the layout direction depending on the orientation of the - // OLED:: - if (OLED::getRotation()) { - // battery - gui_drawBatteryIcon(); - OLED::print(SymbolSpace); // Space out gap between battery <-> temp - gui_drawTipTemp(true); // Draw current tip temp + gui_drawTipTemp(true); + OLED::print(SymbolSpace); + printVoltage(); + OLED::print(SymbolVolts); + } else { + // We switch the layout direction depending on the orientation of the + // OLED:: + if (OLED::getRotation()) { + // battery + gui_drawBatteryIcon(); + OLED::print(SymbolSpace); // Space out gap between battery <-> temp + gui_drawTipTemp(true); // Draw current tip temp - // We draw boost arrow if boosting, or else gap temp <-> heat - // indicator - if (boostModeOn) - OLED::drawSymbol(2); - else - OLED::print(SymbolSpace); + // We draw boost arrow if boosting, or else gap temp <-> heat + // indicator + if (boostModeOn) + OLED::drawSymbol(2); + else + OLED::print(SymbolSpace); - // Draw heating/cooling symbols - OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); - } else { - // Draw heating/cooling symbols - OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); - // We draw boost arrow if boosting, or else gap temp <-> heat - // indicator - if (boostModeOn) - OLED::drawSymbol(2); - else - OLED::print(SymbolSpace); - gui_drawTipTemp(true); // Draw current tip temp + // Draw heating/cooling symbols + OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); + } else { + // Draw heating/cooling symbols + OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); + // We draw boost arrow if boosting, or else gap temp <-> heat + // indicator + if (boostModeOn) + OLED::drawSymbol(2); + else + OLED::print(SymbolSpace); + gui_drawTipTemp(true); // Draw current tip temp - OLED::print(SymbolSpace); // Space out gap between battery <-> temp + OLED::print(SymbolSpace); // Space out gap between battery <-> temp - gui_drawBatteryIcon(); - } - } - OLED::refresh(); + gui_drawBatteryIcon(); + } + } + OLED::refresh(); - // Update the setpoints for the temperature - if (boostModeOn) { + // Update the setpoints for the temperature + if (boostModeOn) { #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.BoostTemp); else #endif - { - currentTempTargetDegC = (systemSettings.BoostTemp); - } - } else { + { + currentTempTargetDegC = (systemSettings.BoostTemp); + } + } else { #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.SolderingTemp); else #endif - { - currentTempTargetDegC = (systemSettings.SolderingTemp); - } - } + { + currentTempTargetDegC = (systemSettings.SolderingTemp); + } + } #ifdef MODEL_TS100 - // Undervoltage test - if (checkVoltageForExit()) { - lastButtonTime = xTaskGetTickCount(); - return; - } + // Undervoltage test + if (checkVoltageForExit()) { + lastButtonTime = xTaskGetTickCount(); + return; + } #else - // on the TS80 we only want to check for over voltage to prevent tip damage - /*if (getInputVoltageX10(systemSettings.voltageDiv, 1) > 150) { - lastButtonTime = xTaskGetTickCount(); - currentlyActiveTemperatureTarget = 0; - return; // Over voltage - }*/ + // on the TS80 we only want to check for over voltage to prevent tip damage + /*if (getInputVoltageX10(systemSettings.voltageDiv, 1) > 150) { + lastButtonTime = xTaskGetTickCount(); + currentlyActiveTemperatureTarget = 0; + return; // Over voltage + }*/ #endif - if (systemSettings.sensitivity && systemSettings.SleepTime) - if (xTaskGetTickCount() - lastMovementTime > sleepThres && xTaskGetTickCount() - lastButtonTime > sleepThres) { - if (gui_SolderingSleepingMode(false)) { - return; // If the function returns non-0 then exit - } - } - // slow down ui update rate - GUIDelay(); - } + if (systemSettings.sensitivity && systemSettings.SleepTime) + if (xTaskGetTickCount() - lastMovementTime > sleepThres + && xTaskGetTickCount() - lastButtonTime > sleepThres) { + if (gui_SolderingSleepingMode(false)) { + return; // If the function returns non-0 then exit + } + } + // slow down ui update rate + GUIDelay(); + } } void showDebugMenu(void) { - uint8_t screen = 0; - ButtonState b; - for (;;) { - OLED::clearScreen(); // Ensure the buffer starts clean - OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) - OLED::setFont(1); // small font - OLED::print(SymbolVersionNumber); // Print version number - OLED::setCursor(0, 8); // second line - OLED::print(DebugMenu[screen]); - switch (screen) { - case 0: // Just prints date - break; - case 1: - // High water mark for GUI - OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 5); - break; - case 2: - // High water mark for the Movement task - OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 5); - break; - case 3: - // High water mark for the PID task - OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 5); - break; - case 4: - // system up time stamp - OLED::printNumber(xTaskGetTickCount() / 100, 5); - break; - case 5: - // Movement time stamp - OLED::printNumber(lastMovementTime / 100, 5); - break; - case 6: - // Raw Tip - { - uint32_t temp = systemSettings.CalibrationOffset; - systemSettings.CalibrationOffset = 0; - OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(1)), 6); - systemSettings.CalibrationOffset = temp; - } - break; - case 7: - // Temp in C - OLED::printNumber(TipThermoModel::getTipInC(1), 5); - break; - case 8: - // Handle Temp - OLED::printNumber(getHandleTemperature(), 3); - break; - case 9: - // Voltage input - printVoltage(); - break; - case 10: - // Print PCB ID number - OLED::printNumber(PCBVersion, 1); - break; - default: - break; - } + uint8_t screen = 0; + ButtonState b; + for (;;) { + OLED::clearScreen(); // Ensure the buffer starts clean + OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) + OLED::setFont(1); // small font + OLED::print(SymbolVersionNumber); // Print version number + OLED::setCursor(0, 8); // second line + OLED::print(DebugMenu[screen]); + switch (screen) { + case 0: // Just prints date + break; + case 1: + // High water mark for GUI + OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 5); + break; + case 2: + // High water mark for the Movement task + OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 5); + break; + case 3: + // High water mark for the PID task + OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 5); + break; + case 4: + // system up time stamp + OLED::printNumber(xTaskGetTickCount() / 100, 5); + break; + case 5: + // Movement time stamp + OLED::printNumber(lastMovementTime / 100, 5); + break; + case 6: + // Raw Tip + { + uint32_t temp = systemSettings.CalibrationOffset; + systemSettings.CalibrationOffset = 0; + OLED::printNumber( + TipThermoModel::convertTipRawADCTouV(getTipRawTemp(1)), 6); + systemSettings.CalibrationOffset = temp; + } + break; + case 7: + // Temp in C + OLED::printNumber(TipThermoModel::getTipInC(1), 5); + break; + case 8: + // Handle Temp + OLED::printNumber(getHandleTemperature(), 3); + break; + case 9: + // Voltage input + printVoltage(); + break; + case 10: + // Print PCB ID number + OLED::printNumber(PCBVersion, 1); + break; + default: + break; + } - OLED::refresh(); - b = getButtonState(); - if (b == BUTTON_B_SHORT) - return; - else if (b == BUTTON_F_SHORT) { - screen++; - screen = screen % 11; - } - GUIDelay(); - } + OLED::refresh(); + b = getButtonState(); + if (b == BUTTON_B_SHORT) + return; + else if (b == BUTTON_F_SHORT) { + screen++; + screen = screen % 11; + } + GUIDelay(); + } } /* StartGUITask function */ void startGUITask(void const *argument __unused) { - uint8_t tempWarningState = 0; - bool buttonLockout = false; - bool tempOnDisplay = false; - getTipRawTemp(1); // reset filter - OLED::setRotation(systemSettings.OrientationMode & 1); - uint32_t ticks = xTaskGetTickCount(); - ticks += 400; // 4 seconds from now - while (xTaskGetTickCount() < ticks) { - if (showBootLogoIfavailable() == false) ticks = xTaskGetTickCount(); - ButtonState buttons = getButtonState(); - if (buttons) ticks = xTaskGetTickCount(); // make timeout now so we will exit - GUIDelay(); - } + uint8_t tempWarningState = 0; + bool buttonLockout = false; + bool tempOnDisplay = false; + getTipRawTemp(1); // reset filter + OLED::setRotation(systemSettings.OrientationMode & 1); + uint32_t ticks = xTaskGetTickCount(); + ticks += 400; // 4 seconds from now + while (xTaskGetTickCount() < ticks) { + if (showBootLogoIfavailable() == false) + ticks = xTaskGetTickCount(); + ButtonState buttons = getButtonState(); + if (buttons) + ticks = xTaskGetTickCount(); // make timeout now so we will exit + GUIDelay(); + } - if (settingsWereReset) { - // Display alert settings were reset - OLED::clearScreen(); - OLED::setFont(1); - OLED::setCursor(0, 0); - OLED::print(SettingsResetMessage); - OLED::refresh(); - waitForButtonPressOrTimeout(1000); - } + if (settingsWereReset) { + // Display alert settings were reset + OLED::clearScreen(); + OLED::setFont(1); + OLED::setCursor(0, 0); + OLED::print(SettingsResetMessage); + OLED::refresh(); + waitForButtonPressOrTimeout(1000); + } - if (systemSettings.autoStartMode) { - // jump directly to the autostart mode - if (systemSettings.autoStartMode == 1) { - gui_solderingMode(0); - buttonLockout = true; - } else if (systemSettings.autoStartMode == 2) { - gui_solderingMode(1); - buttonLockout = true; - } else if (systemSettings.autoStartMode == 3) { - gui_solderingMode(2); - buttonLockout = true; - } - } + if (usb_pd_available) { + OLED::clearScreen(); + OLED::setFont(1); + OLED::setCursor(0, 0); + OLED::print(InputVoltageString); + OLED::refresh(); + waitForButtonPressOrTimeout(1000); + } - for (;;) { - ButtonState buttons = getButtonState(); - if (buttons != BUTTON_NONE) { - OLED::setDisplayState(OLED::DisplayState::ON); - OLED::setFont(0); - } - if (tempWarningState == 2) buttons = BUTTON_F_SHORT; - if (buttons != BUTTON_NONE && buttonLockout) - buttons = BUTTON_NONE; - else - buttonLockout = false; + if (systemSettings.autoStartMode) { + // jump directly to the autostart mode + if (systemSettings.autoStartMode == 1) { + gui_solderingMode(0); + buttonLockout = true; + } else if (systemSettings.autoStartMode == 2) { + gui_solderingMode(1); + buttonLockout = true; + } else if (systemSettings.autoStartMode == 3) { + gui_solderingMode(2); + buttonLockout = true; + } + } - switch (buttons) { - case BUTTON_NONE: - // Do nothing - break; - case BUTTON_BOTH: - // Not used yet - // In multi-language this might be used to reset language on a long hold - // or some such - break; + for (;;) { + ButtonState buttons = getButtonState(); + if (buttons != BUTTON_NONE) { + OLED::setDisplayState(OLED::DisplayState::ON); + OLED::setFont(0); + } + if (tempWarningState == 2) + buttons = BUTTON_F_SHORT; + if (buttons != BUTTON_NONE && buttonLockout) + buttons = BUTTON_NONE; + else + buttonLockout = false; - case BUTTON_B_LONG: - // Show the version information - showDebugMenu(); - break; - case BUTTON_F_LONG: - gui_solderingTempAdjust(); - saveSettings(); - break; - case BUTTON_F_SHORT: - gui_solderingMode(0); // enter soldering mode - buttonLockout = true; - break; - case BUTTON_B_SHORT: - enterSettingsMenu(); // enter the settings menu - buttonLockout = true; - break; - default: - break; - } + switch (buttons) { + case BUTTON_NONE: + // Do nothing + break; + case BUTTON_BOTH: + // Not used yet + // In multi-language this might be used to reset language on a long hold + // or some such + break; - currentTempTargetDegC = 0; // ensure tip is off - getInputVoltageX10(systemSettings.voltageDiv, 0); - uint16_t tipTemp = TipThermoModel::getTipInC(); + case BUTTON_B_LONG: + // Show the version information + showDebugMenu(); + break; + case BUTTON_F_LONG: + gui_solderingTempAdjust(); + saveSettings(); + break; + case BUTTON_F_SHORT: + gui_solderingMode(0); // enter soldering mode + buttonLockout = true; + break; + case BUTTON_B_SHORT: + enterSettingsMenu(); // enter the settings menu + buttonLockout = true; + break; + default: + break; + } - // Preemptively turn the display on. Turn it off if and only if - // the tip temperature is below 50 degrees C *and* motion sleep - // detection is enabled *and* there has been no activity (movement or - // button presses) in a while. - OLED::setDisplayState(OLED::DisplayState::ON); + currentTempTargetDegC = 0; // ensure tip is off + getInputVoltageX10(systemSettings.voltageDiv, 0); + uint16_t tipTemp = TipThermoModel::getTipInC(); - if ((tipTemp < 50) && systemSettings.sensitivity && (((xTaskGetTickCount() - lastMovementTime) > MOVEMENT_INACTIVITY_TIME) && ((xTaskGetTickCount() - lastButtonTime) > BUTTON_INACTIVITY_TIME))) { - OLED::setDisplayState(OLED::DisplayState::OFF); - } + // Preemptively turn the display on. Turn it off if and only if + // the tip temperature is below 50 degrees C *and* motion sleep + // detection is enabled *and* there has been no activity (movement or + // button presses) in a while. + OLED::setDisplayState(OLED::DisplayState::ON); - // Clear the lcd buffer - OLED::clearScreen(); - OLED::setCursor(0, 0); - if (systemSettings.detailedIDLE) { - OLED::setFont(1); - if (tipTemp > 470) { - OLED::print(TipDisconnectedString); - } else { - OLED::print(IdleTipString); - gui_drawTipTemp(false); - OLED::print(IdleSetString); - OLED::printNumber(systemSettings.SolderingTemp, 3); - } - OLED::setCursor(0, 8); + if ((tipTemp < 50) && systemSettings.sensitivity + && (((xTaskGetTickCount() - lastMovementTime) + > MOVEMENT_INACTIVITY_TIME) + && ((xTaskGetTickCount() - lastButtonTime) + > BUTTON_INACTIVITY_TIME))) { + OLED::setDisplayState(OLED::DisplayState::OFF); + } - OLED::print(InputVoltageString); - printVoltage(); + // Clear the lcd buffer + OLED::clearScreen(); + OLED::setCursor(0, 0); + if (systemSettings.detailedIDLE) { + OLED::setFont(1); + if (tipTemp > 470) { + OLED::print(TipDisconnectedString); + } else { + OLED::print(IdleTipString); + gui_drawTipTemp(false); + OLED::print(IdleSetString); + OLED::printNumber(systemSettings.SolderingTemp, 3); + } + OLED::setCursor(0, 8); - } else { - OLED::setFont(0); + OLED::print(InputVoltageString); + printVoltage(); + + } else { + OLED::setFont(0); #ifdef MODEL_TS80 - if (!OLED::getRotation()) { + if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - OLED::drawArea(12, 0, 84, 16, idleScreenBG); - OLED::setCursor(0, 0); - gui_drawBatteryIcon(); - } else { - OLED::drawArea(0, 0, 84, 16, idleScreenBGF); // Needs to be flipped so button ends up - // on right side of screen - OLED::setCursor(84, 0); - gui_drawBatteryIcon(); - } - if (tipTemp > 55) - tempOnDisplay = true; - else if (tipTemp < 45) - tempOnDisplay = false; - if (tempOnDisplay) { - // draw temp over the start soldering button - // Location changes on screen rotation + OLED::drawArea(12, 0, 84, 16, idleScreenBG); + OLED::setCursor(0, 0); + gui_drawBatteryIcon(); + } else { + OLED::drawArea(0, 0, 84, 16, idleScreenBGF); // Needs to be flipped so button ends up + // on right side of screen + OLED::setCursor(84, 0); + gui_drawBatteryIcon(); + } + if (tipTemp > 55) + tempOnDisplay = true; + else if (tipTemp < 45) + tempOnDisplay = false; + if (tempOnDisplay) { + // draw temp over the start soldering button + // Location changes on screen rotation #ifdef MODEL_TS80 - if (!OLED::getRotation()) { + if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - // in right handed mode we want to draw over the first part - OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp - OLED::setCursor(56, 0); + // in right handed mode we want to draw over the first part + OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp + OLED::setCursor(56, 0); - } else { - OLED::fillArea(0, 0, 41, 16, 0); // clear the area - OLED::setCursor(0, 0); - } - // draw in the temp - if (!(systemSettings.coolingTempBlink && (xTaskGetTickCount() % 25 < 16))) gui_drawTipTemp(false); // draw in the temp - } - } - OLED::refresh(); - GUIDelay(); - } + } else { + OLED::fillArea(0, 0, 41, 16, 0); // clear the area + OLED::setCursor(0, 0); + } + // draw in the temp + if (!(systemSettings.coolingTempBlink + && (xTaskGetTickCount() % 25 < 16))) + gui_drawTipTemp(false); // draw in the temp + } + } + OLED::refresh(); + GUIDelay(); + } } From 2c0b14edd4ad56b16ba05fc34a7a3b4ed307c211 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 12 Jun 2020 22:13:40 +1000 Subject: [PATCH 04/53] Culling until fits in code Does _not_ negotiate correctly :( --- workspace/TS100/Core/BSP/Miniware/Power.cpp | 28 +- .../Inc/stm32f1xx_hal_rcc.h | 2 +- .../TS100/Core/BSP/Miniware/postRTOS.cpp | 9 +- .../TS100/Core/Drivers/FUSB302/FUSB302.cpp | 318 ++- .../Core/Drivers/FUSB302/USBC_PD/usb_pd.h | 192 +- .../{usb_pd_policy.c => usb_pd_policy.cpp} | 347 +--- .../FUSB302/USBC_PD/usb_pd_protocol.cpp | 1789 ++++++++--------- .../Core/Drivers/FUSB302/USBC_TCPM/tcpm.h | 134 +- .../Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h | 66 +- .../Core/Drivers/FUSB302/tcpm_driver.cpp | 28 +- .../Core/Drivers/FUSB302/usb_pd_driver.cpp | 236 +-- .../Core/Drivers/FUSB302/usb_pd_driver.h | 4 +- workspace/TS100/Core/Src/gui.cpp | 3 +- 13 files changed, 1377 insertions(+), 1779 deletions(-) rename workspace/TS100/Core/Drivers/FUSB302/USBC_PD/{usb_pd_policy.c => usb_pd_policy.cpp} (66%) diff --git a/workspace/TS100/Core/BSP/Miniware/Power.cpp b/workspace/TS100/Core/BSP/Miniware/Power.cpp index c72e6207..cd552479 100644 --- a/workspace/TS100/Core/BSP/Miniware/Power.cpp +++ b/workspace/TS100/Core/BSP/Miniware/Power.cpp @@ -9,23 +9,37 @@ void power_probe() { // If TS100 - noop #ifdef MODEL_TS80 + startQC(systemSettings.voltageDiv); - startQC(systemSettings.voltageDiv); - - seekQC((systemSettings.cutoutSetting) ? 120 : 90, - systemSettings.voltageDiv); // this will move the QC output to the preferred voltage to start with + seekQC((systemSettings.cutoutSetting) ? 120 : 90, + systemSettings.voltageDiv); // this will move the QC output to the preferred voltage to start with #endif } void power_check() { #ifdef MODEL_TS80 - QC_resync(); + QC_resync(); + if (FUSB302_present) { + pd_run_state_machine(); + if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9) == GPIO_PIN_RESET) { + tcpc_alert(); + } + } + #endif } -uint8_t usb_pd_detect(){ +uint8_t usb_pd_detect() { #ifdef MODEL_TS80 - FUSB302_present=fusb302_detect(); + FUSB302_present = fusb302_detect(); + if (FUSB302_present) { + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } return FUSB302_present; #endif return false; diff --git a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h index 0e3bdfc5..10c507ba 100644 --- a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h +++ b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h @@ -291,7 +291,7 @@ typedef struct /** @defgroup RCC_Flag Flags * Elements values convention: XXXYYYYYb * - YYYYY : Flag position in the register - * - XXX : Register index + * - X XX : Register index * - 001: CR register * - 010: BDCR register * - 011: CSR register diff --git a/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp b/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp index deb78e5d..7b596758 100644 --- a/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp +++ b/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp @@ -8,7 +8,14 @@ #include "stdlib.h" #include "task.h" #include "I2C_Wrapper.hpp" +#include "USBC_TCPM/tcpm.h" void postRToSInit() { - // Any after RTos setup + // Any after RTos setup FRToSI2C::FRToSInit(); +#ifdef MODEL_TS80 + tcpm_init(); + osDelay(50); + pd_init(); + osDelay(50); +#endif } diff --git a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.cpp b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.cpp index 44739e8d..f4f657bb 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.cpp @@ -14,8 +14,8 @@ #include "I2C_Wrapper.hpp" #define PACKET_IS_GOOD_CRC(head) (PD_HEADER_TYPE(head) == PD_CTRL_GOOD_CRC && \ PD_HEADER_CNT(head) == 0) -const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT] = { { 0, - fusb302_I2C_SLAVE_ADDR, &fusb302_tcpm_drv, TCPC_ALERT_ACTIVE_LOW }, }; +const struct tcpc_config_t tcpc_config = { +fusb302_I2C_SLAVE_ADDR, &fusb302_tcpm_drv }; static struct fusb302_chip_state { int cc_polarity; int vconn_enabled; @@ -24,15 +24,15 @@ static struct fusb302_chip_state { int rx_enable; uint8_t mdac_vnc; uint8_t mdac_rd; -} state[CONFIG_USB_PD_PORT_COUNT]; +} state; /* * Bring the FUSB302 out of reset after Hard Reset signaling. This will * automatically flush both the Rx and Tx FIFOs. */ -static void fusb302_pd_reset(int port) { +static void fusb302_pd_reset() { - tcpc_write(port, TCPC_REG_RESET, TCPC_REG_RESET_PD_RESET); + tcpc_write( TCPC_REG_RESET, TCPC_REG_RESET_PD_RESET); } @@ -40,7 +40,7 @@ static void fusb302_pd_reset(int port) { * Flush our Rx FIFO. To prevent packet framing issues, this function should * only be called when Rx is disabled. */ -static void fusb302_flush_rx_fifo(int port) { +static void fusb302_flush_rx_fifo() { /* * other bits in the register _should_ be 0 * until the day we support other SOP* types... @@ -48,39 +48,39 @@ static void fusb302_flush_rx_fifo(int port) { * value should be so we don't clobber it here! */ - tcpc_write(port, TCPC_REG_CONTROL1, TCPC_REG_CONTROL1_RX_FLUSH); + tcpc_write( TCPC_REG_CONTROL1, TCPC_REG_CONTROL1_RX_FLUSH); } -static void fusb302_flush_tx_fifo(int port) { +static void fusb302_flush_tx_fifo() { int reg; - tcpc_read(port, TCPC_REG_CONTROL0, ®); + tcpc_read( TCPC_REG_CONTROL0, ®); reg |= TCPC_REG_CONTROL0_TX_FLUSH; - tcpc_write(port, TCPC_REG_CONTROL0, reg); + tcpc_write( TCPC_REG_CONTROL0, reg); } -static void fusb302_auto_goodcrc_enable(int port, int enable) { +static void fusb302_auto_goodcrc_enable(int enable) { int reg; - tcpc_read(port, TCPC_REG_SWITCHES1, ®); + tcpc_read( TCPC_REG_SWITCHES1, ®); if (enable) reg |= TCPC_REG_SWITCHES1_AUTO_GCRC; else reg &= ~TCPC_REG_SWITCHES1_AUTO_GCRC; - tcpc_write(port, TCPC_REG_SWITCHES1, reg); + tcpc_write( TCPC_REG_SWITCHES1, reg); } /* Convert BC LVL values (in FUSB302) to Type-C CC Voltage Status */ -static int convert_bc_lvl(int port, int bc_lvl) { +static int convert_bc_lvl(int bc_lvl) { /* assume OPEN unless one of the following conditions is true... */ int ret = TYPEC_CC_VOLT_OPEN; - if (state[port].pulling_up) { + if (state.pulling_up) { if (bc_lvl == 0x00) ret = TYPEC_CC_VOLT_RA; else if (bc_lvl < 0x3) @@ -97,13 +97,13 @@ static int convert_bc_lvl(int port, int bc_lvl) { return ret; } -static int measure_cc_pin_source(int port, int cc_measure) { +static int measure_cc_pin_source(int cc_measure) { int switches0_reg; int reg; int cc_lvl; /* Read status register */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); + tcpc_read( TCPC_REG_SWITCHES0, ®); /* Save current value */ switches0_reg = reg; /* Clear pull-up register settings and measure bits */ @@ -117,16 +117,16 @@ static int measure_cc_pin_source(int port, int cc_measure) { reg |= cc_measure; /* Set measurement switch */ - tcpc_write(port, TCPC_REG_SWITCHES0, reg); + tcpc_write( TCPC_REG_SWITCHES0, reg); /* Set MDAC for Open vs Rd/Ra comparison */ - tcpc_write(port, TCPC_REG_MEASURE, state[port].mdac_vnc); + tcpc_write( TCPC_REG_MEASURE, state.mdac_vnc); /* Wait on measurement */ usleep(250); /* Read status register */ - tcpc_read(port, TCPC_REG_STATUS0, ®); + tcpc_read( TCPC_REG_STATUS0, ®); /* Assume open */ cc_lvl = TYPEC_CC_VOLT_OPEN; @@ -134,13 +134,13 @@ static int measure_cc_pin_source(int port, int cc_measure) { /* CC level is below the 'no connect' threshold (vOpen) */ if ((reg & TCPC_REG_STATUS0_COMP) == 0) { /* Set MDAC for Rd vs Ra comparison */ - tcpc_write(port, TCPC_REG_MEASURE, state[port].mdac_rd); + tcpc_write( TCPC_REG_MEASURE, state.mdac_rd); /* Wait on measurement */ usleep(250); /* Read status register */ - tcpc_read(port, TCPC_REG_STATUS0, ®); + tcpc_read( TCPC_REG_STATUS0, ®); cc_lvl = (reg & TCPC_REG_STATUS0_COMP) ? @@ -148,32 +148,32 @@ static int measure_cc_pin_source(int port, int cc_measure) { } /* Restore SWITCHES0 register to its value prior */ - tcpc_write(port, TCPC_REG_SWITCHES0, switches0_reg); + tcpc_write( TCPC_REG_SWITCHES0, switches0_reg); return cc_lvl; } /* Determine cc pin state for source when in manual detect mode */ -static void detect_cc_pin_source_manual(int port, int *cc1_lvl, int *cc2_lvl) { +static void detect_cc_pin_source_manual(int *cc1_lvl, int *cc2_lvl) { int cc1_measure = TCPC_REG_SWITCHES0_MEAS_CC1; int cc2_measure = TCPC_REG_SWITCHES0_MEAS_CC2; - if (state[port].vconn_enabled) { + if (state.vconn_enabled) { /* If VCONN enabled, measure cc_pin that matches polarity */ - if (state[port].cc_polarity) - *cc2_lvl = measure_cc_pin_source(port, cc2_measure); + if (state.cc_polarity) + *cc2_lvl = measure_cc_pin_source(cc2_measure); else - *cc1_lvl = measure_cc_pin_source(port, cc1_measure); + *cc1_lvl = measure_cc_pin_source(cc1_measure); } else { /* If VCONN not enabled, measure both cc1 and cc2 */ - *cc1_lvl = measure_cc_pin_source(port, cc1_measure); - *cc2_lvl = measure_cc_pin_source(port, cc2_measure); + *cc1_lvl = measure_cc_pin_source(cc1_measure); + *cc2_lvl = measure_cc_pin_source(cc2_measure); } } /* Determine cc pin state for sink */ -static void detect_cc_pin_sink(int port, int *cc1, int *cc2) { +static void detect_cc_pin_sink(int *cc1, int *cc2) { int reg; int orig_meas_cc1; int orig_meas_cc2; @@ -183,7 +183,7 @@ static void detect_cc_pin_sink(int port, int *cc1, int *cc2) { /* * Measure CC1 first. */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); + tcpc_read( TCPC_REG_SWITCHES0, ®); /* save original state to be returned to later... */ if (reg & TCPC_REG_SWITCHES0_MEAS_CC1) @@ -200,14 +200,14 @@ static void detect_cc_pin_sink(int port, int *cc1, int *cc2) { reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; reg |= TCPC_REG_SWITCHES0_MEAS_CC1; - tcpc_write(port, TCPC_REG_SWITCHES0, reg); + tcpc_write( TCPC_REG_SWITCHES0, reg); /* CC1 is now being measured by FUSB302. */ /* Wait on measurement */ usleep(250); - tcpc_read(port, TCPC_REG_STATUS0, &bc_lvl_cc1); + tcpc_read( TCPC_REG_STATUS0, &bc_lvl_cc1); /* mask away unwanted bits */ bc_lvl_cc1 &= (TCPC_REG_STATUS0_BC_LVL0 | TCPC_REG_STATUS0_BC_LVL1); @@ -216,29 +216,29 @@ static void detect_cc_pin_sink(int port, int *cc1, int *cc2) { * Measure CC2 next. */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); + tcpc_read( TCPC_REG_SWITCHES0, ®); /* Disable CC1 measurement switch, enable CC2 measurement switch */ reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1; reg |= TCPC_REG_SWITCHES0_MEAS_CC2; - tcpc_write(port, TCPC_REG_SWITCHES0, reg); + tcpc_write( TCPC_REG_SWITCHES0, reg); /* CC2 is now being measured by FUSB302. */ /* Wait on measurement */ usleep(250); - tcpc_read(port, TCPC_REG_STATUS0, &bc_lvl_cc2); + tcpc_read( TCPC_REG_STATUS0, &bc_lvl_cc2); /* mask away unwanted bits */ bc_lvl_cc2 &= (TCPC_REG_STATUS0_BC_LVL0 | TCPC_REG_STATUS0_BC_LVL1); - *cc1 = convert_bc_lvl(port, bc_lvl_cc1); - *cc2 = convert_bc_lvl(port, bc_lvl_cc2); + *cc1 = convert_bc_lvl(bc_lvl_cc1); + *cc2 = convert_bc_lvl(bc_lvl_cc2); /* return MEAS_CC1/2 switches to original state */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); + tcpc_read( TCPC_REG_SWITCHES0, ®); if (orig_meas_cc1) reg |= TCPC_REG_SWITCHES0_MEAS_CC1; else @@ -248,7 +248,7 @@ static void detect_cc_pin_sink(int port, int *cc1, int *cc2) { else reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; - tcpc_write(port, TCPC_REG_SWITCHES0, reg); + tcpc_write( TCPC_REG_SWITCHES0, reg); } @@ -268,7 +268,7 @@ static int get_num_bytes(uint16_t header) { return rv; } -static int fusb302_send_message(int port, uint16_t header, const uint32_t *data, +static int fusb302_send_message(uint16_t header, const uint32_t *data, uint8_t *buf, int buf_pos) { int rv; int reg; @@ -315,17 +315,17 @@ static int fusb302_send_message(int port, uint16_t header, const uint32_t *data, /* burst write for speed! */ - rv = tcpc_xfer(port, buf, buf_pos, 0, 0, I2C_XFER_SINGLE); + rv = tcpc_xfer(buf, buf_pos, 0, 0, I2C_XFER_SINGLE); return rv; } -static int fusb302_tcpm_select_rp_value(int port, int rp) { +static int fusb302_tcpm_select_rp_value(int rp) { int reg; int rv; uint8_t vnc, rd; - rv = tcpc_read(port, TCPC_REG_CONTROL0, ®); + rv = tcpc_read( TCPC_REG_CONTROL0, ®); if (rv) return rv; @@ -348,35 +348,35 @@ static int fusb302_tcpm_select_rp_value(int port, int rp) { vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_VNC_MV); rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_RD_THRESH_MV); } - state[port].mdac_vnc = vnc; - state[port].mdac_rd = rd; - rv = tcpc_write(port, TCPC_REG_CONTROL0, reg); + state.mdac_vnc = vnc; + state.mdac_rd = rd; + rv = tcpc_write( TCPC_REG_CONTROL0, reg); return rv; } -static int fusb302_tcpm_init(int port) { +static int fusb302_tcpm_init() { int reg; /* set default */ - state[port].cc_polarity = -1; + state.cc_polarity = -1; /* set the voltage threshold for no connect detection (vOpen) */ - state[port].mdac_vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_VNC_MV); + state.mdac_vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_VNC_MV); /* set the voltage threshold for Rd vs Ra detection */ - state[port].mdac_rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_RD_THRESH_MV); + state.mdac_rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_RD_THRESH_MV); /* all other variables assumed to default to 0 */ /* Restore default settings */ - tcpc_write(port, TCPC_REG_RESET, TCPC_REG_RESET_SW_RESET); + tcpc_write( TCPC_REG_RESET, TCPC_REG_RESET_SW_RESET); /* Turn on retries and set number of retries */ - tcpc_read(port, TCPC_REG_CONTROL3, ®); + tcpc_read( TCPC_REG_CONTROL3, ®); reg |= TCPC_REG_CONTROL3_AUTO_RETRY; reg |= (PD_RETRY_COUNT & 0x3) << TCPC_REG_CONTROL3_N_RETRIES_POS; - tcpc_write(port, TCPC_REG_CONTROL3, reg); + tcpc_write( TCPC_REG_CONTROL3, reg); /* Create interrupt masks */ reg = 0xFF; @@ -388,7 +388,7 @@ static int fusb302_tcpm_init(int port) { reg &= ~TCPC_REG_MASK_ALERT; /* packet received with correct CRC */ reg &= ~TCPC_REG_MASK_CRC_CHK; - tcpc_write(port, TCPC_REG_MASK, reg); + tcpc_write( TCPC_REG_MASK, reg); reg = 0xFF; /* when all pd message retries fail... */ @@ -399,46 +399,46 @@ static int fusb302_tcpm_init(int port) { reg &= ~TCPC_REG_MASKA_TX_SUCCESS; /* when fusb302 receives a hard reset */ reg &= ~TCPC_REG_MASKA_HARDRESET; - tcpc_write(port, TCPC_REG_MASKA, reg); + tcpc_write( TCPC_REG_MASKA, reg); reg = 0xFF; /* when fusb302 sends GoodCRC to ack a pd message */ reg &= ~TCPC_REG_MASKB_GCRCSENT; - tcpc_write(port, TCPC_REG_MASKB, reg); + tcpc_write( TCPC_REG_MASKB, reg); /* Interrupt Enable */ - tcpc_read(port, TCPC_REG_CONTROL0, ®); + tcpc_read( TCPC_REG_CONTROL0, ®); reg &= ~TCPC_REG_CONTROL0_INT_MASK; - tcpc_write(port, TCPC_REG_CONTROL0, reg); + tcpc_write( TCPC_REG_CONTROL0, reg); /* Set VCONN switch defaults */ - tcpm_set_polarity(port, 0); - tcpm_set_vconn(port, 0); + tcpm_set_polarity(0); + tcpm_set_vconn(0); /* Turn on the power! */ /* TODO: Reduce power consumption */ - tcpc_write(port, TCPC_REG_POWER, TCPC_REG_POWER_PWR_ALL); + tcpc_write( TCPC_REG_POWER, TCPC_REG_POWER_PWR_ALL); return 0; } -static int fusb302_tcpm_release(int port) { +static int fusb302_tcpm_release() { return EC_ERROR_UNIMPLEMENTED; } -static int fusb302_tcpm_get_cc(int port, int *cc1, int *cc2) { - if (state[port].pulling_up) { +static int fusb302_tcpm_get_cc(int *cc1, int *cc2) { + if (state.pulling_up) { /* Source mode? */ - detect_cc_pin_source_manual(port, cc1, cc2); + detect_cc_pin_source_manual(cc1, cc2); } else { /* Sink mode? */ - detect_cc_pin_sink(port, cc1, cc2); + detect_cc_pin_sink(cc1, cc2); } return 0; } -static int fusb302_tcpm_set_cc(int port, int pull) { +static int fusb302_tcpm_set_cc(int pull) { int reg; /* NOTE: FUSB302 toggles a single pull-up between CC1 and CC2 */ @@ -446,7 +446,7 @@ static int fusb302_tcpm_set_cc(int port, int pull) { switch (pull) { case TYPEC_CC_RP: /* enable the pull-up we know to be necessary */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); + tcpc_read( TCPC_REG_SWITCHES0, ®); reg &= ~(TCPC_REG_SWITCHES0_CC2_PU_EN | TCPC_REG_SWITCHES0_CC1_PU_EN | @@ -458,49 +458,49 @@ static int fusb302_tcpm_set_cc(int port, int pull) { reg |= TCPC_REG_SWITCHES0_CC1_PU_EN | TCPC_REG_SWITCHES0_CC2_PU_EN; - if (state[port].vconn_enabled) - reg |= state[port].cc_polarity ? + if (state.vconn_enabled) + reg |= state.cc_polarity ? TCPC_REG_SWITCHES0_VCONN_CC1 : - TCPC_REG_SWITCHES0_VCONN_CC2; + TCPC_REG_SWITCHES0_VCONN_CC2; - tcpc_write(port, TCPC_REG_SWITCHES0, reg); + tcpc_write( TCPC_REG_SWITCHES0, reg); - state[port].pulling_up = 1; + state.pulling_up = 1; break; case TYPEC_CC_RD: /* Enable UFP Mode */ /* turn off toggle */ - tcpc_read(port, TCPC_REG_CONTROL2, ®); + tcpc_read( TCPC_REG_CONTROL2, ®); reg &= ~TCPC_REG_CONTROL2_TOGGLE; - tcpc_write(port, TCPC_REG_CONTROL2, reg); + tcpc_write( TCPC_REG_CONTROL2, reg); /* enable pull-downs, disable pullups */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); + tcpc_read( TCPC_REG_SWITCHES0, ®); reg &= ~(TCPC_REG_SWITCHES0_CC2_PU_EN); reg &= ~(TCPC_REG_SWITCHES0_CC1_PU_EN); reg |= (TCPC_REG_SWITCHES0_CC1_PD_EN); reg |= (TCPC_REG_SWITCHES0_CC2_PD_EN); - tcpc_write(port, TCPC_REG_SWITCHES0, reg); + tcpc_write( TCPC_REG_SWITCHES0, reg); - state[port].pulling_up = 0; + state.pulling_up = 0; break; case TYPEC_CC_OPEN: /* Disable toggling */ - tcpc_read(port, TCPC_REG_CONTROL2, ®); + tcpc_read( TCPC_REG_CONTROL2, ®); reg &= ~TCPC_REG_CONTROL2_TOGGLE; - tcpc_write(port, TCPC_REG_CONTROL2, reg); + tcpc_write( TCPC_REG_CONTROL2, reg); /* Ensure manual switches are opened */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); + tcpc_read( TCPC_REG_SWITCHES0, ®); reg &= ~TCPC_REG_SWITCHES0_CC1_PU_EN; reg &= ~TCPC_REG_SWITCHES0_CC2_PU_EN; reg &= ~TCPC_REG_SWITCHES0_CC1_PD_EN; reg &= ~TCPC_REG_SWITCHES0_CC2_PD_EN; - tcpc_write(port, TCPC_REG_SWITCHES0, reg); + tcpc_write( TCPC_REG_SWITCHES0, reg); - state[port].pulling_up = 0; + state.pulling_up = 0; break; default: /* Unsupported... */ @@ -510,17 +510,17 @@ static int fusb302_tcpm_set_cc(int port, int pull) { return 0; } -static int fusb302_tcpm_set_polarity(int port, int polarity) { +static int fusb302_tcpm_set_polarity(int polarity) { /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */ int reg; - tcpc_read(port, TCPC_REG_SWITCHES0, ®); + tcpc_read( TCPC_REG_SWITCHES0, ®); /* clear VCONN switch bits */ reg &= ~TCPC_REG_SWITCHES0_VCONN_CC1; reg &= ~TCPC_REG_SWITCHES0_VCONN_CC2; - if (state[port].vconn_enabled) { + if (state.vconn_enabled) { /* set VCONN switch to be non-CC line */ if (polarity) reg |= TCPC_REG_SWITCHES0_VCONN_CC1; @@ -538,9 +538,9 @@ static int fusb302_tcpm_set_polarity(int port, int polarity) { else reg |= TCPC_REG_SWITCHES0_MEAS_CC1; - tcpc_write(port, TCPC_REG_SWITCHES0, reg); + tcpc_write( TCPC_REG_SWITCHES0, reg); - tcpc_read(port, TCPC_REG_SWITCHES1, ®); + tcpc_read( TCPC_REG_SWITCHES1, ®); /* clear tx_cc bits */ reg &= ~TCPC_REG_SWITCHES1_TXCC1_EN; @@ -552,15 +552,15 @@ static int fusb302_tcpm_set_polarity(int port, int polarity) { else reg |= TCPC_REG_SWITCHES1_TXCC1_EN; - tcpc_write(port, TCPC_REG_SWITCHES1, reg); + tcpc_write( TCPC_REG_SWITCHES1, reg); /* Save the polarity for later */ - state[port].cc_polarity = polarity; + state.cc_polarity = polarity; return 0; } -static int fusb302_tcpm_set_vconn(int port, int enable) { +static int fusb302_tcpm_set_vconn(int enable) { /* * FUSB302 does not have dedicated VCONN Enable switch. * We'll get through this by disabling both of the @@ -572,31 +572,30 @@ static int fusb302_tcpm_set_vconn(int port, int enable) { int reg; /* save enable state for later use */ - state[port].vconn_enabled = enable; + state.vconn_enabled = enable; if (enable) { /* set to saved polarity */ - tcpm_set_polarity(port, state[port].cc_polarity); + tcpm_set_polarity(state.cc_polarity); } else { - tcpc_read(port, TCPC_REG_SWITCHES0, ®); + tcpc_read( TCPC_REG_SWITCHES0, ®); /* clear VCONN switch bits */ reg &= ~TCPC_REG_SWITCHES0_VCONN_CC1; reg &= ~TCPC_REG_SWITCHES0_VCONN_CC2; - tcpc_write(port, TCPC_REG_SWITCHES0, reg); + tcpc_write( TCPC_REG_SWITCHES0, reg); } return 0; } -static int fusb302_tcpm_set_msg_header(int port, int power_role, - int data_role) { +static int fusb302_tcpm_set_msg_header(int power_role, int data_role) { int reg; - tcpc_read(port, TCPC_REG_SWITCHES1, ®); + tcpc_read( TCPC_REG_SWITCHES1, ®); reg &= ~TCPC_REG_SWITCHES1_POWERROLE; reg &= ~TCPC_REG_SWITCHES1_DATAROLE; @@ -606,25 +605,25 @@ static int fusb302_tcpm_set_msg_header(int port, int power_role, if (data_role) reg |= TCPC_REG_SWITCHES1_DATAROLE; - tcpc_write(port, TCPC_REG_SWITCHES1, reg); + tcpc_write( TCPC_REG_SWITCHES1, reg); return 0; } -static int fusb302_tcpm_set_rx_enable(int port, int enable) { +static int fusb302_tcpm_set_rx_enable(int enable) { int reg; - state[port].rx_enable = enable; + state.rx_enable = enable; /* Get current switch state */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); + tcpc_read( TCPC_REG_SWITCHES0, ®); /* Clear CC1/CC2 measure bits */ reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1; reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; if (enable) { - switch (state[port].cc_polarity) { + switch (state.cc_polarity) { /* if CC polarity hasnt been determined, can't enable */ case -1: return EC_ERROR_UNKNOWN; @@ -638,39 +637,39 @@ static int fusb302_tcpm_set_rx_enable(int port, int enable) { /* "shouldn't get here" */ return EC_ERROR_UNKNOWN; } - tcpc_write(port, TCPC_REG_SWITCHES0, reg); + tcpc_write( TCPC_REG_SWITCHES0, reg); /* Disable BC_LVL interrupt when enabling PD comm */ - if (!tcpc_read(port, TCPC_REG_MASK, ®)) - tcpc_write(port, TCPC_REG_MASK, reg | TCPC_REG_MASK_BC_LVL); + if (!tcpc_read( TCPC_REG_MASK, ®)) + tcpc_write( TCPC_REG_MASK, reg | TCPC_REG_MASK_BC_LVL); /* flush rx fifo in case messages have been coming our way */ - fusb302_flush_rx_fifo(port); + fusb302_flush_rx_fifo(); } else { - tcpc_write(port, TCPC_REG_SWITCHES0, reg); + tcpc_write( TCPC_REG_SWITCHES0, reg); /* Enable BC_LVL interrupt when disabling PD comm */ - if (!tcpc_read(port, TCPC_REG_MASK, ®)) - tcpc_write(port, TCPC_REG_MASK, reg & ~TCPC_REG_MASK_BC_LVL); + if (!tcpc_read( TCPC_REG_MASK, ®)) + tcpc_write( TCPC_REG_MASK, reg & ~TCPC_REG_MASK_BC_LVL); } - fusb302_auto_goodcrc_enable(port, enable); + fusb302_auto_goodcrc_enable(enable); return 0; } /* Return true if our Rx FIFO is empty */ -static int fusb302_rx_fifo_is_empty(int port) { +static int fusb302_rx_fifo_is_empty() { int reg, ret; - ret = (!tcpc_read(port, TCPC_REG_STATUS1, ®)) + ret = (!tcpc_read( TCPC_REG_STATUS1, ®)) && (reg & TCPC_REG_STATUS1_RX_EMPTY); return ret; } -static int fusb302_tcpm_get_message(int port, uint32_t *payload, int *head) { +static int fusb302_tcpm_get_message(uint32_t *payload, int *head) { /* * This is the buffer that will get the burst-read data * from the fusb302. @@ -683,7 +682,7 @@ static int fusb302_tcpm_get_message(int port, uint32_t *payload, int *head) { int rv, len; /* If our FIFO is empty then we have no packet */ - if (fusb302_rx_fifo_is_empty(port)) + if (fusb302_rx_fifo_is_empty()) return EC_ERROR_UNKNOWN; /* Read until we have a non-GoodCRC packet or an empty FIFO */ @@ -694,7 +693,7 @@ static int fusb302_tcpm_get_message(int port, uint32_t *payload, int *head) { * PART 1 OF BURST READ: Write in register address. * Issue a START, no STOP. */ - rv = tcpc_xfer(port, buf, 1, 0, 0, I2C_XFER_START); + rv = tcpc_xfer(buf, 1, 0, 0, I2C_XFER_START); /* * PART 2 OF BURST READ: Read up to the header. @@ -703,7 +702,7 @@ static int fusb302_tcpm_get_message(int port, uint32_t *payload, int *head) { * and determine how many more bytes we need to read. * TODO: Check token to ensure valid packet. */ - rv |= tcpc_xfer(port, 0, 0, buf, 3, I2C_XFER_START); + rv |= tcpc_xfer(0, 0, buf, 3, I2C_XFER_START); /* Grab the header */ *head = (buf[1] & 0xFF); @@ -717,9 +716,9 @@ static int fusb302_tcpm_get_message(int port, uint32_t *payload, int *head) { * No START, but do issue a STOP at the end. * add 4 to len to read CRC out */ - rv |= tcpc_xfer(port, 0, 0, buf, len + 4, I2C_XFER_STOP); + rv |= tcpc_xfer(0, 0, buf, len + 4, I2C_XFER_STOP); - } while (!rv && PACKET_IS_GOOD_CRC(*head) && !fusb302_rx_fifo_is_empty(port)); + } while (!rv && PACKET_IS_GOOD_CRC(*head) && !fusb302_rx_fifo_is_empty()); if (!rv) { /* Discard GoodCRC packets */ @@ -738,8 +737,8 @@ static int fusb302_tcpm_get_message(int port, uint32_t *payload, int *head) { return rv; } -static int fusb302_tcpm_transmit(int port, enum tcpm_transmit_type type, - uint16_t header, const uint32_t *data) { +static int fusb302_tcpm_transmit(enum tcpm_transmit_type type, uint16_t header, + const uint32_t *data) { /* * this is the buffer that will be burst-written into the fusb302 * maximum size necessary = @@ -760,7 +759,7 @@ static int fusb302_tcpm_transmit(int port, enum tcpm_transmit_type type, int reg; /* Flush the TXFIFO */ - fusb302_flush_tx_fifo(port); + fusb302_flush_tx_fifo (); switch (type) { case TCPC_TX_SOP: @@ -774,37 +773,37 @@ static int fusb302_tcpm_transmit(int port, enum tcpm_transmit_type type, buf[buf_pos++] = fusb302_TKN_SYNC1; buf[buf_pos++] = fusb302_TKN_SYNC2; - fusb302_send_message(port, header, data, buf, buf_pos); - // wait for the GoodCRC to come back before we let the rest - // of the code do stuff like change polarity and miss it + fusb302_send_message(header, data, buf, buf_pos); +// wait for the GoodCRC to come back before we let the rest +// of the code do stuff like change polarity and miss it // delay_us(600); osDelay(1); break; case TCPC_TX_HARD_RESET: /* Simply hit the SEND_HARD_RESET bit */ - tcpc_read(port, TCPC_REG_CONTROL3, ®); + tcpc_read( TCPC_REG_CONTROL3, ®); reg |= TCPC_REG_CONTROL3_SEND_HARDRESET; - tcpc_write(port, TCPC_REG_CONTROL3, reg); + tcpc_write( TCPC_REG_CONTROL3, reg); break; case TCPC_TX_BIST_MODE_2: /* Hit the BIST_MODE2 bit and start TX */ - tcpc_read(port, TCPC_REG_CONTROL1, ®); + tcpc_read( TCPC_REG_CONTROL1, ®); reg |= TCPC_REG_CONTROL1_BIST_MODE2; - tcpc_write(port, TCPC_REG_CONTROL1, reg); + tcpc_write( TCPC_REG_CONTROL1, reg); - tcpc_read(port, TCPC_REG_CONTROL0, ®); + tcpc_read( TCPC_REG_CONTROL0, ®); reg |= TCPC_REG_CONTROL0_TX_START; - tcpc_write(port, TCPC_REG_CONTROL0, reg); + tcpc_write( TCPC_REG_CONTROL0, reg); - //task_wait_event(PD_T_BIST_TRANSMIT); +//task_wait_event(PD_T_BIST_TRANSMIT); /* Clear BIST mode bit, TX_START is self-clearing */ - tcpc_read(port, TCPC_REG_CONTROL1, ®); + tcpc_read( TCPC_REG_CONTROL1, ®); reg &= ~TCPC_REG_CONTROL1_BIST_MODE2; - tcpc_write(port, TCPC_REG_CONTROL1, reg); + tcpc_write( TCPC_REG_CONTROL1, reg); break; default: @@ -815,20 +814,19 @@ static int fusb302_tcpm_transmit(int port, enum tcpm_transmit_type type, } #ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC -static int fusb302_tcpm_get_vbus_level(int port) +static int fusb302_tcpm_get_vbus_level() { int reg; /* Read status register */ - tcpc_read(port, TCPC_REG_STATUS0, ®); - + tcpc_read( TCPC_REG_STATUS0, ®); return (reg & TCPC_REG_STATUS0_VBUSOK) ? 1 : 0; } #endif -void fusb302_tcpc_alert(int port) { +void fusb302_tcpc_alert() { /* interrupt has been received */ int interrupt; int interrupta; @@ -836,85 +834,85 @@ void fusb302_tcpc_alert(int port) { /* reading interrupt registers clears them */ - tcpc_read(port, TCPC_REG_INTERRUPT, &interrupt); - tcpc_read(port, TCPC_REG_INTERRUPTA, &interrupta); - tcpc_read(port, TCPC_REG_INTERRUPTB, &interruptb); + tcpc_read( TCPC_REG_INTERRUPT, &interrupt); + tcpc_read( TCPC_REG_INTERRUPTA, &interrupta); + tcpc_read( TCPC_REG_INTERRUPTB, &interruptb); /* * Ignore BC_LVL changes when transmitting / receiving PD, * since CC level will constantly change. */ - if (state[port].rx_enable) + if (state.rx_enable) interrupt &= ~TCPC_REG_INTERRUPT_BC_LVL; if (interrupt & TCPC_REG_INTERRUPT_BC_LVL) { /* CC Status change */ - //task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0); +//task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0); } if (interrupt & TCPC_REG_INTERRUPT_COLLISION) { /* packet sending collided */ - pd_transmit_complete(port, TCPC_TX_COMPLETE_FAILED); + pd_transmit_complete(TCPC_TX_COMPLETE_FAILED); } /* GoodCRC was received, our FIFO is now non-empty */ if (interrupta & TCPC_REG_INTERRUPTA_TX_SUCCESS) { - //task_set_event(PD_PORT_TO_TASK_ID(port), - // PD_EVENT_RX, 0); +//task_set_event(PD_PORT_TO_TASK_ID(port), +// PD_EVENT_RX, 0); - pd_transmit_complete(port, TCPC_TX_COMPLETE_SUCCESS); + pd_transmit_complete(TCPC_TX_COMPLETE_SUCCESS); } if (interrupta & TCPC_REG_INTERRUPTA_RETRYFAIL) { /* all retries have failed to get a GoodCRC */ - pd_transmit_complete(port, TCPC_TX_COMPLETE_FAILED); + pd_transmit_complete(TCPC_TX_COMPLETE_FAILED); } if (interrupta & TCPC_REG_INTERRUPTA_HARDSENT) { /* hard reset has been sent */ /* bring FUSB302 out of reset */ - fusb302_pd_reset(port); + fusb302_pd_reset(); - pd_transmit_complete(port, TCPC_TX_COMPLETE_SUCCESS); + pd_transmit_complete(TCPC_TX_COMPLETE_SUCCESS); } if (interrupta & TCPC_REG_INTERRUPTA_HARDRESET) { /* hard reset has been received */ /* bring FUSB302 out of reset */ - fusb302_pd_reset(port); + fusb302_pd_reset(); - pd_execute_hard_reset(port); + pd_execute_hard_reset (); - //task_wake(PD_PORT_TO_TASK_ID(port)); +//task_wake(PD_PORT_TO_TASK_ID(port)); } if (interruptb & TCPC_REG_INTERRUPTB_GCRCSENT) { /* Packet received and GoodCRC sent */ /* (this interrupt fires after the GoodCRC finishes) */ - if (state[port].rx_enable) { + if (state.rx_enable) { //task_set_event(PD_PORT_TO_TASK_ID(port), // PD_EVENT_RX, 0); } else { /* flush rx fifo if rx isn't enabled */ - fusb302_flush_rx_fifo(port); + fusb302_flush_rx_fifo(); } } } /* For BIST receiving */ -void tcpm_set_bist_test_data(int port) { +void tcpm_set_bist_test_data() { int reg; /* Read control3 register */ - tcpc_read(port, TCPC_REG_CONTROL3, ®); + tcpc_read( TCPC_REG_CONTROL3, ®); /* Set the BIST_TMODE bit (Clears on Hard Reset) */ reg |= TCPC_REG_CONTROL3_BIST_TMODE; /* Write the updated value */ - tcpc_write(port, TCPC_REG_CONTROL3, reg); + tcpc_write( TCPC_REG_CONTROL3, reg); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h index cd520d3e..e863e5ff 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h +++ b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h @@ -192,17 +192,17 @@ enum pd_rx_errors { /* function table for entered mode */ struct amode_fx { - int (*status)(int port, uint32_t *payload); - int (*config)(int port, uint32_t *payload); + int (*status)( uint32_t *payload); + int (*config)( uint32_t *payload); }; /* function table for alternate mode capable responders */ struct svdm_response { - int (*identity)(int port, uint32_t *payload); - int (*svids)(int port, uint32_t *payload); - int (*modes)(int port, uint32_t *payload); - int (*enter_mode)(int port, uint32_t *payload); - int (*exit_mode)(int port, uint32_t *payload); + int (*identity)( uint32_t *payload); + int (*svids)( uint32_t *payload); + int (*modes)( uint32_t *payload); + int (*enter_mode)( uint32_t *payload); + int (*exit_mode)( uint32_t *payload); struct amode_fx *amode; }; @@ -214,12 +214,12 @@ struct svdm_svid_data { struct svdm_amode_fx { uint16_t svid; - int (*enter)(int port, uint32_t mode_caps); - int (*status)(int port, uint32_t *payload); - int (*config)(int port, uint32_t *payload); - void (*post_config)(int port); - int (*attention)(int port, uint32_t *payload); - void (*exit)(int port); + int (*enter)( uint32_t mode_caps); + int (*status)( uint32_t *payload); + int (*config)( uint32_t *payload); + void (*post_config)(); + int (*attention)( uint32_t *payload); + void (*exit)(); }; /* defined in /usb_pd_policy.c */ @@ -251,8 +251,6 @@ enum hpd_event { /* supported alternate modes */ enum pd_alternate_modes { - PD_AMODE_GOOGLE, - PD_AMODE_DISPLAYPORT, /* not a real mode */ PD_AMODE_COUNT, }; @@ -787,7 +785,7 @@ void pd_set_dual_role(enum pd_dual_role_states state); * * @param port Port number from which to get role */ -int pd_get_role(int port); +int pd_get_role(); #endif @@ -973,7 +971,7 @@ enum pd_request_type { * @param port USB-C port number * @return 0 for PD_REV1.0, 1 for PD_REV2.0, 2 for PD_REV3.0 */ -int pd_get_rev(int port); +int pd_get_rev(); /** * Get current PD VDO Version @@ -981,7 +979,7 @@ int pd_get_rev(int port); * @param port USB-C port number * @return 0 for PD_REV1.0, 1 for PD_REV2.0 */ -int pd_get_vdo_ver(int port); +int pd_get_vdo_ver(); #else #define pd_get_rev(n) PD_REV20 #define pd_get_vdo_ver(n) VDM_VER10 @@ -996,7 +994,7 @@ int pd_get_vdo_ver(int port); * @param req_type request type * @return <0 if invalid, else EC_SUCCESS */ -int pd_build_request(int port, uint32_t *rdo, uint32_t *ma, uint32_t *mv, +int pd_build_request( uint32_t *rdo, uint32_t *ma, uint32_t *mv, enum pd_request_type req_type); /** @@ -1014,7 +1012,7 @@ int pd_is_max_request_allowed(void); * @param cnt the number of Power Data Objects. * @param src_caps Power Data Objects representing the source capabilities. */ -void pd_process_source_cap_callback(int port, int cnt, uint32_t *src_caps); +void pd_process_source_cap_callback( int cnt, uint32_t *src_caps); /** * Process source capabilities packet @@ -1023,7 +1021,7 @@ void pd_process_source_cap_callback(int port, int cnt, uint32_t *src_caps); * @param cnt the number of Power Data Objects. * @param src_caps Power Data Objects representing the source capabilities. */ -void pd_process_source_cap(int port, int cnt, uint32_t *src_caps); +void pd_process_source_cap( int cnt, uint32_t *src_caps); /** * Find PDO index that offers the most amount of power and stays within @@ -1034,7 +1032,7 @@ void pd_process_source_cap(int port, int cnt, uint32_t *src_caps); * @param pdo raw pdo corresponding to index, or index 0 on error (output) * @return index of PDO within source cap packet */ -int pd_find_pdo_index(int port, int max_mv, uint32_t *pdo); +int pd_find_pdo_index( int max_mv, uint32_t *pdo); /** * Extract power information out of a Power Data Object (PDO) @@ -1052,7 +1050,7 @@ void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *mv); * @param ma reduce current to minimum value. * @param mv reduce voltage to minimum value. */ -void pd_snk_give_back(int port, uint32_t * const ma, uint32_t * const mv); +void pd_snk_give_back( uint32_t * const ma, uint32_t * const mv); /** * Put a cap on the max voltage requested as a sink. @@ -1104,7 +1102,7 @@ void pd_transition_voltage(int idx); * * @param port USB-C port number */ -void pd_power_supply_reset(int port); +void pd_power_supply_reset(); /** * Enable or disable VBUS discharge for a given port. @@ -1112,7 +1110,7 @@ void pd_power_supply_reset(int port); * @param port USB-C port number * @enable 1 if enabling discharge, 0 if disabling */ -void pd_set_vbus_discharge(int port, int enable); +void pd_set_vbus_discharge( int enable); /** * Enable the power supply output after the ready delay. @@ -1120,7 +1118,7 @@ void pd_set_vbus_discharge(int port, int enable); * @param port USB-C port number * @return EC_SUCCESS if the power supply is ready, <0 else. */ -int pd_set_power_supply_ready(int port); +int pd_set_power_supply_ready(); /** * Ask the specified voltage from the PD source. @@ -1129,7 +1127,7 @@ int pd_set_power_supply_ready(int port); * @param port USB-C port number * @param mv request voltage in millivolts. */ -void pd_request_source_voltage(int port, int mv); +void pd_request_source_voltage( int mv); /** * Set a voltage limit from the PD source. @@ -1138,7 +1136,7 @@ void pd_request_source_voltage(int port, int mv); * @param port USB-C port number * @param mv limit voltage in millivolts. */ -void pd_set_external_voltage_limit(int port, int mv); +void pd_set_external_voltage_limit( int mv); /** * Set the PD input current limit. @@ -1147,7 +1145,7 @@ void pd_set_external_voltage_limit(int port, int mv); * @param max_ma Maximum current limit * @param supply_voltage Voltage at which current limit is applied */ -void pd_set_input_current_limit(int port, uint32_t max_ma, +void pd_set_input_current_limit( uint32_t max_ma, uint32_t supply_voltage); @@ -1156,7 +1154,7 @@ void pd_set_input_current_limit(int port, uint32_t max_ma, * * @param port USB-C port number. */ -void pd_update_contract(int port); +void pd_update_contract(); /* Encode DTS status of port partner in current limit parameter */ typedef uint32_t typec_current_t; @@ -1170,7 +1168,7 @@ typedef uint32_t typec_current_t; * @param max_ma Maximum current limit * @param supply_voltage Voltage at which current limit is applied */ -void typec_set_input_current_limit(int port, typec_current_t max_ma, +void typec_set_input_current_limit( typec_current_t max_ma, uint32_t supply_voltage); /** @@ -1179,7 +1177,7 @@ void typec_set_input_current_limit(int port, typec_current_t max_ma, * @param port USB-C port number * @param rp One of enum tcpc_rp_value (eg TYPEC_RP_3A0) defining the limit. */ -void typec_set_source_current_limit(int port, int rp); +void typec_set_source_current_limit( int rp); /** * Verify board specific health status : current, voltages... @@ -1194,14 +1192,14 @@ int pd_board_checks(void); * @param port USB-C port number * @return VBUS is detected */ -int pd_snk_is_vbus_provided(int port); +int pd_snk_is_vbus_provided(); /** * Notify PD protocol that VBUS has gone low * * @param port USB-C port number */ -void pd_vbus_low(int port); +void pd_vbus_low(); /** * Check if power swap is allowed. @@ -1209,7 +1207,7 @@ void pd_vbus_low(int port); * @param port USB-C port number * @return True if power swap is allowed, False otherwise */ -int pd_check_power_swap(int port); +int pd_check_power_swap(); /** * Check if data swap is allowed. @@ -1218,7 +1216,7 @@ int pd_check_power_swap(int port); * @param data_role current data role * @return True if data swap is allowed, False otherwise */ -int pd_check_data_swap(int port, int data_role); +int pd_check_data_swap( int data_role); /** * Check if vconn swap is allowed. @@ -1227,7 +1225,7 @@ int pd_check_data_swap(int port, int data_role); * @return True if vconn swap is allowed, False otherwise */ -int pd_check_vconn_swap(int port); +int pd_check_vconn_swap(); /** * Check current power role for potential power swap @@ -1236,7 +1234,7 @@ int pd_check_vconn_swap(int port); * @param pr_role Our power role * @param flags PD flags */ -void pd_check_pr_role(int port, int pr_role, int flags); +void pd_check_pr_role( int pr_role, int flags); /** * Check current data role for potential data swap @@ -1245,7 +1243,7 @@ void pd_check_pr_role(int port, int pr_role, int flags); * @param dr_role Our data role * @param flags PD flags */ -void pd_check_dr_role(int port, int dr_role, int flags); +void pd_check_dr_role( int dr_role, int flags); /** * Check if we should charge from this device. This is @@ -1264,7 +1262,7 @@ int pd_charge_from_device(uint16_t vid, uint16_t pid); * @param port USB-C port number * @param data_role new data role */ -void pd_execute_data_swap(int port, int data_role); +void pd_execute_data_swap( int data_role); /** * Get PD device info used for VDO_CMD_SEND_INFO / VDO_CMD_READ_INFO @@ -1282,7 +1280,7 @@ void pd_get_info(uint32_t *info_data); * @param rpayload pointer to the data to send back. * @return if >0, number of VDOs to send back. */ -int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload); +int pd_custom_vdm( int cnt, uint32_t *payload, uint32_t **rpayload); /** * Handle Structured Vendor Defined Messages @@ -1293,7 +1291,7 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload); * @param rpayload pointer to the data to send back. * @return if >0, number of VDOs to send back. */ -int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload); +int pd_svdm( int cnt, uint32_t *payload, uint32_t **rpayload); /** * Handle Custom VDMs for flashing. @@ -1303,7 +1301,7 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload); * @param payload payload data. * @return if >0, number of VDOs to send back. */ -int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload); +int pd_custom_flash_vdm( int cnt, uint32_t *payload); /** * Enter alternate mode on DFP @@ -1313,7 +1311,7 @@ int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload); * @param opos object position of mode to exit. * @return vdm for UFP to be sent to enter mode or zero if not. */ -uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos); +uint32_t pd_dfp_enter_mode( uint16_t svid, int opos); /** * Get DisplayPort pin mode for DFP to request from UFP's capabilities. @@ -1322,7 +1320,7 @@ uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos); * @param status DisplayPort Status VDO. * @return one-hot PIN config to request. */ -int pd_dfp_dp_get_pin_mode(int port, uint32_t status); +int pd_dfp_dp_get_pin_mode( uint32_t status); /** * Exit alternate mode on DFP @@ -1332,14 +1330,14 @@ int pd_dfp_dp_get_pin_mode(int port, uint32_t status); * @param opos object position of mode to exit. * @return 1 if UFP should be sent exit mode VDM. */ -int pd_dfp_exit_mode(int port, uint16_t svid, int opos); +int pd_dfp_exit_mode( uint16_t svid, int opos); /** * Initialize policy engine for DFP * * @param port USB-C port number */ -void pd_dfp_pe_init(int port); +void pd_dfp_pe_init(); /** * Return the VID of the USB PD accessory connected to a specified port @@ -1347,7 +1345,7 @@ void pd_dfp_pe_init(int port); * @param port USB-C port number * @return the USB Vendor Identifier or 0 if it doesn't exist */ -uint16_t pd_get_identity_vid(int port); +uint16_t pd_get_identity_vid(); /** * Return the PID of the USB PD accessory connected to a specified port @@ -1355,7 +1353,7 @@ uint16_t pd_get_identity_vid(int port); * @param port USB-C port number * @return the USB Product Identifier or 0 if it doesn't exist */ -uint16_t pd_get_identity_pid(int port); +uint16_t pd_get_identity_pid(); /** * Store Device ID & RW hash of device @@ -1367,7 +1365,7 @@ uint16_t pd_get_identity_pid(int port); * @return true if the dev / hash match an existing hash * in our table, false otherwise */ -int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash, +int pd_dev_store_rw_hash( uint16_t dev_id, uint32_t *rw_hash, uint32_t ec_current_image); /** @@ -1376,7 +1374,7 @@ int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash, * @param port USB-C accessory port number * @return EC_RES_SUCCESS if the VDM was sent properly else error code */ -int pd_fetch_acc_log_entry(int port); +int pd_fetch_acc_log_entry(); /** * Analyze the log entry received as the VDO_CMD_GET_LOG payload. @@ -1385,7 +1383,7 @@ int pd_fetch_acc_log_entry(int port); * @param cnt number of data objects in payload * @param payload payload data */ -void pd_log_recv_vdm(int port, int cnt, uint32_t *payload); +void pd_log_recv_vdm( int cnt, uint32_t *payload); /** * Send Vendor Defined Message @@ -1396,7 +1394,7 @@ void pd_log_recv_vdm(int port, int cnt, uint32_t *payload); * @param data Pointer to payload to send * @param count number of data objects in payload */ -void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data, +void pd_send_vdm( uint32_t vid, int cmd, const uint32_t *data, int count); /* Power Data Objects for the source and the sink */ @@ -1425,7 +1423,7 @@ static inline void pd_send_host_event(int mask) { } * @param svid USB standard or vendor id * @return object position of mode chosen in alternate mode otherwise zero. */ -int pd_alt_mode(int port, uint16_t svid); +int pd_alt_mode( uint16_t svid); /** * Send hpd over USB PD. @@ -1433,7 +1431,7 @@ int pd_alt_mode(int port, uint16_t svid); * @param port port number. * @param hpd hotplug detect type. */ -void pd_send_hpd(int port, enum hpd_event hpd); +void pd_send_hpd( enum hpd_event hpd); /** * Enable USB Billboard Device. @@ -1448,7 +1446,7 @@ extern const struct deferred_data pd_usb_billboard_deferred_data; * * @param port USB-C port number */ -void pd_init_dequeue(int port); +void pd_init_dequeue(); /** * Prepare packet reading state machine. @@ -1459,7 +1457,7 @@ void pd_init_dequeue(int port); * @param val the read bits. * @return new position in the packet buffer. */ -int pd_dequeue_bits(int port, int off, int len, uint32_t *val); +int pd_dequeue_bits( int off, int len, uint32_t *val); /** * Advance until the end of the preamble. @@ -1467,7 +1465,7 @@ int pd_dequeue_bits(int port, int off, int len, uint32_t *val); * @param port USB-C port number * @return new position in the packet buffer. */ -int pd_find_preamble(int port); +int pd_find_preamble(); /** * Write the preamble in the TX buffer. @@ -1475,7 +1473,7 @@ int pd_find_preamble(int port); * @param port USB-C port number * @return new position in the packet buffer. */ -int pd_write_preamble(int port); +int pd_write_preamble(); /** * Write one 10-period symbol in the TX packet. @@ -1487,7 +1485,7 @@ int pd_write_preamble(int port); * @param val10 the 10-bit integer. * @return new position in the packet buffer. */ -int pd_write_sym(int port, int bit_off, uint32_t val10); +int pd_write_sym( int bit_off, uint32_t val10); /** @@ -1498,7 +1496,7 @@ int pd_write_sym(int port, int bit_off, uint32_t val10); * @param bit_off current position in the packet buffer. * @return new position in the packet buffer. */ -int pd_write_last_edge(int port, int bit_off); +int pd_write_last_edge( int bit_off); /** * Do 4B5B encoding on a 32-bit word. @@ -1508,7 +1506,7 @@ int pd_write_last_edge(int port, int bit_off); * @param val32 32-bit word value to encode * @return new offset in the message in bits. */ -int encode_word(int port, int off, uint32_t val32); +int encode_word( int off, uint32_t val32); /** * Ensure that we have an edge after EOP and we end up at level 0, @@ -1520,7 +1518,7 @@ int encode_word(int port, int off, uint32_t val32); * @param data payload content * @return length of the message in bits. */ -int prepare_message(int port, uint16_t header, uint8_t cnt, +int prepare_message( uint16_t header, uint8_t cnt, const uint32_t *data); /** @@ -1529,7 +1527,7 @@ int prepare_message(int port, uint16_t header, uint8_t cnt, * @param port USB-C port number * @param msg context string. */ -void pd_dump_packet(int port, const char *msg); +void pd_dump_packet( const char *msg); /** * Change the TX data clock frequency. @@ -1537,7 +1535,7 @@ void pd_dump_packet(int port, const char *msg); * @param port USB-C port number * @param freq frequency in hertz. */ -void pd_set_clock(int port, int freq); +void pd_set_clock( int freq); /* TX/RX callbacks */ @@ -1549,7 +1547,7 @@ void pd_set_clock(int port, int freq); * @param bit_len size of the packet in bits. * @return length transmitted or negative if error */ -int pd_start_tx(int port, int polarity, int bit_len); +int pd_start_tx( int polarity, int bit_len); /** * Set PD TX DMA to use circular mode. Call this before pd_start_tx() to @@ -1557,14 +1555,14 @@ int pd_start_tx(int port, int polarity, int bit_len); * * @param port USB-C port number */ -void pd_tx_set_circular_mode(int port); +void pd_tx_set_circular_mode(); /** * Stop PD TX DMA circular mode transaction already in progress. * * @param port USB-C port number */ -void pd_tx_clear_circular_mode(int port); +void pd_tx_clear_circular_mode(); /** * Call when we are done sending a packet. @@ -1572,7 +1570,7 @@ void pd_tx_clear_circular_mode(int port); * @param port USB-C port number * @param polarity plug polarity (0=CC1, 1=CC2). */ -void pd_tx_done(int port, int polarity); +void pd_tx_done( int polarity); /** * Check whether the PD reception is started. @@ -1580,14 +1578,14 @@ void pd_tx_done(int port, int polarity); * @param port USB-C port number * @return true if the reception is on-going. */ -int pd_rx_started(int port); +int pd_rx_started(); /** * Suspend the PD task. * @param port USB-C port number * @param enable pass 0 to resume, anything else to suspend */ -void pd_set_suspend(int port, int enable); +void pd_set_suspend( int enable); /** * Check if the port has been initialized and PD task has not been @@ -1596,29 +1594,29 @@ void pd_set_suspend(int port, int enable); * @param port USB-C port number * @return true if the PD task is not suspended. */ -int pd_is_port_enabled(int port); +int pd_is_port_enabled(); /* Callback when the hardware has detected an incoming packet */ -void pd_rx_event(int port); +void pd_rx_event(); /* Start sampling the CC line for reception */ -void pd_rx_start(int port); +void pd_rx_start(); /* Call when we are done reading a packet */ -void pd_rx_complete(int port); +void pd_rx_complete(); /* restart listening to the CC wire */ -void pd_rx_enable_monitoring(int port); +void pd_rx_enable_monitoring(); /* stop listening to the CC wire during transmissions */ -void pd_rx_disable_monitoring(int port); +void pd_rx_disable_monitoring(); /* get time since last RX edge interrupt */ -uint64_t get_time_since_last_edge(int port); +uint64_t get_time_since_last_edge(); /** * Deinitialize the hardware used for PD. * * @param port USB-C port number */ -void pd_hw_release(int port); +void pd_hw_release(); /** * Initialize the hardware used for PD RX/TX. @@ -1626,7 +1624,7 @@ void pd_hw_release(int port); * @param port USB-C port number * @param role Role to initialize pins in */ -void pd_hw_init(int port, int role); +void pd_hw_init( int role); /** * Initialize the reception side of hardware used for PD. @@ -1636,19 +1634,19 @@ void pd_hw_init(int port, int role); * * @param port USB-C port number */ -void pd_hw_init_rx(int port); +void pd_hw_init_rx(); /** * Initialize the Power Delivery state machine */ -void pd_init(int port); +void pd_init(); /** * Run the state machine. This function must be called regularly * to iterate through the state machine. It uses get_time() to * determine what actions to take each call. */ -void pd_run_state_machine(int port); +void pd_run_state_machine(); /* --- Protocol layer functions --- */ @@ -1659,14 +1657,14 @@ void pd_run_state_machine(int port); * @param payload buffer to store the packet payload (must be 7x 32-bit) * @return the packet header or <0 in case of error */ -int pd_analyze_rx(int port, uint32_t *payload); +int pd_analyze_rx( uint32_t *payload); /** * Check if PD communication is enabled * * @return true if it's enabled or false otherwise */ -int pd_comm_is_enabled(int port); +int pd_comm_is_enabled(); /** * Get connected state @@ -1674,14 +1672,14 @@ int pd_comm_is_enabled(int port); * @param port USB-C port number * @return True if port is in connected state */ -int pd_is_connected(int port); +int pd_is_connected(); /** * Execute a hard reset * * @param port USB-C port number */ -void pd_execute_hard_reset(int port); +void pd_execute_hard_reset(); /** * Signal to protocol layer that PD transmit is complete @@ -1689,28 +1687,28 @@ void pd_execute_hard_reset(int port); * @param port USB-C port number * @param status status of the transmission */ -void pd_transmit_complete(int port, int status); +void pd_transmit_complete( int status); /** * Get port polarity. * * @param port USB-C port number */ -int pd_get_polarity(int port); +int pd_get_polarity(); /** * Get port partner data swap capable status * * @param port USB-C port number */ -int pd_get_partner_data_swap_capable(int port); +int pd_get_partner_data_swap_capable(); /** * Request power swap command to be issued * * @param port USB-C port number */ -void pd_request_power_swap(int port); +void pd_request_power_swap(); /** * Try to become the VCONN source, if we are not already the source and the @@ -1718,14 +1716,14 @@ void pd_request_power_swap(int port); * * @param port USB-C port number */ -void pd_try_vconn_src(int port); +void pd_try_vconn_src(); /** * Request data swap command to be issued * * @param port USB-C port number */ -void pd_request_data_swap(int port); +void pd_request_data_swap(); /** * Set the PD communication enabled flag. When communication is disabled, @@ -1735,7 +1733,7 @@ void pd_request_data_swap(int port); * @param port USB-C port number * @param enable Enable flag to set */ -void pd_comm_enable(int port, int enable); +void pd_comm_enable( int enable); /** * Set the PD pings enabled flag. When source has negotiated power over @@ -1745,7 +1743,7 @@ void pd_comm_enable(int port, int enable); * @param port USB-C port number * @param enable Enable flag to set */ -void pd_ping_enable(int port, int enable); +void pd_ping_enable( int enable); /* Issue PD soft reset */ void pd_soft_reset(void); @@ -1758,7 +1756,7 @@ void pd_prepare_reset(void); * * @param port USB-C port number */ -void pd_set_new_power_request(int port); +void pd_set_new_power_request(); /** * Return true if partner port is a DTS or TS capable of entering debug @@ -1766,7 +1764,7 @@ void pd_set_new_power_request(int port); * * @param port USB-C port number */ -int pd_ts_dts_plugged(int port); +int pd_ts_dts_plugged(); /* ----- Logging ----- */ #ifdef CONFIG_USB_PD_LOGGING diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.c b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.cpp similarity index 66% rename from workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.c rename to workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.cpp index 49b9cdad..d70f7c3c 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.c +++ b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.cpp @@ -17,69 +17,31 @@ static int rw_flash_changed = 1; int pd_check_requested_voltage(uint32_t rdo, const int port) { - int max_ma = rdo & 0x3FF; - int op_ma = (rdo >> 10) & 0x3FF; - int idx = RDO_POS(rdo); - uint32_t pdo; - uint32_t pdo_ma; -#if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ - defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) - const uint32_t *src_pdo; - const int pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port); -#else - const uint32_t *src_pdo = pd_src_pdo; - const int pdo_cnt = pd_src_pdo_cnt; -#endif - - /* Board specific check for this request */ - if (pd_board_check_request(rdo, pdo_cnt)) - return EC_ERROR_INVAL; - - /* check current ... */ - pdo = src_pdo[idx - 1]; - pdo_ma = (pdo & 0x3ff); - if (op_ma > pdo_ma) - return EC_ERROR_INVAL; /* too much op current */ - if (max_ma > pdo_ma && !(rdo & RDO_CAP_MISMATCH)) - return EC_ERROR_INVAL; /* too much max current */ - - CPRINTF("Requested %d V %d mA (for %d/%d mA)\n", - ((pdo >> 10) & 0x3ff) * 50, (pdo & 0x3ff) * 10, - op_ma * 10, max_ma * 10); - - /* Accept the requested voltage */ - return EC_SUCCESS; + //No source + return EC_ERROR_INVAL; } -static int stub_pd_board_check_request(uint32_t rdo, int pdo_cnt) { - int idx = RDO_POS(rdo); - - /* Check for invalid index */ - return (!idx || idx > pdo_cnt) ? EC_ERROR_INVAL : EC_SUCCESS; -} -int pd_board_check_request(uint32_t, int) __attribute__((weak, alias("stub_pd_board_check_request"))); - #ifdef CONFIG_USB_PD_DUAL_ROLE /* Last received source cap */ -static uint32_t pd_src_caps[CONFIG_USB_PD_PORT_COUNT][PDO_MAX_OBJECTS]; -static uint8_t pd_src_cap_cnt[CONFIG_USB_PD_PORT_COUNT]; +static uint32_t pd_src_caps[PDO_MAX_OBJECTS]; +static uint8_t pd_src_cap_cnt; /* Cap on the max voltage requested as a sink (in millivolts) */ static unsigned max_request_mv = PD_MAX_VOLTAGE_MV; /* no cap */ -int pd_find_pdo_index(int port, int max_mv, uint32_t *selected_pdo) { +int pd_find_pdo_index(int max_mv, uint32_t *selected_pdo) { int i, uw, mv, ma; int ret = 0; int __attribute__((unused)) cur_mv = 0; int cur_uw = 0; int prefer_cur; - const uint32_t *src_caps = pd_src_caps[port]; + const uint32_t *src_caps = pd_src_caps; /* max voltage is always limited by this boards max request */ max_mv = MIN(max_mv, PD_MAX_VOLTAGE_MV); /* Get max power that is under our max voltage input */ - for (i = 0; i < pd_src_cap_cnt[port]; i++) { + for (i = 0; i < pd_src_cap_cnt; i++) { /* its an unsupported Augmented PDO (PD3.0) */ if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) continue; @@ -149,7 +111,7 @@ void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *mv) { *ma = MIN(max_ma, PD_MAX_CURRENT_MA); } -int pd_build_request(int port, uint32_t *rdo, uint32_t *ma, uint32_t *mv, +int pd_build_request(uint32_t *rdo, uint32_t *ma, uint32_t *mv, enum pd_request_type req_type) { uint32_t pdo; int pdo_index, flags = 0; @@ -160,10 +122,10 @@ int pd_build_request(int port, uint32_t *rdo, uint32_t *ma, uint32_t *mv, if (req_type == PD_REQUEST_VSAFE5V) { /* src cap 0 should be vSafe5V */ pdo_index = 0; - pdo = pd_src_caps[port][0]; + pdo = pd_src_caps[0]; } else { /* find pdo index for max voltage we can request */ - pdo_index = pd_find_pdo_index(port, max_request_mv, &pdo); + pdo_index = pd_find_pdo_index(max_request_mv, &pdo); } pd_extract_pdo_power(pdo, ma, mv); @@ -205,29 +167,29 @@ int pd_build_request(int port, uint32_t *rdo, uint32_t *ma, uint32_t *mv, return EC_SUCCESS; } -void pd_process_source_cap(int port, int cnt, uint32_t *src_caps) { +void pd_process_source_cap(int cnt, uint32_t *src_caps) { #ifdef CONFIG_CHARGE_MANAGER uint32_t ma, mv, pdo; #endif int i; - pd_src_cap_cnt[port] = cnt; + pd_src_cap_cnt = cnt; for (i = 0; i < cnt; i++) - pd_src_caps[port][i] = *src_caps++; + pd_src_caps[i] = *src_caps++; #ifdef CONFIG_CHARGE_MANAGER /* Get max power info that we could request */ - pd_find_pdo_index(port, PD_MAX_VOLTAGE_MV, &pdo); + pd_find_pdo_index( PD_MAX_VOLTAGE_MV, &pdo); pd_extract_pdo_power(pdo, &ma, &mv); /* Set max. limit, but apply 500mA ceiling */ - //charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, PD_MIN_MA); - pd_set_input_current_limit(port, ma, mv); + //charge_manager_set_ceil( CEIL_REQUESTOR_PD, PD_MIN_MA); + pd_set_input_current_limit(ma, mv); #endif } #pragma weak pd_process_source_cap_callback -void pd_process_source_cap_callback(int port, int cnt, uint32_t *src_caps) { +void pd_process_source_cap_callback(int cnt, uint32_t *src_caps) { } void pd_set_max_voltage(unsigned mv) { @@ -257,16 +219,16 @@ static struct pd_policy pe[CONFIG_USB_PD_PORT_COUNT]; void pd_dfp_pe_init(int port) { - memset(&pe[port], 0, sizeof(struct pd_policy)); + memset(&pe, 0, sizeof(struct pd_policy)); } -static void dfp_consume_identity(int port, int cnt, uint32_t *payload) +static void dfp_consume_identity( int cnt, uint32_t *payload) { int ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]); - size_t identity_size = MIN(sizeof(pe[port].identity), + size_t identity_size = MIN(sizeof(pe.identity), (cnt - 1) * sizeof(uint32_t)); pd_dfp_pe_init(port); - memcpy(&pe[port].identity, payload + 1, identity_size); + memcpy(&pe.identity, payload + 1, identity_size); switch (ptype) { case IDH_PTYPE_AMA: /* TODO(tbroch) do I disable VBUS here if power contract @@ -286,19 +248,19 @@ static void dfp_consume_identity(int port, int cnt, uint32_t *payload) } } -static int dfp_discover_svids(int port, uint32_t *payload) +static int dfp_discover_svids( uint32_t *payload) { payload[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID); return 1; } -static void dfp_consume_svids(int port, uint32_t *payload) +static void dfp_consume_svids( uint32_t *payload) { int i; uint32_t *ptr = payload + 1; uint16_t svid0, svid1; - for (i = pe[port].svid_cnt; i < pe[port].svid_cnt + 12; i += 2) { + for (i = pe.svid_cnt; i < pe.svid_cnt + 12; i += 2) { if (i == SVID_DISCOVERY_MAX) { CPRINTF("ERR:SVIDCNT\n"); break; @@ -307,14 +269,14 @@ static void dfp_consume_svids(int port, uint32_t *payload) svid0 = PD_VDO_SVID_SVID0(*ptr); if (!svid0) break; - pe[port].svids[i].svid = svid0; - pe[port].svid_cnt++; + pe.svids[i].svid = svid0; + pe.svid_cnt++; svid1 = PD_VDO_SVID_SVID1(*ptr); if (!svid1) break; - pe[port].svids[i + 1].svid = svid1; - pe[port].svid_cnt++; + pe.svids[i + 1].svid = svid1; + pe.svid_cnt++; ptr++; } /* TODO(tbroch) need to re-issue discover svids if > 12 */ @@ -322,65 +284,65 @@ static void dfp_consume_svids(int port, uint32_t *payload) CPRINTF("ERR:SVID+12\n"); } -static int dfp_discover_modes(int port, uint32_t *payload) +static int dfp_discover_modes( uint32_t *payload) { - uint16_t svid = pe[port].svids[pe[port].svid_idx].svid; - if (pe[port].svid_idx >= pe[port].svid_cnt) + uint16_t svid = pe.svids[pe.svid_idx].svid; + if (pe.svid_idx >= pe.svid_cnt) return 0; payload[0] = VDO(svid, 1, CMD_DISCOVER_MODES); return 1; } -static void dfp_consume_modes(int port, int cnt, uint32_t *payload) +static void dfp_consume_modes( int cnt, uint32_t *payload) { - int idx = pe[port].svid_idx; - pe[port].svids[idx].mode_cnt = cnt - 1; - if (pe[port].svids[idx].mode_cnt < 0) { + int idx = pe.svid_idx; + pe.svids[idx].mode_cnt = cnt - 1; + if (pe.svids[idx].mode_cnt < 0) { CPRINTF("ERR:NOMODE\n"); } else { - memcpy(pe[port].svids[pe[port].svid_idx].mode_vdo, &payload[1], - sizeof(uint32_t) * pe[port].svids[idx].mode_cnt); + memcpy(pe.svids[pe.svid_idx].mode_vdo, &payload[1], + sizeof(uint32_t) * pe.svids[idx].mode_cnt); } - pe[port].svid_idx++; + pe.svid_idx++; } -static int get_mode_idx(int port, uint16_t svid) +static int get_mode_idx( uint16_t svid) { int i; for (i = 0; i < PD_AMODE_COUNT; i++) { - if (pe[port].amodes[i].fx->svid == svid) + if (pe.amodes[i].fx->svid == svid) return i; } return -1; } -static struct svdm_amode_data *get_modep(int port, uint16_t svid) +static struct svdm_amode_data *get_modep( uint16_t svid) { - int idx = get_mode_idx(port, svid); + int idx = get_mode_idx( svid); - return (idx == -1) ? NULL : &pe[port].amodes[idx]; + return (idx == -1) ? NULL : &pe.amodes[idx]; } -int pd_alt_mode(int port, uint16_t svid) +int pd_alt_mode( uint16_t svid) { - struct svdm_amode_data *modep = get_modep(port, svid); + struct svdm_amode_data *modep = get_modep( svid); return (modep) ? modep->opos : -1; } -int allocate_mode(int port, uint16_t svid) +int allocate_mode( uint16_t svid) { int i, j; struct svdm_amode_data *modep; - int mode_idx = get_mode_idx(port, svid); + int mode_idx = get_mode_idx( svid); if (mode_idx != -1) return mode_idx; /* There's no space to enter another mode */ - if (pe[port].amode_idx == PD_AMODE_COUNT) { + if (pe.amode_idx == PD_AMODE_COUNT) { CPRINTF("ERR:NO AMODE SPACE\n"); return -1; } @@ -390,17 +352,17 @@ int allocate_mode(int port, uint16_t svid) if (!&supported_modes[i]) continue; - for (j = 0; j < pe[port].svid_cnt; j++) { - struct svdm_svid_data *svidp = &pe[port].svids[j]; + for (j = 0; j < pe.svid_cnt; j++) { + struct svdm_svid_data *svidp = &pe.svids[j]; if ((svidp->svid != supported_modes[i].svid) || (svid && (svidp->svid != svid))) continue; - modep = &pe[port].amodes[pe[port].amode_idx]; + modep = &pe.amodes[pe.amode_idx]; modep->fx = &supported_modes[i]; - modep->data = &pe[port].svids[j]; - pe[port].amode_idx++; - return pe[port].amode_idx - 1; + modep->data = &pe.svids[j]; + pe.amode_idx++; + return pe.amode_idx - 1; } } return -1; @@ -410,15 +372,15 @@ int allocate_mode(int port, uint16_t svid) * Enter default mode ( payload[0] == 0 ) or attempt to enter mode via svid & * opos */ -uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos) +uint32_t pd_dfp_enter_mode( uint16_t svid, int opos) { - int mode_idx = allocate_mode(port, svid); + int mode_idx = allocate_mode( svid); struct svdm_amode_data *modep; uint32_t mode_caps; if (mode_idx == -1) return 0; - modep = &pe[port].amodes[mode_idx]; + modep = &pe.amodes[mode_idx]; if (!opos) { /* choose the lowest as default */ @@ -431,7 +393,7 @@ uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos) } mode_caps = modep->data->mode_vdo[modep->opos - 1]; - if (modep->fx->enter(port, mode_caps) == -1) + if (modep->fx->enter( mode_caps) == -1) return 0; /* SVDM to send to UFP for mode entry */ @@ -459,17 +421,17 @@ static int validate_mode_request(struct svdm_amode_data *modep, return 1; } -static void dfp_consume_attention(int port, uint32_t *payload) +static void dfp_consume_attention( uint32_t *payload) { uint16_t svid = PD_VDO_VID(payload[0]); int opos = PD_VDO_OPOS(payload[0]); - struct svdm_amode_data *modep = get_modep(port, svid); + struct svdm_amode_data *modep = get_modep( svid); if (!modep || !validate_mode_request(modep, svid, opos)) return; if (modep->fx->attention) - modep->fx->attention(port, payload); + modep->fx->attention( payload); } /* @@ -491,9 +453,9 @@ static void dfp_consume_attention(int port, uint32_t *payload) * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C * receptacle must always choose C/D in those cases. */ -int pd_dfp_dp_get_pin_mode(int port, uint32_t status) +int pd_dfp_dp_get_pin_mode( uint32_t status) { - struct svdm_amode_data *modep = get_modep(port, USB_SID_DISPLAYPORT); + struct svdm_amode_data *modep = get_modep( USB_SID_DISPLAYPORT); uint32_t mode_caps; uint32_t pin_caps; if (!modep) @@ -522,7 +484,7 @@ int pd_dfp_dp_get_pin_mode(int port, uint32_t status) return 1 << get_next_bit(&pin_caps); } -int pd_dfp_exit_mode(int port, uint16_t svid, int opos) +int pd_dfp_exit_mode( uint16_t svid, int opos) { struct svdm_amode_data *modep; int idx; @@ -534,8 +496,8 @@ int pd_dfp_exit_mode(int port, uint16_t svid, int opos) */ if (!svid) { for (idx = 0; idx < PD_AMODE_COUNT; idx++) - if (pe[port].amodes[idx].fx) - pe[port].amodes[idx].fx->exit(port); + if (pe.amodes[idx].fx) + pe.amodes[idx].fx->exit(port); pd_dfp_pe_init(port); return 0; @@ -547,7 +509,7 @@ int pd_dfp_exit_mode(int port, uint16_t svid, int opos) * to exit all modes. We currently don't have any UFPs that support * multiple modes on one SVID. */ - modep = get_modep(port, svid); + modep = get_modep( svid); if (!modep || !validate_mode_request(modep, svid, opos)) return 0; @@ -560,12 +522,12 @@ int pd_dfp_exit_mode(int port, uint16_t svid, int opos) uint16_t pd_get_identity_vid(int port) { - return PD_IDH_VID(pe[port].identity[0]); + return PD_IDH_VID(pe.identity[0]); } uint16_t pd_get_identity_pid(int port) { - return PD_PRODUCT_PID(pe[port].identity[2]); + return PD_PRODUCT_PID(pe.identity[2]); } #ifdef CONFIG_CMD_USB_PD_PE @@ -579,34 +541,34 @@ static void dump_pe(int port) struct svdm_amode_data *modep; uint32_t mode_caps; - if (pe[port].identity[0] == 0) { + if (pe.identity[0] == 0) { ccprintf("No identity discovered yet.\n"); return; } - idh_ptype = PD_IDH_PTYPE(pe[port].identity[0]); + idh_ptype = PD_IDH_PTYPE(pe.identity[0]); ccprintf("IDENT:\n"); - ccprintf("\t[ID Header] %08x :: %s, VID:%04x\n", pe[port].identity[0], + ccprintf("\t[ID Header] %08x :: %s, VID:%04x\n", pe.identity[0], idh_ptype_names[idh_ptype], pd_get_identity_vid(port)); - ccprintf("\t[Cert Stat] %08x\n", pe[port].identity[1]); - for (i = 2; i < ARRAY_SIZE(pe[port].identity); i++) { + ccprintf("\t[Cert Stat] %08x\n", pe.identity[1]); + for (i = 2; i < ARRAY_SIZE(pe.identity); i++) { ccprintf("\t"); - if (pe[port].identity[i]) - ccprintf("[%d] %08x ", i, pe[port].identity[i]); + if (pe.identity[i]) + ccprintf("[%d] %08x ", i, pe.identity[i]); } ccprintf("\n"); - if (pe[port].svid_cnt < 1) { + if (pe.svid_cnt < 1) { ccprintf("No SVIDS discovered yet.\n"); return; } - for (i = 0; i < pe[port].svid_cnt; i++) { - ccprintf("SVID[%d]: %04x MODES:", i, pe[port].svids[i].svid); - for (j = 0; j < pe[port].svids[j].mode_cnt; j++) + for (i = 0; i < pe.svid_cnt; i++) { + ccprintf("SVID[%d]: %04x MODES:", i, pe.svids[i].svid); + for (j = 0; j < pe.svids[j].mode_cnt; j++) ccprintf(" [%d] %08x", j + 1, - pe[port].svids[i].mode_vdo[j]); + pe.svids[i].mode_vdo[j]); ccprintf("\n"); - modep = get_modep(port, pe[port].svids[i].svid); + modep = get_modep( pe.svids[i].svid); if (modep) { mode_caps = modep->data->mode_vdo[modep->opos - 1]; ccprintf("MODE[%d]: svid:%04x caps:%08x\n", modep->opos, @@ -638,10 +600,10 @@ DECLARE_CONSOLE_COMMAND(pe, command_pe, #endif /* CONFIG_USB_PD_ALT_MODE_DFP */ -int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { +int pd_svdm(int cnt, uint32_t *payload, uint32_t **rpayload) { int cmd = PD_VDO_CMD(payload[0]); int cmd_type = PD_VDO_CMDT(payload[0]); - int (*func)(int port, uint32_t *payload) = NULL; + int (*func)(uint32_t *payload) = NULL; int rsize = 1; /* VDM header at a minimum */ @@ -677,7 +639,7 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { * attention is only SVDM with no response * (just goodCRC) return zero here. */ - dfp_consume_attention(port, payload); + dfp_consume_attention( payload); return 0; #endif default: @@ -685,7 +647,7 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { rsize = 0; } if (func) - rsize = func(port, payload); + rsize = func(payload); else /* not supported : NACK it */ rsize = 0; @@ -703,30 +665,30 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { #ifdef CONFIG_USB_PD_ALT_MODE_DFP struct svdm_amode_data *modep; - modep = get_modep(port, PD_VDO_VID(payload[0])); + modep = get_modep( PD_VDO_VID(payload[0])); #endif switch (cmd) { #ifdef CONFIG_USB_PD_ALT_MODE_DFP case CMD_DISCOVER_IDENT: - dfp_consume_identity(port, cnt, payload); - rsize = dfp_discover_svids(port, payload); + dfp_consume_identity( cnt, payload); + rsize = dfp_discover_svids( payload); #ifdef CONFIG_CHARGE_MANAGER if (pd_charge_from_device(pd_get_identity_vid(port), pd_get_identity_pid(port))) - charge_manager_update_dualrole(port, + charge_manager_update_dualrole( CAP_DEDICATED); #endif break; case CMD_DISCOVER_SVID: - dfp_consume_svids(port, payload); - rsize = dfp_discover_modes(port, payload); + dfp_consume_svids( payload); + rsize = dfp_discover_modes( payload); break; case CMD_DISCOVER_MODES: - dfp_consume_modes(port, cnt, payload); - rsize = dfp_discover_modes(port, payload); + dfp_consume_modes( cnt, payload); + rsize = dfp_discover_modes( payload); /* enter the default mode for DFP */ if (!rsize) { - payload[0] = pd_dfp_enter_mode(port, 0, 0); + payload[0] = pd_dfp_enter_mode( 0, 0); if (payload[0]) rsize = 1; } @@ -736,10 +698,10 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { rsize = 0; } else { if (!modep->opos) - pd_dfp_enter_mode(port, 0, 0); + pd_dfp_enter_mode( 0, 0); if (modep->opos) { - rsize = modep->fx->status(port, + rsize = modep->fx->status( payload); payload[0] |= PD_VDO_OPOS(modep->opos); } @@ -748,9 +710,9 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { case CMD_DP_STATUS: /* DP status response & UFP's DP attention have same payload */ - dfp_consume_attention(port, payload); + dfp_consume_attention( payload); if (modep && modep->opos) - rsize = modep->fx->config(port, payload); + rsize = modep->fx->config( payload); else rsize = 0; break; @@ -810,7 +772,7 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { #else -int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) +int pd_svdm( int cnt, uint32_t *payload, uint32_t **rpayload) { return 0; } @@ -818,7 +780,7 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) #endif /* CONFIG_USB_PD_ALT_MODE */ #ifndef CONFIG_USB_PD_CUSTOM_VDM -int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { +int pd_vdm(int cnt, uint32_t *payload, uint32_t **rpayload) { return 0; } #endif /* !CONFIG_USB_PD_CUSTOM_VDM */ @@ -837,7 +799,6 @@ static void pd_usb_billboard_deferred(void) { #endif } -DECLARE_DEFERRED( pd_usb_billboard_deferred); #ifdef CONFIG_USB_PD_ALT_MODE_DFP static int hc_remote_pd_discovery(struct host_cmd_handler_args *args) @@ -897,110 +858,12 @@ DECLARE_HOST_COMMAND(EC_CMD_USB_PD_GET_AMODE, #define FW_RW_END (CONFIG_EC_WRITABLE_STORAGE_OFF + \ CONFIG_RW_STORAGE_OFF + CONFIG_RW_SIZE) -/* - uint8_t *flash_hash_rw(void) - { - static struct sha256_ctx ctx; - - // re-calculate RW hash when changed as its time consuming - if (rw_flash_changed) { - rw_flash_changed = 0; - SHA256_init(&ctx); - SHA256_update(&ctx, (void *)CONFIG_PROGRAM_MEMORY_BASE + - CONFIG_RW_MEM_OFF, - CONFIG_RW_SIZE - RSANUMBYTES); - return SHA256_final(&ctx); - } else { - return ctx.buf; - } - } - - - void pd_get_info(uint32_t *info_data) - { - void *rw_hash = flash_hash_rw(); - - // copy first 20 bytes of RW hash - memcpy(info_data, rw_hash, 5 * sizeof(uint32_t)); - // copy other info into data msg - #if defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR) && \ - defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR) - info_data[5] = VDO_INFO(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR, - CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR, - ver_get_numcommits(), - (system_get_image_copy() != SYSTEM_IMAGE_RO)); - #else - info_data[5] = 0; - #endif - } - - int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload) - { - static int flash_offset; - int rsize = 1; // default is just VDM header returned - - switch (PD_VDO_CMD(payload[0])) { - case VDO_CMD_VERSION: - memcpy(payload + 1, ¤t_image_data.version, 24); - rsize = 7; - break; - case VDO_CMD_REBOOT: - // ensure the power supply is in a safe state - pd_power_supply_reset(0); - system_reset(0); - break; - case VDO_CMD_READ_INFO: - // copy info into response - pd_get_info(payload + 1); - rsize = 7; - break; - case VDO_CMD_FLASH_ERASE: - // do not kill the code under our feet - if (system_get_image_copy() != SYSTEM_IMAGE_RO) - break; - pd_log_event(PD_EVENT_ACC_RW_ERASE, 0, 0, NULL); - flash_offset = CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF; - flash_physical_erase(CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF, CONFIG_RW_SIZE); - rw_flash_changed = 1; - break; - case VDO_CMD_FLASH_WRITE: - // do not kill the code under our feet - if ((system_get_image_copy() != SYSTEM_IMAGE_RO) || - (flash_offset < CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF)) - break; - flash_physical_write(flash_offset, 4*(cnt - 1), - (const char *)(payload+1)); - flash_offset += 4*(cnt - 1); - rw_flash_changed = 1; - break; - case VDO_CMD_ERASE_SIG: - // this is not touching the code area - { - uint32_t zero = 0; - int offset; - // zeroes the area containing the RSA signature - for (offset = FW_RW_END - RSANUMBYTES; - offset < FW_RW_END; offset += 4) - flash_physical_write(offset, 4, - (const char *)&zero); - } - break; - default: - // Unknown : do not answer - return 0; - } - return rsize; - } - */ #ifdef CONFIG_USB_PD_DISCHARGE -void pd_set_vbus_discharge(int port, int enable) +void pd_set_vbus_discharge( int enable) { static struct mutex discharge_lock[CONFIG_USB_PD_PORT_COUNT]; - mutex_lock(&discharge_lock[port]); + mutex_lock(&discharge_lock); enable &= !board_vbus_source_enabled(port); #ifdef CONFIG_USB_PD_DISCHARGE_GPIO if (!port) @@ -1010,10 +873,10 @@ void pd_set_vbus_discharge(int port, int enable) gpio_set_level(GPIO_USB_C1_DISCHARGE, enable); #endif /* CONFIG_USB_PD_PORT_COUNT */ #elif defined(CONFIG_USB_PD_DISCHARGE_TCPC) - tcpc_discharge_vbus(port, enable); + tcpc_discharge_vbus( enable); #else #error "PD discharge implementation not defined" #endif - mutex_unlock(&discharge_lock[port]); + mutex_unlock(&discharge_lock); } #endif /* CONFIG_USB_PD_DISCHARGE */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.cpp b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.cpp index 1b1cc383..1ef96807 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.cpp @@ -42,17 +42,17 @@ static uint8_t pd_comm_enabled[CONFIG_USB_PD_PORT_COUNT]; #else /* CONFIG_COMMON_RUNTIME */ #define CPRINTF(format, args...) #define CPRINTS(format, args...) -static const int debug_level=0; +static const int debug_level = 0; #endif #ifdef CONFIG_USB_PD_DUAL_ROLE -#define DUAL_ROLE_IF_ELSE(port, sink_clause, src_clause) \ - (pd[port].power_role == PD_ROLE_SINK ? (sink_clause) : (src_clause)) +#define DUAL_ROLE_IF_ELSE( sink_clause, src_clause) \ + (pd.power_role == PD_ROLE_SINK ? (sink_clause) : (src_clause)) #else -#define DUAL_ROLE_IF_ELSE(port, sink_clause, src_clause) (src_clause) +#define DUAL_ROLE_IF_ELSE( sink_clause, src_clause) (src_clause) #endif -#define READY_RETURN_STATE(port) DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_READY, \ +#define READY_RETURN_STATE() DUAL_ROLE_IF_ELSE( PD_STATE_SNK_READY, \ PD_STATE_SRC_READY) /* Type C supply voltage (mV) */ @@ -126,7 +126,7 @@ static uint64_t next_role_swap = PD_T_DRP_SNK; static int snk_hard_reset_vbus_off = 0; #endif #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE -static const int auto_toggle_supported = tcpm_auto_toggle_supported(port); +static const int auto_toggle_supported = tcpm_auto_toggle_supported(); #endif #if defined(CONFIG_CHARGE_MANAGER) static typec_current_t typec_curr = 0, typec_curr_change = 0; @@ -208,7 +208,7 @@ static struct pd_protocol { /* protocol revision */ uint8_t rev; #endif -} pd[CONFIG_USB_PD_PORT_COUNT]; +} pd; #ifdef CONFIG_COMMON_RUNTIME static const char * const pd_state_names[] = { @@ -248,7 +248,7 @@ BUILD_ASSERT(ARRAY_SIZE(pd_state_names) == PD_STATE_COUNT); static struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES]; #endif -int pd_comm_is_enabled(int port) { +int pd_comm_is_enabled() { #ifdef CONFIG_COMMON_RUNTIME return pd_comm_enabled[port]; #else @@ -256,71 +256,71 @@ int pd_comm_is_enabled(int port) { #endif } -static inline void set_state_timeout(int port, uint64_t timeout, +static inline void set_state_timeout(uint64_t timeout, enum pd_states timeout_state) { - pd[port].timeout = timeout; - pd[port].timeout_state = timeout_state; + pd.timeout = timeout; + pd.timeout_state = timeout_state; } #ifdef CONFIG_USB_PD_REV30 -int pd_get_rev(int port) +int pd_get_rev() { - return pd[port].rev; + return pd.rev; } -int pd_get_vdo_ver(int port) +int pd_get_vdo_ver() { - return vdo_ver[pd[port].rev]; + return vdo_ver[pd.rev]; } #endif /* Return flag for pd state is connected */ -int pd_is_connected(int port) { - if (pd[port].task_state == PD_STATE_DISABLED) +int pd_is_connected() { + if (pd.task_state == PD_STATE_DISABLED) return 0; #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - if (pd[port].task_state == PD_STATE_DRP_AUTO_TOGGLE) + if (pd.task_state == PD_STATE_DRP_AUTO_TOGGLE) return 0; #endif - return DUAL_ROLE_IF_ELSE(port, + return DUAL_ROLE_IF_ELSE( /* sink */ - pd[port].task_state != PD_STATE_SNK_DISCONNECTED && pd[port].task_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE, + pd.task_state != PD_STATE_SNK_DISCONNECTED && pd.task_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE, /* source */ - pd[port].task_state != PD_STATE_SRC_DISCONNECTED && pd[port].task_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE); + pd.task_state != PD_STATE_SRC_DISCONNECTED && pd.task_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE); } /* * Return true if partner port is a DTS or TS capable of entering debug * mode (eg. is presenting Rp/Rp or Rd/Rd). */ -int pd_ts_dts_plugged(int port) { - return pd[port].flags & PD_FLAGS_TS_DTS_PARTNER; +int pd_ts_dts_plugged() { + return pd.flags & PD_FLAGS_TS_DTS_PARTNER; } #ifdef CONFIG_USB_PD_DUAL_ROLE -void pd_vbus_low(int port) { - pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW; +void pd_vbus_low() { + pd.flags &= ~PD_FLAGS_VBUS_NEVER_LOW; } -static inline int pd_is_vbus_present(int port) { +static inline int pd_is_vbus_present() { #ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - return tcpm_get_vbus_level(port); + return tcpm_get_vbus_level(); #else - return pd_snk_is_vbus_provided(port); + return pd_snk_is_vbus_provided(); #endif } #endif -static inline void set_state(int port, enum pd_states next_state) { - enum pd_states last_state = pd[port].task_state; +static inline void set_state(enum pd_states next_state) { + enum pd_states last_state = pd.task_state; #ifdef CONFIG_LOW_POWER_IDLE int i; #endif - set_state_timeout(port, 0, PD_STATE_DISABLED); - pd[port].task_state = next_state; + set_state_timeout(0, PD_STATE_DISABLED); + pd.task_state = next_state; if (last_state == next_state) return; @@ -329,7 +329,7 @@ static inline void set_state(int port, enum pd_states next_state) { #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE /* Clear flag to allow DRP auto toggle when possible */ if (last_state != PD_STATE_DRP_AUTO_TOGGLE) - pd[port].flags &= ~PD_FLAGS_TCPC_DRP_TOGGLE; + pd.flags &= ~PD_FLAGS_TCPC_DRP_TOGGLE; #endif /* Ignore dual-role toggling between sink and source */ @@ -342,56 +342,40 @@ static inline void set_state(int port, enum pd_states next_state) { if (next_state == PD_STATE_SRC_DISCONNECTED || next_state == PD_STATE_SNK_DISCONNECTED) { /* Clear the input current limit */ - pd_set_input_current_limit(port, 0, 0); + pd_set_input_current_limit(0, 0); #ifdef CONFIG_CHARGE_MANAGER - //typec_set_input_current_limit(port, 0, 0); - //charge_manager_set_ceil(port, + //typec_set_input_current_limit( 0, 0); + //charge_manager_set_ceil( // CEIL_REQUESTOR_PD, // CHARGE_CEIL_NONE); #endif #ifdef CONFIG_USBC_VCONN - tcpm_set_vconn(port, 0); + tcpm_set_vconn( 0); #endif #else /* CONFIG_USB_PD_DUAL_ROLE */ if (next_state == PD_STATE_SRC_DISCONNECTED) { #endif - /* - * If we are source, make sure VBUS is off and - * if PD REV3.0, restore RP. - */ - if (pd[port].power_role == PD_ROLE_SOURCE) { - /* - * Rp is restored by pd_power_supply_reset if - * CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT is defined. - */ - pd_power_supply_reset(port); -#if !defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) && \ - defined(CONFIG_USB_PD_REV30) - /* Restore Rp */ - tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP); - tcpm_set_cc(port, TYPEC_CC_RP); -#endif - } + #ifdef CONFIG_USB_PD_REV30 /* Adjust rev to highest level*/ - pd[port].rev = PD_REV30; + pd.rev = PD_REV30; #endif #ifdef CONFIG_USB_PD_CHROMEOS - pd[port].dev_id = 0; - pd[port].flags &= ~PD_FLAGS_RESET_ON_DISCONNECT_MASK; + pd.dev_id = 0; + pd.flags &= ~PD_FLAGS_RESET_ON_DISCONNECT_MASK; #endif #ifdef CONFIG_CHARGE_MANAGER - //charge_manager_update_dualrole(port, CAP_UNKNOWN); + //charge_manager_update_dualrole( CAP_UNKNOWN); #endif #ifdef CONFIG_USB_PD_ALT_MODE_DFP - pd_dfp_exit_mode(port, 0, 0); + pd_dfp_exit_mode( 0, 0); #endif #ifdef CONFIG_USBC_SS_MUX - usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, - pd[port].polarity); + usb_mux_set( TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, + pd.polarity); #endif /* Disable TCPC RX */ - tcpm_set_rx_enable(port, 0); + tcpm_set_rx_enable(0); } #ifdef CONFIG_LOW_POWER_IDLE @@ -414,38 +398,38 @@ static inline void set_state(int port, enum pd_states next_state) { } /* increment message ID counter */ -static void inc_id(int port) { - pd[port].msg_id = (pd[port].msg_id + 1) & PD_MESSAGE_ID_COUNT; +static void inc_id() { + pd.msg_id = (pd.msg_id + 1) & PD_MESSAGE_ID_COUNT; } #ifdef CONFIG_USB_PD_REV30 -static void sink_can_xmit(int port, int rp) +static void sink_can_xmit( int rp) { - tcpm_select_rp_value(port, rp); - tcpm_set_cc(port, TYPEC_CC_RP); + tcpm_select_rp_value( rp); + tcpm_set_cc( TYPEC_CC_RP); } -static inline void pd_ca_reset(int port) +static inline void pd_ca_reset() { - pd[port].ca_buffered = 0; + pd.ca_buffered = 0; } #endif -void pd_transmit_complete(int port, int status) { +void pd_transmit_complete(int status) { if (status == TCPC_TX_COMPLETE_SUCCESS) - inc_id(port); + inc_id(); - pd[port].tx_status = status; - //task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX, 0); + pd.tx_status = status; + //task_set_event(PD_PORT_TO_TASK_ID(), PD_EVENT_TX, 0); pd_task_set_event(PD_EVENT_TX, 0); } -static int pd_transmit(int port, enum tcpm_transmit_type type, uint16_t header, +static int pd_transmit(enum tcpm_transmit_type type, uint16_t header, const uint32_t *data) { int evt; /* If comms are disabled, do not transmit, return error */ - if (!pd_comm_is_enabled(port)) + if (!pd_comm_is_enabled()) return -1; #ifdef CONFIG_USB_PD_REV30 /* Source-coordinated collision avoidance */ @@ -465,9 +449,9 @@ static int pd_transmit(int port, enum tcpm_transmit_type type, uint16_t header, * * Note: a Sink can still send Hard Reset signaling at any time. */ - if ((pd[port].rev == PD_REV30) && - (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT)) { - if (pd[port].power_role == PD_ROLE_SOURCE) { + if ((pd.rev == PD_REV30) && + (pd.flags & PD_FLAGS_EXPLICIT_CONTRACT)) { + if (pd.power_role == PD_ROLE_SOURCE) { /* * Inform Sink that it can't transmit. If a sink * transmition is in progress and a collsion occurs, @@ -475,32 +459,32 @@ static int pd_transmit(int port, enum tcpm_transmit_type type, uint16_t header, * all extended messages are chunked. This effectively * defaults to PD REV 2.0 collision avoidance. */ - sink_can_xmit(port, SINK_TX_NG); + sink_can_xmit( SINK_TX_NG); } else if (type != TCPC_TX_HARD_RESET) { int cc1; int cc2; - tcpm_get_cc(port, &cc1, &cc2); + tcpm_get_cc( &cc1, &cc2); if (cc1 == TYPEC_CC_VOLT_SNK_1_5 || cc2 == TYPEC_CC_VOLT_SNK_1_5) { /* Sink can't transmit now. */ /* Check if message is already buffered. */ - if (pd[port].ca_buffered) + if (pd.ca_buffered) return -1; /* Buffer message and send later. */ - pd[port].ca_type = type; - pd[port].ca_header = header; - memcpy(pd[port].ca_buffer, + pd.ca_type = type; + pd.ca_header = header; + memcpy(pd.ca_buffer, data, sizeof(uint32_t) * PD_HEADER_CNT(header)); - pd[port].ca_buffered = 1; + pd.ca_buffered = 1; return 1; } } } #endif - tcpm_transmit(port, type, header, data); + tcpm_transmit(type, header, data); /* Wait until TX is complete */ // Would wait, except that we're making tcpm_transmit blocking @@ -510,10 +494,10 @@ static int pd_transmit(int port, enum tcpm_transmit_type type, uint16_t header, * If the source just completed a transmit, tell * the sink it can transmit if it wants to. */ - if ((pd[port].rev == PD_REV30) && - (pd[port].power_role == PD_ROLE_SOURCE) && - (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT)) { - sink_can_xmit(port, SINK_TX_OK); + if ((pd.rev == PD_REV30) && + (pd.power_role == PD_ROLE_SOURCE) && + (pd.flags & PD_FLAGS_EXPLICIT_CONTRACT)) { + sink_can_xmit( SINK_TX_OK); } #endif @@ -522,50 +506,50 @@ static int pd_transmit(int port, enum tcpm_transmit_type type, uint16_t header, // return -1; /* TODO: give different error condition for failed vs discarded */ - return pd[port].tx_status == TCPC_TX_COMPLETE_SUCCESS ? 1 : -1; + return pd.tx_status == TCPC_TX_COMPLETE_SUCCESS ? 1 : -1; } #ifdef CONFIG_USB_PD_REV30 -static void pd_ca_send_pending(int port) +static void pd_ca_send_pending() { int cc1; int cc2; /* Check if a message has been buffered. */ - if (!pd[port].ca_buffered) + if (!pd.ca_buffered) return; - tcpm_get_cc(port, &cc1, &cc2); + tcpm_get_cc( &cc1, &cc2); if ((cc1 != TYPEC_CC_VOLT_SNK_1_5) && (cc2 != TYPEC_CC_VOLT_SNK_1_5)) - if (pd_transmit(port, pd[port].ca_type, - pd[port].ca_header, - pd[port].ca_buffer) < 0) + if (pd_transmit( pd.ca_type, + pd.ca_header, + pd.ca_buffer) < 0) return; /* Message was sent, so free up the buffer. */ - pd[port].ca_buffered = 0; + pd.ca_buffered = 0; } #endif -static void pd_update_roles(int port) { +static void pd_update_roles() { /* Notify TCPC of role update */ - tcpm_set_msg_header(port, pd[port].power_role, pd[port].data_role); + tcpm_set_msg_header(pd.power_role, pd.data_role); } -static int send_control(int port, int type) { +static int send_control(int type) { int bit_len; - uint16_t header = PD_HEADER(type, pd[port].power_role, pd[port].data_role, - pd[port].msg_id, 0, pd_get_rev(port), 0); + uint16_t header = PD_HEADER(type, pd.power_role, pd.data_role, pd.msg_id, 0, + pd_get_rev(), 0); - bit_len = pd_transmit(port, TCPC_TX_SOP, header, NULL); + bit_len = pd_transmit(TCPC_TX_SOP, header, NULL); if (debug_level >= 2) CPRINTF("CTRL[%d]>%d\n", type, bit_len); return bit_len; } -static int send_source_cap(int port) { +static int send_source_cap() { int bit_len; #if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) @@ -579,14 +563,13 @@ static int send_source_cap(int port) { if (src_pdo_cnt == 0) /* No source capabilities defined, sink only */ - header = PD_HEADER(PD_CTRL_REJECT, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, 0, pd_get_rev(port), 0); + header = PD_HEADER(PD_CTRL_REJECT, pd.power_role, pd.data_role, + pd.msg_id, 0, pd_get_rev(), 0); else - header = PD_HEADER(PD_DATA_SOURCE_CAP, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, src_pdo_cnt, - pd_get_rev(port), 0); + header = PD_HEADER(PD_DATA_SOURCE_CAP, pd.power_role, pd.data_role, + pd.msg_id, src_pdo_cnt, pd_get_rev(), 0); - bit_len = pd_transmit(port, TCPC_TX_SOP, header, src_pdo); + bit_len = pd_transmit(TCPC_TX_SOP, header, src_pdo); if (debug_level >= 2) CPRINTF("srcCAP>%d\n", bit_len); @@ -594,16 +577,16 @@ static int send_source_cap(int port) { } #ifdef CONFIG_USB_PD_REV30 -static int send_battery_cap(int port, uint32_t *payload) +static int send_battery_cap( uint32_t *payload) { int bit_len; uint16_t msg[6] = {0, 0, 0, 0, 0, 0}; uint16_t header = PD_HEADER(PD_EXT_BATTERY_CAP, - pd[port].power_role, - pd[port].data_role, - pd[port].msg_id, + pd.power_role, + pd.data_role, + pd.msg_id, 3, /* Number of Data Objects */ - pd[port].rev, + pd.rev, 1 /* This is an exteded message */ ); @@ -673,22 +656,22 @@ static int send_battery_cap(int port, uint32_t *payload) } } - bit_len = pd_transmit(port, TCPC_TX_SOP, header, (uint32_t *)msg); + bit_len = pd_transmit( TCPC_TX_SOP, header, (uint32_t *)msg); if (debug_level >= 2) CPRINTF("batCap>%d\n", bit_len); return bit_len; } -static int send_battery_status(int port, uint32_t *payload) +static int send_battery_status( uint32_t *payload) { int bit_len; uint32_t msg = 0; uint16_t header = PD_HEADER(PD_DATA_BATTERY_STATUS, - pd[port].power_role, - pd[port].data_role, - pd[port].msg_id, + pd.power_role, + pd.data_role, + pd.msg_id, 1, /* Number of Data Objects */ - pd[port].rev, + pd.rev, 0 /* This is NOT an extended message */ ); @@ -740,7 +723,7 @@ static int send_battery_status(int port, uint32_t *payload) msg = BSDO_CAP(BSDO_CAP_UNKNOWN); } - bit_len = pd_transmit(port, TCPC_TX_SOP, header, &msg); + bit_len = pd_transmit( TCPC_TX_SOP, header, &msg); if (debug_level >= 2) CPRINTF("batStat>%d\n", bit_len); @@ -749,30 +732,30 @@ static int send_battery_status(int port, uint32_t *payload) #endif #ifdef CONFIG_USB_PD_DUAL_ROLE -static void send_sink_cap(int port) { +static void send_sink_cap() { int bit_len; - uint16_t header = PD_HEADER(PD_DATA_SINK_CAP, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, pd_snk_pdo_cnt, - pd_get_rev(port), 0); + uint16_t header = PD_HEADER(PD_DATA_SINK_CAP, pd.power_role, + pd.data_role, pd.msg_id, pd_snk_pdo_cnt, pd_get_rev(), + 0); - bit_len = pd_transmit(port, TCPC_TX_SOP, header, pd_snk_pdo); + bit_len = pd_transmit(TCPC_TX_SOP, header, pd_snk_pdo); if (debug_level >= 2) CPRINTF("snkCAP>%d\n", bit_len); } -static int send_request(int port, uint32_t rdo) { +static int send_request(uint32_t rdo) { int bit_len; - uint16_t header = PD_HEADER(PD_DATA_REQUEST, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, 1, pd_get_rev(port), 0); + uint16_t header = PD_HEADER(PD_DATA_REQUEST, pd.power_role, + pd.data_role, pd.msg_id, 1, pd_get_rev(), 0); - bit_len = pd_transmit(port, TCPC_TX_SOP, header, &rdo); + bit_len = pd_transmit(TCPC_TX_SOP, header, &rdo); if (debug_level >= 2) CPRINTF("REQ%d>\n", bit_len); return bit_len; } #ifdef CONFIG_BBRAM -static int pd_get_saved_active(int port) +static int pd_get_saved_active() { uint8_t val; @@ -784,7 +767,7 @@ static int pd_get_saved_active(int port) return !!val; } -static void pd_set_saved_active(int port, int val) +static void pd_set_saved_active( int val) { if (system_set_bbram(port ? SYSTEM_BBRAM_IDX_PD1 : SYSTEM_BBRAM_IDX_PD0, val)) @@ -794,56 +777,53 @@ static void pd_set_saved_active(int port, int val) #endif /* CONFIG_USB_PD_DUAL_ROLE */ #ifdef CONFIG_COMMON_RUNTIME -static int send_bist_cmd(int port) +static int send_bist_cmd() { /* currently only support sending bist carrier 2 */ uint32_t bdo = BDO(BDO_MODE_CARRIER2, 0); int bit_len; - uint16_t header = PD_HEADER(PD_DATA_BIST, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, 1, - pd_get_rev(port), 0); + uint16_t header = PD_HEADER(PD_DATA_BIST, pd.power_role, + pd.data_role, pd.msg_id, 1, + pd_get_rev(), 0); - bit_len = pd_transmit(port, TCPC_TX_SOP, header, &bdo); + bit_len = pd_transmit( TCPC_TX_SOP, header, &bdo); CPRINTF("BIST>%d\n", bit_len); return bit_len; } #endif -static void queue_vdm(int port, uint32_t *header, const uint32_t *data, - int data_cnt) { - pd[port].vdo_count = data_cnt + 1; - pd[port].vdo_data[0] = header[0]; - memcpy(&pd[port].vdo_data[1], data, sizeof(uint32_t) * data_cnt); +static void queue_vdm(uint32_t *header, const uint32_t *data, int data_cnt) { + pd.vdo_count = data_cnt + 1; + pd.vdo_data[0] = header[0]; + memcpy(&pd.vdo_data[1], data, sizeof(uint32_t) * data_cnt); /* Set ready, pd task will actually send */ - pd[port].vdm_state = VDM_STATE_READY; + pd.vdm_state = VDM_STATE_READY; } -static void handle_vdm_request(int port, int cnt, uint32_t *payload) { +static void handle_vdm_request(int cnt, uint32_t *payload) { int rlen = 0; uint32_t *rdata; - if (pd[port].vdm_state == VDM_STATE_BUSY) { + if (pd.vdm_state == VDM_STATE_BUSY) { /* If UFP responded busy retry after timeout */ if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_BUSY) { - pd[port].vdm_timeout.val = get_time().val + + pd.vdm_timeout.val = get_time().val + PD_T_VDM_BUSY; - pd[port].vdm_state = VDM_STATE_WAIT_RSP_BUSY; - pd[port].vdo_retry = (payload[0] & ~VDO_CMDT_MASK) | + pd.vdm_state = VDM_STATE_WAIT_RSP_BUSY; + pd.vdo_retry = (payload[0] & ~VDO_CMDT_MASK) | CMDT_INIT; return; } else { - pd[port].vdm_state = VDM_STATE_DONE; + pd.vdm_state = VDM_STATE_DONE; } } if (PD_VDO_SVDM(payload[0])) - rlen = pd_svdm(port, cnt, payload, &rdata); - else - rlen = pd_custom_vdm(port, cnt, payload, &rdata); + rlen = pd_svdm(cnt, payload, &rdata); if (rlen > 0) { - queue_vdm(port, rdata, &rdata[1], rlen - 1); + queue_vdm(rdata, &rdata[1], rlen - 1); return; } if (debug_level >= 2) @@ -851,75 +831,73 @@ static void handle_vdm_request(int port, int cnt, uint32_t *payload) { PD_VDO_VID(payload[0]), payload[0] & 0xFFFF); } -void pd_execute_hard_reset(int port) { - if (pd[port].last_state == PD_STATE_HARD_RESET_SEND) +void pd_execute_hard_reset() { + if (pd.last_state == PD_STATE_HARD_RESET_SEND) CPRINTF("C%d HARD RST TX\n", port); else CPRINTF("C%d HARD RST RX\n", port); - pd[port].msg_id = 0; + pd.msg_id = 0; #ifdef CONFIG_USB_PD_ALT_MODE_DFP - pd_dfp_exit_mode(port, 0, 0); + pd_dfp_exit_mode( 0, 0); #endif #ifdef CONFIG_USB_PD_REV30 - pd[port].rev = PD_REV30; - pd_ca_reset(port); + pd.rev = PD_REV30; + pd_ca_reset(); #endif /* * Fake set last state to hard reset to make sure that the next * state to run knows that we just did a hard reset. */ - pd[port].last_state = PD_STATE_HARD_RESET_EXECUTE; + pd.last_state = PD_STATE_HARD_RESET_EXECUTE; #ifdef CONFIG_USB_PD_DUAL_ROLE /* * If we are swapping to a source and have changed to Rp, restore back * to Rd and turn off vbus to match our power_role. */ - if (pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY - || pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE) { - tcpm_set_cc(port, TYPEC_CC_RD); - pd_power_supply_reset(port); + if (pd.task_state == PD_STATE_SNK_SWAP_STANDBY + || pd.task_state == PD_STATE_SNK_SWAP_COMPLETE) { + tcpm_set_cc(TYPEC_CC_RD); + pd_power_supply_reset(); } - if (pd[port].power_role == PD_ROLE_SINK) { + if (pd.power_role == PD_ROLE_SINK) { /* Clear the input current limit */ - pd_set_input_current_limit(port, 0, 0); + pd_set_input_current_limit(0, 0); #ifdef CONFIG_CHARGE_MANAGER - //charge_manager_set_ceil(port, + //charge_manager_set_ceil( // CEIL_REQUESTOR_PD, // CHARGE_CEIL_NONE); #endif /* CONFIG_CHARGE_MANAGER */ - set_state(port, PD_STATE_SNK_HARD_RESET_RECOVER); + set_state (PD_STATE_SNK_HARD_RESET_RECOVER); return; } #endif /* CONFIG_USB_PD_DUAL_ROLE */ /* We are a source, cut power */ - pd_power_supply_reset(port); - pd[port].src_recover = get_time().val + PD_T_SRC_RECOVER; - set_state(port, PD_STATE_SRC_HARD_RESET_RECOVER); + pd_power_supply_reset(); + pd.src_recover = get_time().val + PD_T_SRC_RECOVER; + set_state(PD_STATE_SRC_HARD_RESET_RECOVER); } -static void execute_soft_reset(int port) { - pd[port].msg_id = 0; - set_state(port, - DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_DISCOVERY, - PD_STATE_SRC_DISCOVERY)); +static void execute_soft_reset() { + pd.msg_id = 0; + set_state( + DUAL_ROLE_IF_ELSE(PD_STATE_SNK_DISCOVERY, PD_STATE_SRC_DISCOVERY)); CPRINTF("C%d Soft Rst\n", port); } void pd_soft_reset(void) { int i; - for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; ++i) - if (pd_is_connected(i)) { - set_state(i, PD_STATE_SOFT_RESET); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(i)); - } + if (pd_is_connected()) { + set_state(PD_STATE_SOFT_RESET); + // getting rid of task stuff + //task_wake(PD_PORT_TO_TASK_ID(i)); + } } #ifdef CONFIG_USB_PD_DUAL_ROLE @@ -927,7 +905,7 @@ void pd_soft_reset(void) { * Request desired charge voltage from source. * Returns EC_SUCCESS on success or non-zero on failure. */ -static int pd_send_request_msg(int port, int always_send_request) { +static int pd_send_request_msg(int always_send_request) { uint32_t rdo, curr_limit, supply_voltage; int res; @@ -945,14 +923,14 @@ static int pd_send_request_msg(int port, int always_send_request) { #endif /* Clear new power request */ - pd[port].new_power_request = 0; + pd.new_power_request = 0; /* Build and send request RDO */ /* * If this port is not actively charging or we are not allowed to * request the max voltage, then select vSafe5V */ - res = pd_build_request(port, &rdo, &curr_limit, &supply_voltage, + res = pd_build_request(&rdo, &curr_limit, &supply_voltage, charging && max_request_allowed ? PD_REQUEST_MAX : PD_REQUEST_VSAFE5V); @@ -965,38 +943,38 @@ static int pd_send_request_msg(int port, int always_send_request) { if (!always_send_request) { /* Don't re-request the same voltage */ - if (pd[port].prev_request_mv == supply_voltage) + if (pd.prev_request_mv == supply_voltage) return EC_SUCCESS; #ifdef CONFIG_CHARGE_MANAGER /* Limit current to PD_MIN_MA during transition */ //else - // charge_manager_force_ceil(port, PD_MIN_MA); + // charge_manager_force_ceil( PD_MIN_MA); #endif } CPRINTF("Req C%d [%d] %dmV %dmA", port, RDO_POS(rdo), supply_voltage, curr_limit); if (rdo & RDO_CAP_MISMATCH) - CPRINTF(" Mismatch"); CPRINTF("\n"); + CPRINTF(" Mismatch");CPRINTF("\n"); - pd[port].curr_limit = curr_limit; - pd[port].supply_voltage = supply_voltage; - pd[port].prev_request_mv = supply_voltage; - res = send_request(port, rdo); + pd.curr_limit = curr_limit; + pd.supply_voltage = supply_voltage; + pd.prev_request_mv = supply_voltage; + res = send_request(rdo); if (res < 0) return res; - set_state(port, PD_STATE_SNK_REQUESTED); + set_state (PD_STATE_SNK_REQUESTED); return EC_SUCCESS; } #endif -static void pd_update_pdo_flags(int port, uint32_t pdo) { +static void pd_update_pdo_flags(uint32_t pdo) { #ifdef CONFIG_CHARGE_MANAGER #ifdef CONFIG_USB_PD_ALT_MODE_DFP int charge_whitelisted = - (pd[port].power_role == PD_ROLE_SINK && - pd_charge_from_device(pd_get_identity_vid(port), - pd_get_identity_pid(port))); + (pd.power_role == PD_ROLE_SINK && + pd_charge_from_device(pd_get_identity_vid(), + pd_get_identity_pid())); #else const int charge_whitelisted = 0; #endif @@ -1008,25 +986,25 @@ static void pd_update_pdo_flags(int port, uint32_t pdo) { #ifdef CONFIG_USB_PD_DUAL_ROLE if (pdo & PDO_FIXED_DUAL_ROLE) - pd[port].flags |= PD_FLAGS_PARTNER_DR_POWER; + pd.flags |= PD_FLAGS_PARTNER_DR_POWER; else - pd[port].flags &= ~PD_FLAGS_PARTNER_DR_POWER; + pd.flags &= ~PD_FLAGS_PARTNER_DR_POWER; if (pdo & PDO_FIXED_EXTERNAL) - pd[port].flags |= PD_FLAGS_PARTNER_EXTPOWER; + pd.flags |= PD_FLAGS_PARTNER_EXTPOWER; else - pd[port].flags &= ~PD_FLAGS_PARTNER_EXTPOWER; + pd.flags &= ~PD_FLAGS_PARTNER_EXTPOWER; if (pdo & PDO_FIXED_COMM_CAP) - pd[port].flags |= PD_FLAGS_PARTNER_USB_COMM; + pd.flags |= PD_FLAGS_PARTNER_USB_COMM; else - pd[port].flags &= ~PD_FLAGS_PARTNER_USB_COMM; + pd.flags &= ~PD_FLAGS_PARTNER_USB_COMM; #endif if (pdo & PDO_FIXED_DATA_SWAP) - pd[port].flags |= PD_FLAGS_PARTNER_DR_DATA; + pd.flags |= PD_FLAGS_PARTNER_DR_DATA; else - pd[port].flags &= ~PD_FLAGS_PARTNER_DR_DATA; + pd.flags &= ~PD_FLAGS_PARTNER_DR_DATA; #ifdef CONFIG_CHARGE_MANAGER /* @@ -1036,128 +1014,91 @@ static void pd_update_pdo_flags(int port, uint32_t pdo) { * charging white-list. */ /* - if (!(pd[port].flags & PD_FLAGS_PARTNER_DR_POWER) || - (pd[port].flags & PD_FLAGS_PARTNER_EXTPOWER) || + if (!(pd.flags & PD_FLAGS_PARTNER_DR_POWER) || + (pd.flags & PD_FLAGS_PARTNER_EXTPOWER) || charge_whitelisted) - charge_manager_update_dualrole(port, CAP_DEDICATED); + charge_manager_update_dualrole( CAP_DEDICATED); else - charge_manager_update_dualrole(port, CAP_DUALROLE); + charge_manager_update_dualrole( CAP_DUALROLE); */ #endif } -static void handle_data_request(int port, uint16_t head, uint32_t *payload) { +static void handle_data_request(uint16_t head, uint32_t *payload) { int type = PD_HEADER_TYPE(head); int cnt = PD_HEADER_CNT(head); switch (type) { #ifdef CONFIG_USB_PD_DUAL_ROLE case PD_DATA_SOURCE_CAP: - if ((pd[port].task_state == PD_STATE_SNK_DISCOVERY) - || (pd[port].task_state == PD_STATE_SNK_TRANSITION) + if ((pd.task_state == PD_STATE_SNK_DISCOVERY) + || (pd.task_state == PD_STATE_SNK_TRANSITION) #ifdef CONFIG_USB_PD_VBUS_DETECT_NONE - || (pd[port].task_state == + || (pd.task_state == PD_STATE_SNK_HARD_RESET_RECOVER) #endif - || (pd[port].task_state == PD_STATE_SNK_READY)) { + || (pd.task_state == PD_STATE_SNK_READY)) { #ifdef CONFIG_USB_PD_REV30 /* * Only adjust sink rev if source rev is higher. */ - if (PD_HEADER_REV(head) < pd[port].rev) - pd[port].rev = PD_HEADER_REV(head); + if (PD_HEADER_REV(head) < pd.rev) + pd.rev = PD_HEADER_REV(head); #endif /* Port partner is now known to be PD capable */ - pd[port].flags |= PD_FLAGS_PREVIOUS_PD_CONN; + pd.flags |= PD_FLAGS_PREVIOUS_PD_CONN; /* src cap 0 should be fixed PDO */ - pd_update_pdo_flags(port, payload[0]); + pd_update_pdo_flags(payload[0]); - pd_process_source_cap(port, cnt, payload); + pd_process_source_cap(cnt, payload); /* Source will resend source cap on failure */ - pd_send_request_msg(port, 1); + pd_send_request_msg(1); // We call the callback after we send the request // because the timing on Request seems to be sensitive // User code can take the time until PS_RDY to do stuff - pd_process_source_cap_callback(port, cnt, payload); + pd_process_source_cap_callback(cnt, payload); } break; #endif /* CONFIG_USB_PD_DUAL_ROLE */ case PD_DATA_REQUEST: - if ((pd[port].power_role == PD_ROLE_SOURCE) && (cnt == 1)) { -#ifdef CONFIG_USB_PD_REV30 - /* - * Adjust the rev level to what the sink supports. If - * they're equal, no harm done. - */ - pd[port].rev = PD_HEADER_REV(head); -#endif - if (!pd_check_requested_voltage(payload[0], port)) { - if (send_control(port, PD_CTRL_ACCEPT) < 0) - /* - * if we fail to send accept, do - * nothing and let sink timeout and - * send hard reset - */ - return; - /* explicit contract is now in place */ - pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT; -#ifdef CONFIG_USB_PD_REV30 - /* - * Start Source-coordinated collision - * avoidance - */ - if (pd[port].rev == PD_REV30 && - pd[port].power_role == PD_ROLE_SOURCE) - sink_can_xmit(port, SINK_TX_OK); -#endif -#ifdef CONFIG_USB_PD_DUAL_ROLE -#ifdef CONFIG_BBRAM - pd_set_saved_active(port, 1); -#endif -#endif - pd[port].requested_idx = RDO_POS(payload[0]); - set_state(port, PD_STATE_SRC_ACCEPTED); - return; - } - } /* the message was incorrect or cannot be satisfied */ - send_control(port, PD_CTRL_REJECT); + send_control(PD_CTRL_REJECT); /* keep last contract in place (whether implicit or explicit) */ - set_state(port, PD_STATE_SRC_READY); + set_state(PD_STATE_SRC_READY); break; case PD_DATA_BIST: /* If not in READY state, then don't start BIST */ - if (DUAL_ROLE_IF_ELSE(port, pd[port].task_state == PD_STATE_SNK_READY, - pd[port].task_state == PD_STATE_SRC_READY)) { + if (DUAL_ROLE_IF_ELSE(pd.task_state == PD_STATE_SNK_READY, + pd.task_state == PD_STATE_SRC_READY)) { /* currently only support sending bist carrier mode 2 */ if ((payload[0] >> 28) == 5) { /* bist data object mode is 2 */ - pd_transmit(port, TCPC_TX_BIST_MODE_2, 0, + pd_transmit(TCPC_TX_BIST_MODE_2, 0, NULL); /* Set to appropriate port disconnected state */ - set_state(port, - DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_DISCONNECTED, + set_state( + DUAL_ROLE_IF_ELSE(PD_STATE_SNK_DISCONNECTED, PD_STATE_SRC_DISCONNECTED)); } } break; case PD_DATA_SINK_CAP: - pd[port].flags |= PD_FLAGS_SNK_CAP_RECVD; + pd.flags |= PD_FLAGS_SNK_CAP_RECVD; /* snk cap 0 should be fixed PDO */ - pd_update_pdo_flags(port, payload[0]); - if (pd[port].task_state == PD_STATE_SRC_GET_SINK_CAP) - set_state(port, PD_STATE_SRC_READY); + pd_update_pdo_flags(payload[0]); + if (pd.task_state == PD_STATE_SRC_GET_SINK_CAP) + set_state(PD_STATE_SRC_READY); break; #ifdef CONFIG_USB_PD_REV30 case PD_DATA_BATTERY_STATUS: break; #endif case PD_DATA_VENDOR_DEF: - handle_vdm_request(port, cnt, payload); + handle_vdm_request(cnt, payload); break; default: CPRINTF("Unhandled data message type %d\n", type); @@ -1165,50 +1106,50 @@ static void handle_data_request(int port, uint16_t head, uint32_t *payload) { } #ifdef CONFIG_USB_PD_DUAL_ROLE -void pd_request_power_swap(int port) { - if (pd[port].task_state == PD_STATE_SRC_READY) - set_state(port, PD_STATE_SRC_SWAP_INIT); - else if (pd[port].task_state == PD_STATE_SNK_READY) - set_state(port, PD_STATE_SNK_SWAP_INIT); +void pd_request_power_swap() { + if (pd.task_state == PD_STATE_SRC_READY) + set_state (PD_STATE_SRC_SWAP_INIT); + else if (pd.task_state == PD_STATE_SNK_READY) + set_state (PD_STATE_SNK_SWAP_INIT); // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } #ifdef CONFIG_USBC_VCONN_SWAP -static void pd_request_vconn_swap(int port) +static void pd_request_vconn_swap() { - if (pd[port].task_state == PD_STATE_SRC_READY || - pd[port].task_state == PD_STATE_SNK_READY) - set_state(port, PD_STATE_VCONN_SWAP_SEND); + if (pd.task_state == PD_STATE_SRC_READY || + pd.task_state == PD_STATE_SNK_READY) + set_state( PD_STATE_VCONN_SWAP_SEND); // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } -void pd_try_vconn_src(int port) +void pd_try_vconn_src() { /* * If we don't currently provide vconn, and we can supply it, send * a vconn swap request. */ - if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) { - if (pd_check_vconn_swap(port)) - pd_request_vconn_swap(port); + if (!(pd.flags & PD_FLAGS_VCONN_ON)) { + if (pd_check_vconn_swap()) + pd_request_vconn_swap(); } } #endif #endif /* CONFIG_USB_PD_DUAL_ROLE */ -void pd_request_data_swap(int port) { - if (DUAL_ROLE_IF_ELSE(port, pd[port].task_state == PD_STATE_SNK_READY, - pd[port].task_state == PD_STATE_SRC_READY)) - set_state(port, PD_STATE_DR_SWAP); +void pd_request_data_swap() { + if (DUAL_ROLE_IF_ELSE(pd.task_state == PD_STATE_SNK_READY, + pd.task_state == PD_STATE_SRC_READY)) + set_state(PD_STATE_DR_SWAP); // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } -static void pd_set_data_role(int port, int role) { - pd[port].data_role = role; - pd_execute_data_swap(port, role); +static void pd_set_data_role(int role) { + pd.data_role = role; + pd_execute_data_swap(role); #ifdef CONFIG_USBC_SS_MUX #ifdef CONFIG_USBC_SS_MUX_DFP_ONLY @@ -1217,25 +1158,25 @@ static void pd_set_data_role(int port, int role) { * If new data role is UFP, then disconnect the SS mux. */ if (role == PD_ROLE_DFP) - usb_mux_set(port, TYPEC_MUX_USB, USB_SWITCH_CONNECT, - pd[port].polarity); + usb_mux_set( TYPEC_MUX_USB, USB_SWITCH_CONNECT, + pd.polarity); else - usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, - pd[port].polarity); + usb_mux_set( TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, + pd.polarity); #else - usb_mux_set(port, TYPEC_MUX_USB, USB_SWITCH_CONNECT, - pd[port].polarity); + usb_mux_set( TYPEC_MUX_USB, USB_SWITCH_CONNECT, + pd.polarity); #endif #endif - pd_update_roles(port); + pd_update_roles(); } -static void pd_dr_swap(int port) { - pd_set_data_role(port, !pd[port].data_role); - pd[port].flags |= PD_FLAGS_CHECK_IDENTITY; +static void pd_dr_swap() { + pd_set_data_role(!pd.data_role); + pd.flags |= PD_FLAGS_CHECK_IDENTITY; } -static void handle_ctrl_request(int port, uint16_t head, uint32_t *payload) { +static void handle_ctrl_request(uint16_t head, uint32_t *payload) { int type = PD_HEADER_TYPE(head); int res; @@ -1247,21 +1188,21 @@ static void handle_ctrl_request(int port, uint16_t head, uint32_t *payload) { /* Nothing else to do */ break; case PD_CTRL_GET_SOURCE_CAP: - res = send_source_cap(port); - if ((res >= 0) && (pd[port].task_state == PD_STATE_SRC_DISCOVERY)) - set_state(port, PD_STATE_SRC_NEGOCIATE); + res = send_source_cap(); + if ((res >= 0) && (pd.task_state == PD_STATE_SRC_DISCOVERY)) + set_state(PD_STATE_SRC_NEGOCIATE); break; case PD_CTRL_GET_SINK_CAP: #ifdef CONFIG_USB_PD_DUAL_ROLE - send_sink_cap(port); + send_sink_cap(); #else - send_control(port, REFUSE(pd[port].rev)); + send_control(REFUSE(pd.rev)); #endif break; #ifdef CONFIG_USB_PD_DUAL_ROLE case PD_CTRL_GOTO_MIN: #ifdef CONFIG_USB_PD_GIVE_BACK - if (pd[port].task_state == PD_STATE_SNK_READY) { + if (pd.task_state == PD_STATE_SNK_READY) { /* * Reduce power consumption now! * @@ -1269,63 +1210,63 @@ static void handle_ctrl_request(int port, uint16_t head, uint32_t *payload) { * by sending a new source cap message at a * later time. */ - pd_snk_give_back(port, &pd[port].curr_limit, - &pd[port].supply_voltage); - set_state(port, PD_STATE_SNK_TRANSITION); + pd_snk_give_back( &pd.curr_limit, + &pd.supply_voltage); + set_state( PD_STATE_SNK_TRANSITION); } #endif break; case PD_CTRL_PS_RDY: - if (pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE) { - set_state(port, PD_STATE_SNK_SWAP_STANDBY); - } else if (pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY) { + if (pd.task_state == PD_STATE_SNK_SWAP_SRC_DISABLE) { + set_state (PD_STATE_SNK_SWAP_STANDBY); + } else if (pd.task_state == PD_STATE_SRC_SWAP_STANDBY) { /* reset message ID and swap roles */ - pd[port].msg_id = 0; - pd[port].power_role = PD_ROLE_SINK; - pd_update_roles(port); - set_state(port, PD_STATE_SNK_DISCOVERY); + pd.msg_id = 0; + pd.power_role = PD_ROLE_SINK; + pd_update_roles(); + set_state (PD_STATE_SNK_DISCOVERY); #ifdef CONFIG_USBC_VCONN_SWAP - } else if (pd[port].task_state == PD_STATE_VCONN_SWAP_INIT) { + } else if (pd.task_state == PD_STATE_VCONN_SWAP_INIT) { /* * If VCONN is on, then this PS_RDY tells us it's * ok to turn VCONN off */ - if (pd[port].flags & PD_FLAGS_VCONN_ON) - set_state(port, PD_STATE_VCONN_SWAP_READY); + if (pd.flags & PD_FLAGS_VCONN_ON) + set_state( PD_STATE_VCONN_SWAP_READY); #endif - } else if (pd[port].task_state == PD_STATE_SNK_DISCOVERY) { + } else if (pd.task_state == PD_STATE_SNK_DISCOVERY) { /* Don't know what power source is ready. Reset. */ - set_state(port, PD_STATE_HARD_RESET_SEND); - } else if (pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY) { + set_state(PD_STATE_HARD_RESET_SEND); + } else if (pd.task_state == PD_STATE_SNK_SWAP_STANDBY) { /* Do nothing, assume this is a redundant PD_RDY */ - } else if (pd[port].power_role == PD_ROLE_SINK) { - set_state(port, PD_STATE_SNK_READY); - pd_set_input_current_limit(port, pd[port].curr_limit, - pd[port].supply_voltage); + } else if (pd.power_role == PD_ROLE_SINK) { + set_state (PD_STATE_SNK_READY); + pd_set_input_current_limit(pd.curr_limit, + pd.supply_voltage); #ifdef CONFIG_CHARGE_MANAGER /* Set ceiling based on what's negotiated */ - //charge_manager_set_ceil(port, + //charge_manager_set_ceil( // CEIL_REQUESTOR_PD, - // pd[port].curr_limit); + // pd.curr_limit); #endif } break; #endif case PD_CTRL_REJECT: case PD_CTRL_WAIT: - if (pd[port].task_state == PD_STATE_DR_SWAP) - set_state(port, READY_RETURN_STATE(port)); + if (pd.task_state == PD_STATE_DR_SWAP) + set_state(READY_RETURN_STATE()); #ifdef CONFIG_USBC_VCONN_SWAP - else if (pd[port].task_state == PD_STATE_VCONN_SWAP_SEND) - set_state(port, READY_RETURN_STATE(port)); + else if (pd.task_state == PD_STATE_VCONN_SWAP_SEND) + set_state( READY_RETURN_STATE()); #endif #ifdef CONFIG_USB_PD_DUAL_ROLE - else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT) - set_state(port, PD_STATE_SRC_READY); - else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT) - set_state(port, PD_STATE_SNK_READY); - else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) { + else if (pd.task_state == PD_STATE_SRC_SWAP_INIT) + set_state(PD_STATE_SRC_READY); + else if (pd.task_state == PD_STATE_SNK_SWAP_INIT) + set_state (PD_STATE_SNK_READY); + else if (pd.task_state == PD_STATE_SNK_REQUESTED) { /* * Explicit Contract in place * @@ -1341,158 +1282,158 @@ static void handle_ctrl_request(int port, uint16_t head, uint32_t *payload) { * On reception of a WAIT or REJECT message, * transition to PD_STATE_SNK_DISCOVERY */ - if (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT) { + if (pd.flags & PD_FLAGS_EXPLICIT_CONTRACT) { /* We have an explicit contract */ if (type == PD_CTRL_WAIT) { /* * Trigger a new power request when * we enter PD_STATE_SNK_READY */ - pd[port].new_power_request = 1; + pd.new_power_request = 1; /* * After the request is triggered, * make sure the request is sent. */ - pd[port].prev_request_mv = 0; + pd.prev_request_mv = 0; /* * Transition to PD_STATE_SNK_READY * after PD_T_SINK_REQUEST ms. */ - set_state_timeout(port, get_time().val + + set_state_timeout(get_time().val + PD_T_SINK_REQUEST, PD_STATE_SNK_READY); } else { /* The request was rejected */ - set_state(port, PD_STATE_SNK_READY); + set_state(PD_STATE_SNK_READY); } } else { /* No explicit contract */ - set_state(port, PD_STATE_SNK_DISCOVERY); + set_state (PD_STATE_SNK_DISCOVERY); } } #endif break; case PD_CTRL_ACCEPT: - if (pd[port].task_state == PD_STATE_SOFT_RESET) { + if (pd.task_state == PD_STATE_SOFT_RESET) { /* * For the case that we sent soft reset in SNK_DISCOVERY * on startup due to VBUS never low, clear the flag. */ - pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW; - execute_soft_reset(port); - } else if (pd[port].task_state == PD_STATE_DR_SWAP) { + pd.flags &= ~PD_FLAGS_VBUS_NEVER_LOW; + execute_soft_reset(); + } else if (pd.task_state == PD_STATE_DR_SWAP) { /* switch data role */ - pd_dr_swap(port); - set_state(port, READY_RETURN_STATE(port)); + pd_dr_swap(); + set_state(READY_RETURN_STATE()); #ifdef CONFIG_USB_PD_DUAL_ROLE #ifdef CONFIG_USBC_VCONN_SWAP - } else if (pd[port].task_state == PD_STATE_VCONN_SWAP_SEND) { + } else if (pd.task_state == PD_STATE_VCONN_SWAP_SEND) { /* switch vconn */ - set_state(port, PD_STATE_VCONN_SWAP_INIT); + set_state( PD_STATE_VCONN_SWAP_INIT); #endif - } else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT) { + } else if (pd.task_state == PD_STATE_SRC_SWAP_INIT) { /* explicit contract goes away for power swap */ - pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT; - set_state(port, PD_STATE_SRC_SWAP_SNK_DISABLE); - } else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT) { + pd.flags &= ~PD_FLAGS_EXPLICIT_CONTRACT; + set_state (PD_STATE_SRC_SWAP_SNK_DISABLE); + } else if (pd.task_state == PD_STATE_SNK_SWAP_INIT) { /* explicit contract goes away for power swap */ - pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT; - set_state(port, PD_STATE_SNK_SWAP_SNK_DISABLE); - } else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) { + pd.flags &= ~PD_FLAGS_EXPLICIT_CONTRACT; + set_state (PD_STATE_SNK_SWAP_SNK_DISABLE); + } else if (pd.task_state == PD_STATE_SNK_REQUESTED) { /* explicit contract is now in place */ - pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT; + pd.flags |= PD_FLAGS_EXPLICIT_CONTRACT; #ifdef CONFIG_BBRAM - pd_set_saved_active(port, 1); + pd_set_saved_active( 1); #endif - set_state(port, PD_STATE_SNK_TRANSITION); + set_state (PD_STATE_SNK_TRANSITION); #endif } break; case PD_CTRL_SOFT_RESET: - execute_soft_reset(port); + execute_soft_reset(); /* We are done, acknowledge with an Accept packet */ - send_control(port, PD_CTRL_ACCEPT); + send_control(PD_CTRL_ACCEPT); break; case PD_CTRL_PR_SWAP: #ifdef CONFIG_USB_PD_DUAL_ROLE - if (pd_check_power_swap(port)) { - send_control(port, PD_CTRL_ACCEPT); + if (pd_check_power_swap()) { + send_control(PD_CTRL_ACCEPT); /* * Clear flag for checking power role to avoid * immediately requesting another swap. */ - pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE; - set_state(port, - DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_SWAP_SNK_DISABLE, + pd.flags &= ~PD_FLAGS_CHECK_PR_ROLE; + set_state( + DUAL_ROLE_IF_ELSE(PD_STATE_SNK_SWAP_SNK_DISABLE, PD_STATE_SRC_SWAP_SNK_DISABLE)); } else { - send_control(port, REFUSE(pd[port].rev)); + send_control(REFUSE(pd.rev)); } #else - send_control(port, REFUSE(pd[port].rev)); + send_control(REFUSE(pd.rev)); #endif break; case PD_CTRL_DR_SWAP: - if (pd_check_data_swap(port, pd[port].data_role)) { + if (pd_check_data_swap(pd.data_role)) { /* * Accept switch and perform data swap. Clear * flag for checking data role to avoid * immediately requesting another swap. */ - pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE; - if (send_control(port, PD_CTRL_ACCEPT) >= 0) - pd_dr_swap(port); + pd.flags &= ~PD_FLAGS_CHECK_DR_ROLE; + if (send_control(PD_CTRL_ACCEPT) >= 0) + pd_dr_swap(); } else { - send_control(port, REFUSE(pd[port].rev)); + send_control(REFUSE(pd.rev)); } break; case PD_CTRL_VCONN_SWAP: #ifdef CONFIG_USBC_VCONN_SWAP - if (pd[port].task_state == PD_STATE_SRC_READY || - pd[port].task_state == PD_STATE_SNK_READY) { - if (pd_check_vconn_swap(port)) { - if (send_control(port, PD_CTRL_ACCEPT) > 0) - set_state(port, + if (pd.task_state == PD_STATE_SRC_READY || + pd.task_state == PD_STATE_SNK_READY) { + if (pd_check_vconn_swap()) { + if (send_control( PD_CTRL_ACCEPT) > 0) + set_state( PD_STATE_VCONN_SWAP_INIT); } else { - send_control(port, REFUSE(pd[port].rev)); + send_control( REFUSE(pd.rev)); } } #else - send_control(port, REFUSE(pd[port].rev)); + send_control(REFUSE(pd.rev)); #endif break; default: #ifdef CONFIG_USB_PD_REV30 - send_control(port, PD_CTRL_NOT_SUPPORTED); + send_control( PD_CTRL_NOT_SUPPORTED); #endif CPRINTF("Unhandled ctrl message type %d\n", type); } } #ifdef CONFIG_USB_PD_REV30 -static void handle_ext_request(int port, uint16_t head, uint32_t *payload) +static void handle_ext_request( uint16_t head, uint32_t *payload) { int type = PD_HEADER_TYPE(head); switch (type) { case PD_EXT_GET_BATTERY_CAP: - send_battery_cap(port, payload); + send_battery_cap( payload); break; case PD_EXT_GET_BATTERY_STATUS: - send_battery_status(port, payload); + send_battery_status( payload); break; case PD_EXT_BATTERY_CAP: break; default: - send_control(port, PD_CTRL_NOT_SUPPORTED); + send_control( PD_CTRL_NOT_SUPPORTED); } } #endif -static void handle_request(int port, uint16_t head, uint32_t *payload) { +static void handle_request(uint16_t head, uint32_t *payload) { int cnt = PD_HEADER_CNT(head); int p; @@ -1501,59 +1442,58 @@ static void handle_request(int port, uint16_t head, uint32_t *payload) { || debug_level >= 3) { CPRINTF("RECV %04x/%d ", head, cnt); for (p = 0; p < cnt; p++) - CPRINTF("[%d]%08x ", p, payload[p]); CPRINTF("\n"); + CPRINTF("[%d]%08x ", p, payload[p]);CPRINTF("\n"); } /* * If we are in disconnected state, we shouldn't get a request. * Ignore it if we get one. */ - if (!pd_is_connected(port)) + if (!pd_is_connected()) return; #ifdef CONFIG_USB_PD_REV30 /* Check if this is an extended chunked data message. */ - if (pd[port].rev == PD_REV30 && PD_HEADER_EXT(head)) { - handle_ext_request(port, head, payload); + if (pd.rev == PD_REV30 && PD_HEADER_EXT(head)) { + handle_ext_request( head, payload); return; } #endif if (cnt) - handle_data_request(port, head, payload); + handle_data_request(head, payload); else - handle_ctrl_request(port, head, payload); + handle_ctrl_request(head, payload); } -void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data, - int count) { +void pd_send_vdm(uint32_t vid, int cmd, const uint32_t *data, int count) { if (count > VDO_MAX_SIZE - 1) { CPRINTF("VDM over max size\n"); return; } /* set VDM header with VID & CMD */ - pd[port].vdo_data[0] = + pd.vdo_data[0] = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ? 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), cmd); #ifdef CONFIG_USB_PD_REV30 - pd[port].vdo_data[0] |= VDO_SVDM_VERS(vdo_ver[pd[port].rev]); + pd.vdo_data[0] |= VDO_SVDM_VERS(vdo_ver[pd.rev]); #endif - queue_vdm(port, pd[port].vdo_data, data, count); + queue_vdm(pd.vdo_data, data, count); // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } -static inline int pdo_busy(int port) { +static inline int pdo_busy() { /* * Note, main PDO state machine (pd_task) uses READY state exclusively * to denote port partners have successfully negociated a contract. All * other protocol actions force state transitions. */ - int rv = (pd[port].task_state != PD_STATE_SRC_READY); + int rv = (pd.task_state != PD_STATE_SRC_READY); #ifdef CONFIG_USB_PD_DUAL_ROLE - rv &= (pd[port].task_state != PD_STATE_SNK_READY); + rv &= (pd.task_state != PD_STATE_SNK_READY); #endif return rv; } @@ -1583,15 +1523,15 @@ static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr) { return timeout; } -static void pd_vdm_send_state_machine(int port) { +static void pd_vdm_send_state_machine() { int res; uint16_t header; - switch (pd[port].vdm_state) { + switch (pd.vdm_state) { case VDM_STATE_READY: /* Only transmit VDM if connected. */ - if (!pd_is_connected(port)) { - pd[port].vdm_state = VDM_STATE_ERR_BUSY; + if (!pd_is_connected()) { + pd.vdm_state = VDM_STATE_ERR_BUSY; break; } @@ -1599,35 +1539,33 @@ static void pd_vdm_send_state_machine(int port) { * if there's traffic or we're not in PDO ready state don't send * a VDM. */ - if (pdo_busy(port)) + if (pdo_busy()) break; /* Prepare and send VDM */ - header = PD_HEADER(PD_DATA_VENDOR_DEF, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, (int )pd[port].vdo_count, - pd_get_rev(port), 0); - res = pd_transmit(port, TCPC_TX_SOP, header, pd[port].vdo_data); + header = PD_HEADER(PD_DATA_VENDOR_DEF, pd.power_role, pd.data_role, + pd.msg_id, (int )pd.vdo_count, pd_get_rev(), 0); + res = pd_transmit(TCPC_TX_SOP, header, pd.vdo_data); if (res < 0) { - pd[port].vdm_state = VDM_STATE_ERR_SEND; + pd.vdm_state = VDM_STATE_ERR_SEND; } else { - pd[port].vdm_state = VDM_STATE_BUSY; - pd[port].vdm_timeout.val = get_time().val - + vdm_get_ready_timeout(pd[port].vdo_data[0]); + pd.vdm_state = VDM_STATE_BUSY; + pd.vdm_timeout.val = get_time().val + + vdm_get_ready_timeout(pd.vdo_data[0]); } break; case VDM_STATE_WAIT_RSP_BUSY: /* wait and then initiate request again */ - if (get_time().val > pd[port].vdm_timeout.val) { - pd[port].vdo_data[0] = pd[port].vdo_retry; - pd[port].vdo_count = 1; - pd[port].vdm_state = VDM_STATE_READY; + if (get_time().val > pd.vdm_timeout.val) { + pd.vdo_data[0] = pd.vdo_retry; + pd.vdo_count = 1; + pd.vdm_state = VDM_STATE_READY; } break; case VDM_STATE_BUSY: /* Wait for VDM response or timeout */ - if (pd[port].vdm_timeout.val - && (get_time().val > pd[port].vdm_timeout.val)) { - pd[port].vdm_state = VDM_STATE_ERR_TMOUT; + if (pd.vdm_timeout.val && (get_time().val > pd.vdm_timeout.val)) { + pd.vdm_state = VDM_STATE_ERR_TMOUT; } break; default: @@ -1649,22 +1587,22 @@ static inline void pd_dev_dump_info(uint16_t dev_id, uint8_t *hash) } #endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */ -int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash, +int pd_dev_store_rw_hash(uint16_t dev_id, uint32_t *rw_hash, uint32_t current_image) { #ifdef CONFIG_COMMON_RUNTIME int i; #endif #ifdef CONFIG_USB_PD_CHROMEOS - pd[port].dev_id = dev_id; - memcpy(pd[port].dev_rw_hash, rw_hash, PD_RW_HASH_SIZE); + pd.dev_id = dev_id; + memcpy(pd.dev_rw_hash, rw_hash, PD_RW_HASH_SIZE); #endif #ifdef CONFIG_CMD_PD_DEV_DUMP_INFO if (debug_level >= 2) pd_dev_dump_info(dev_id, (uint8_t *)rw_hash); #endif #ifdef CONFIG_USB_PD_CHROMEOS - pd[port].current_image = current_image; + pd.current_image = current_image; #endif #ifdef CONFIG_COMMON_RUNTIME @@ -1738,62 +1676,62 @@ void pd_set_dual_role(enum pd_dual_role_states state) { ; } -void pd_update_dual_role_config(int port) { +void pd_update_dual_role_config() { /* * Change to sink if port is currently a source AND (new DRP * state is force sink OR new DRP state is either toggle off * or debug accessory toggle only and we are in the source * disconnected state). */ - if (pd[port].power_role == PD_ROLE_SOURCE - && ((drp_state == PD_DRP_FORCE_SINK && !pd_ts_dts_plugged(port)) + if (pd.power_role == PD_ROLE_SOURCE + && ((drp_state == PD_DRP_FORCE_SINK && !pd_ts_dts_plugged()) || (drp_state == PD_DRP_TOGGLE_OFF - && pd[port].task_state == PD_STATE_SRC_DISCONNECTED))) { - pd[port].power_role = PD_ROLE_SINK; - set_state(port, PD_STATE_SNK_DISCONNECTED); - tcpm_set_cc(port, TYPEC_CC_RD); + && pd.task_state == PD_STATE_SRC_DISCONNECTED))) { + pd.power_role = PD_ROLE_SINK; + set_state (PD_STATE_SNK_DISCONNECTED); + tcpm_set_cc(TYPEC_CC_RD); /* Make sure we're not sourcing VBUS. */ - pd_power_supply_reset(port); + pd_power_supply_reset(); } /* * Change to source if port is currently a sink and the * new DRP state is force source. */ - if (pd[port].power_role == PD_ROLE_SINK + if (pd.power_role == PD_ROLE_SINK && drp_state == PD_DRP_FORCE_SOURCE) { - pd[port].power_role = PD_ROLE_SOURCE; - set_state(port, PD_STATE_SRC_DISCONNECTED); - tcpm_set_cc(port, TYPEC_CC_RP); + pd.power_role = PD_ROLE_SOURCE; + set_state(PD_STATE_SRC_DISCONNECTED); + tcpm_set_cc(TYPEC_CC_RP); } #if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \ defined(CONFIG_USB_PD_TCPC_LOW_POWER) /* When switching drp mode, make sure tcpc is out of standby mode */ - tcpm_set_drp_toggle(port, 0); + tcpm_set_drp_toggle( 0); #endif } -int pd_get_role(int port) { - return pd[port].power_role; +int pd_get_role() { + return pd.power_role; } -static int pd_is_power_swapping(int port) { +static int pd_is_power_swapping() { /* return true if in the act of swapping power roles */ - return pd[port].task_state == PD_STATE_SNK_SWAP_SNK_DISABLE - || pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE - || pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY - || pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE - || pd[port].task_state == PD_STATE_SRC_SWAP_SNK_DISABLE - || pd[port].task_state == PD_STATE_SRC_SWAP_SRC_DISABLE - || pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY; + return pd.task_state == PD_STATE_SNK_SWAP_SNK_DISABLE + || pd.task_state == PD_STATE_SNK_SWAP_SRC_DISABLE + || pd.task_state == PD_STATE_SNK_SWAP_STANDBY + || pd.task_state == PD_STATE_SNK_SWAP_COMPLETE + || pd.task_state == PD_STATE_SRC_SWAP_SNK_DISABLE + || pd.task_state == PD_STATE_SRC_SWAP_SRC_DISABLE + || pd.task_state == PD_STATE_SRC_SWAP_STANDBY; } /* * Provide Rp to ensure the partner port is in a known state (eg. not * PD negotiated, not sourcing 20V). */ -static void pd_partner_port_reset(int port) { +static void pd_partner_port_reset() { uint64_t timeout; #ifdef CONFIG_BBRAM @@ -1802,61 +1740,61 @@ static void pd_partner_port_reset(int port) { * active, and we didn't just lose power, make sure we * don't boot into RO with a pre-existing power contract. */ - if (!pd_get_saved_active(port) || + if (!pd_get_saved_active() || system_get_image_copy() != SYSTEM_IMAGE_RO || system_get_reset_flags() & (RESET_FLAG_BROWNOUT | RESET_FLAG_POWER_ON)) return; #endif // CONFIG_BBRAM /* Provide Rp for 100 msec. or until we no longer have VBUS. */ - tcpm_set_cc(port, TYPEC_CC_RP); + tcpm_set_cc(TYPEC_CC_RP); timeout = get_time().val + 100 * MSEC; - while (get_time().val < timeout && pd_is_vbus_present(port)) + while (get_time().val < timeout && pd_is_vbus_present()) msleep(10); #ifdef CONFIG_BBRAM - pd_set_saved_active(port, 0); + pd_set_saved_active( 0); #endif } #endif /* CONFIG_USB_PD_DUAL_ROLE */ -int pd_get_polarity(int port) { - return pd[port].polarity; +int pd_get_polarity() { + return pd.polarity; } -int pd_get_partner_data_swap_capable(int port) { +int pd_get_partner_data_swap_capable() { /* return data swap capable status of port partner */ - return pd[port].flags & PD_FLAGS_PARTNER_DR_DATA; + return pd.flags & PD_FLAGS_PARTNER_DR_DATA; } #ifdef CONFIG_COMMON_RUNTIME -void pd_comm_enable(int port, int enable) +void pd_comm_enable( int enable) { /* We don't check port >= CONFIG_USB_PD_PORT_COUNT deliberately */ pd_comm_enabled[port] = enable; /* If type-C connection, then update the TCPC RX enable */ - if (pd_is_connected(port)) - tcpm_set_rx_enable(port, enable); + if (pd_is_connected()) + tcpm_set_rx_enable( enable); #ifdef CONFIG_USB_PD_DUAL_ROLE /* * If communications are enabled, start hard reset timer for * any port in PD_SNK_DISCOVERY. */ - if (enable && pd[port].task_state == PD_STATE_SNK_DISCOVERY) - set_state_timeout(port, + if (enable && pd.task_state == PD_STATE_SNK_DISCOVERY) + set_state_timeout( get_time().val + PD_T_SINK_WAIT_CAP, PD_STATE_HARD_RESET_SEND); #endif } #endif -void pd_ping_enable(int port, int enable) { +void pd_ping_enable(int enable) { if (enable) - pd[port].flags |= PD_FLAGS_PING_ENABLED; + pd.flags |= PD_FLAGS_PING_ENABLED; else - pd[port].flags &= ~PD_FLAGS_PING_ENABLED; + pd.flags &= ~PD_FLAGS_PING_ENABLED; } /** @@ -1917,10 +1855,10 @@ static typec_current_t get_typec_current_limit(int polarity, int cc1, int cc2) { /** * Signal power request to indicate a charger update that affects the port. */ -void pd_set_new_power_request(int port) { - pd[port].new_power_request = 1; +void pd_set_new_power_request() { +// pd.new_power_request = 1; // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } #endif /* CONFIG_CHARGE_MANAGER */ @@ -1972,22 +1910,22 @@ static void pd_init_tasks(void) #endif /* CONFIG_COMMON_RUNTIME */ #ifndef CONFIG_USB_PD_TCPC -static int pd_restart_tcpc(int port) { +static int pd_restart_tcpc() { if (board_set_tcpc_power_mode) { /* force chip reset */ - board_set_tcpc_power_mode(port, 0); + board_set_tcpc_power_mode(0); } - return tcpm_init(port); + return tcpm_init(); } #endif -void pd_init(int port) { +void pd_init() { #ifdef CONFIG_COMMON_RUNTIME pd_init_tasks(); #endif /* Ensure the power supply is in the default state */ - pd_power_supply_reset(port); + pd_power_supply_reset(); #ifdef CONFIG_USB_PD_TCPC_BOARD_INIT /* Board specific TCPC init */ @@ -1995,18 +1933,18 @@ void pd_init(int port) { #endif /* Initialize TCPM driver and wait for TCPC to be ready */ - res = tcpm_init(port); + res = tcpm_init(); #ifdef CONFIG_USB_PD_DUAL_ROLE - //pd_partner_port_reset(port); + //pd_partner_port_reset(); #endif CPRINTS("TCPC p%d init %s", port, res ? "failed" : "ready"); - this_state = res ? PD_STATE_SUSPENDED : PD_DEFAULT_STATE(port); + this_state = res ? PD_STATE_SUSPENDED : PD_DEFAULT_STATE(); #ifndef CONFIG_USB_PD_TCPC if (!res) { struct ec_response_pd_chip_info *info; - tcpm_get_chip_info(port, 0, &info); + tcpm_get_chip_info(0, &info); CPRINTS("TCPC p%d VID:0x%x PID:0x%x DID:0x%x FWV:0x%lx", port, info->vendor_id, info->product_id, info->device_id, info->fw_version_number); @@ -2015,8 +1953,8 @@ void pd_init(int port) { #ifdef CONFIG_USB_PD_REV30 /* Set Revision to highest */ - pd[port].rev = PD_REV30; - pd_ca_reset(port); + pd.rev = PD_REV30; + pd_ca_reset(); #endif #ifdef CONFIG_USB_PD_DUAL_ROLE @@ -2025,60 +1963,59 @@ void pd_init(int port) { * present. This flag is used to maintain a PD connection after a * reset by sending a soft reset. */ - //pd[port].flags = pd_is_vbus_present(port) ? PD_FLAGS_VBUS_NEVER_LOW : 0; - pd[port].flags = 0; + //pd.flags = pd_is_vbus_present() ? PD_FLAGS_VBUS_NEVER_LOW : 0; + pd.flags = 0; #endif /* Disable TCPC RX until connection is established */ - tcpm_set_rx_enable(port, 0); + tcpm_set_rx_enable(0); #ifdef CONFIG_USBC_SS_MUX /* Initialize USB mux to its default state */ - usb_mux_init(port); + usb_mux_init(); #endif /* Initialize PD protocol state variables for each port. */ - pd[port].power_role = PD_ROLE_DEFAULT(port); - pd[port].vdm_state = VDM_STATE_DONE; - set_state(port, this_state); + pd.power_role = PD_ROLE_DEFAULT(); + pd.vdm_state = VDM_STATE_DONE; + set_state(this_state); #ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - ASSERT(PD_ROLE_DEFAULT(port) == PD_ROLE_SINK); - tcpm_select_rp_value(port, CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT); + ASSERT(PD_ROLE_DEFAULT() == PD_ROLE_SINK); + tcpm_select_rp_value( CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT); #else - tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP); + tcpm_select_rp_value( CONFIG_USB_PD_PULLUP); #endif - tcpm_set_cc(port, - PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE ? - TYPEC_CC_RP : TYPEC_CC_RD); + tcpm_set_cc( + PD_ROLE_DEFAULT() == PD_ROLE_SOURCE ? TYPEC_CC_RP : TYPEC_CC_RD); #ifdef CONFIG_USB_PD_ALT_MODE_DFP /* Initialize PD Policy engine */ - pd_dfp_pe_init(port); + pd_dfp_pe_init(); #endif #ifdef CONFIG_CHARGE_MANAGER /* Initialize PD and type-C supplier current limits to 0 */ - pd_set_input_current_limit(port, 0, 0); - //typec_set_input_current_limit(port, 0, 0); - //charge_manager_update_dualrole(port, CAP_UNKNOWN); + pd_set_input_current_limit(0, 0); + //typec_set_input_current_limit( 0, 0); + //charge_manager_update_dualrole( CAP_UNKNOWN); #endif } -void pd_run_state_machine(int port) { +void pd_run_state_machine() { #ifdef CONFIG_USB_PD_REV30 /* send any pending messages */ - pd_ca_send_pending(port); + pd_ca_send_pending(); #endif /* process VDM messages last */ - pd_vdm_send_state_machine(port); + pd_vdm_send_state_machine(); /* Verify board specific health status : current, voltages... */ res = pd_board_checks(); if (res != EC_SUCCESS) { /* cut the power */ - pd_execute_hard_reset(port); + pd_execute_hard_reset(); /* notify the other side of the issue */ - pd_transmit(port, TCPC_TX_HARD_RESET, 0, NULL); + pd_transmit(TCPC_TX_HARD_RESET, 0, NULL); } /* wait for next event/packet or timeout expiration */ @@ -2086,7 +2023,7 @@ void pd_run_state_machine(int port) { //evt = task_wait_event(timeout); #ifdef CONFIG_USB_PD_DUAL_ROLE if (evt & PD_EVENT_UPDATE_DUAL_ROLE) - pd_update_dual_role_config(port); + pd_update_dual_role_config(); #endif #ifdef CONFIG_USB_PD_TCPC @@ -2094,21 +2031,21 @@ void pd_run_state_machine(int port) { * run port controller task to check CC and/or read incoming * messages */ - tcpc_run(port, evt); + tcpc_run( evt); #else /* if TCPC has reset, then need to initialize it again */ if (evt & PD_EVENT_TCPC_RESET) { CPRINTS("TCPC p%d reset!", port); - if (tcpm_init(port) != EC_SUCCESS) + if (tcpm_init() != EC_SUCCESS) CPRINTS("TCPC p%d init failed", port); #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE } if ((evt & PD_EVENT_TCPC_RESET) && - (pd[port].task_state != PD_STATE_DRP_AUTO_TOGGLE)) { + (pd.task_state != PD_STATE_DRP_AUTO_TOGGLE)) { #endif /* Ensure CC termination is default */ - tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == + tcpm_set_cc( PD_ROLE_DEFAULT() == PD_ROLE_SOURCE ? TYPEC_CC_RP : TYPEC_CC_RD); /* @@ -2118,23 +2055,23 @@ void pd_run_state_machine(int port) { * Otherwise, go to the default disconnected state * and force renegotiation. */ - if (pd[port].vdm_state == VDM_STATE_DONE + if (pd.vdm_state == VDM_STATE_DONE && ( #ifdef CONFIG_USB_PD_DUAL_ROLE - (PD_ROLE_DEFAULT(port) == PD_ROLE_SINK - && pd[port].task_state == PD_STATE_SNK_READY) + (PD_ROLE_DEFAULT() == PD_ROLE_SINK + && pd.task_state == PD_STATE_SNK_READY) || #endif - (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE - && pd[port].task_state == PD_STATE_SRC_READY))) { - tcpm_set_polarity(port, pd[port].polarity); - tcpm_set_msg_header(port, pd[port].power_role, pd[port].data_role); - tcpm_set_rx_enable(port, 1); + (PD_ROLE_DEFAULT() == PD_ROLE_SOURCE + && pd.task_state == PD_STATE_SRC_READY))) { + tcpm_set_polarity(pd.polarity); + tcpm_set_msg_header(pd.power_role, pd.data_role); + tcpm_set_rx_enable(1); } else { /* Ensure state variables are at default */ - pd[port].power_role = PD_ROLE_DEFAULT(port); - pd[port].vdm_state = VDM_STATE_DONE; - set_state(port, PD_DEFAULT_STATE(port)); + pd.power_role = PD_ROLE_DEFAULT(); + pd.vdm_state = VDM_STATE_DONE; + set_state(PD_DEFAULT_STATE()); } } #endif @@ -2142,15 +2079,15 @@ void pd_run_state_machine(int port) { /* process any potential incoming message */ incoming_packet = evt & PD_EVENT_RX; //if (incoming_packet) { - if (!tcpm_get_message(port, payload, &head)) - handle_request(port, head, payload); + if (!tcpm_get_message(payload, &head)) + handle_request(head, payload); //} - if (pd[port].req_suspend_state) - set_state(port, PD_STATE_SUSPENDED); + if (pd.req_suspend_state) + set_state(PD_STATE_SUSPENDED); /* if nothing to do, verify the state of the world in 500ms */ - this_state = pd[port].task_state; + this_state = pd.task_state; timeout = 500 * MSEC; switch (this_state) { case PD_STATE_DISABLED: @@ -2158,18 +2095,18 @@ void pd_run_state_machine(int port) { break; case PD_STATE_SRC_DISCONNECTED: timeout = 10 * MSEC; - tcpm_get_cc(port, &cc1, &cc2); + tcpm_get_cc(&cc1, &cc2); #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE /* * Attempt TCPC auto DRP toggle if it is * not already auto toggling and not try.src */ if (auto_toggle_supported && - !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) && - !(pd[port].flags & PD_FLAGS_TRY_SRC) && + !(pd.flags & PD_FLAGS_TCPC_DRP_TOGGLE) && + !(pd.flags & PD_FLAGS_TRY_SRC) && (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN)) { - set_state(port, PD_STATE_DRP_AUTO_TOGGLE); + set_state( PD_STATE_DRP_AUTO_TOGGLE); timeout = 2*MSEC; break; } @@ -2180,11 +2117,11 @@ void pd_run_state_machine(int port) { || (cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_RA)) { #ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP /* Enable VBUS */ - if (pd_set_power_supply_ready(port)) + if (pd_set_power_supply_ready()) break; #endif - pd[port].cc_state = PD_CC_NONE; - set_state(port, PD_STATE_SRC_DISCONNECTED_DEBOUNCE); + pd.cc_state = PD_CC_NONE; + set_state(PD_STATE_SRC_DISCONNECTED_DEBOUNCE); } #if defined(CONFIG_USB_PD_DUAL_ROLE) /* @@ -2195,17 +2132,17 @@ void pd_run_state_machine(int port) { * If Try.SRC state is not active, then this block * handles the normal DRP toggle from SRC->SNK */ - else if ((pd[port].flags & PD_FLAGS_TRY_SRC - && get_time().val >= pd[port].try_src_marker) - || (!(pd[port].flags & PD_FLAGS_TRY_SRC) + else if ((pd.flags & PD_FLAGS_TRY_SRC + && get_time().val >= pd.try_src_marker) + || (!(pd.flags & PD_FLAGS_TRY_SRC) && drp_state != PD_DRP_FORCE_SOURCE && drp_state != PD_DRP_FREEZE && get_time().val >= next_role_swap)) { - pd[port].power_role = PD_ROLE_SINK; - set_state(port, PD_STATE_SNK_DISCONNECTED); - tcpm_set_cc(port, TYPEC_CC_RD); + pd.power_role = PD_ROLE_SINK; + set_state (PD_STATE_SNK_DISCONNECTED); + tcpm_set_cc(TYPEC_CC_RD); next_role_swap = get_time().val + PD_T_DRP_SNK; - pd[port].try_src_marker = get_time().val + PD_T_TRY_WAIT; + pd.try_src_marker = get_time().val + PD_T_TRY_WAIT; /* Swap states quickly */ timeout = 2 * MSEC; @@ -2214,7 +2151,7 @@ void pd_run_state_machine(int port) { break; case PD_STATE_SRC_DISCONNECTED_DEBOUNCE: timeout = 20 * MSEC; - tcpm_get_cc(port, &cc1, &cc2); + tcpm_get_cc(&cc1, &cc2); if (cc1 == TYPEC_CC_VOLT_RD && cc2 == TYPEC_CC_VOLT_RD) { /* Debug accessory */ @@ -2227,19 +2164,19 @@ void pd_run_state_machine(int port) { new_cc_state = PD_CC_AUDIO_ACC; } else { /* No UFP */ - set_state(port, PD_STATE_SRC_DISCONNECTED); + set_state(PD_STATE_SRC_DISCONNECTED); timeout = 5 * MSEC; break; } /* If in Try.SRC state, then don't need to debounce */ - if (!(pd[port].flags & PD_FLAGS_TRY_SRC)) { + if (!(pd.flags & PD_FLAGS_TRY_SRC)) { /* Debounce the cc state */ - if (new_cc_state != pd[port].cc_state) { - pd[port].cc_debounce = get_time().val + + if (new_cc_state != pd.cc_state) { + pd.cc_debounce = get_time().val + PD_T_CC_DEBOUNCE; - pd[port].cc_state = new_cc_state; + pd.cc_state = new_cc_state; break; - } else if (get_time().val < pd[port].cc_debounce) { + } else if (get_time().val < pd.cc_debounce) { break; } } @@ -2248,41 +2185,41 @@ void pd_run_state_machine(int port) { /* UFP is attached */ if (new_cc_state == PD_CC_UFP_ATTACHED || new_cc_state == PD_CC_DEBUG_ACC) { - pd[port].polarity = (cc1 != TYPEC_CC_VOLT_RD); - tcpm_set_polarity(port, pd[port].polarity); + pd.polarity = (cc1 != TYPEC_CC_VOLT_RD); + tcpm_set_polarity(pd.polarity); /* initial data role for source is DFP */ - pd_set_data_role(port, PD_ROLE_DFP); + pd_set_data_role( PD_ROLE_DFP); if (new_cc_state == PD_CC_DEBUG_ACC) - pd[port].flags |= + pd.flags |= PD_FLAGS_TS_DTS_PARTNER; #ifndef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP /* Enable VBUS */ - if (pd_set_power_supply_ready(port)) { + if (pd_set_power_supply_ready()) { #ifdef CONFIG_USBC_SS_MUX - usb_mux_set(port, TYPEC_MUX_NONE, + usb_mux_set( TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, - pd[port].polarity); + pd.polarity); #endif break; } #endif /* If PD comm is enabled, enable TCPC RX */ - if (pd_comm_is_enabled(port)) - tcpm_set_rx_enable(port, 1); + if (pd_comm_is_enabled()) + tcpm_set_rx_enable(1); #ifdef CONFIG_USBC_VCONN - tcpm_set_vconn(port, 1); - pd[port].flags |= PD_FLAGS_VCONN_ON; + tcpm_set_vconn( 1); + pd.flags |= PD_FLAGS_VCONN_ON; #endif - pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE | + pd.flags |= PD_FLAGS_CHECK_PR_ROLE | PD_FLAGS_CHECK_DR_ROLE; hard_reset_count = 0; timeout = 5 * MSEC; - set_state(port, PD_STATE_SRC_STARTUP); + set_state(PD_STATE_SRC_STARTUP); } /* * AUDIO_ACC will remain in this state indefinitely @@ -2291,15 +2228,15 @@ void pd_run_state_machine(int port) { break; case PD_STATE_SRC_HARD_RESET_RECOVER: /* Do not continue until hard reset recovery time */ - if (get_time().val < pd[port].src_recover) { + if (get_time().val < pd.src_recover) { timeout = 50 * MSEC; break; } /* Enable VBUS */ timeout = 10 * MSEC; - if (pd_set_power_supply_ready(port)) { - set_state(port, PD_STATE_SRC_DISCONNECTED); + if (pd_set_power_supply_ready()) { + set_state(PD_STATE_SRC_DISCONNECTED); break; } #ifdef CONFIG_USB_PD_TCPM_TCPCI @@ -2308,21 +2245,21 @@ void pd_run_state_machine(int port) { * to RECEIVE_DETECT register to enable * PD message passing. */ - if (pd_comm_is_enabled(port)) - tcpm_set_rx_enable(port, 1); + if (pd_comm_is_enabled()) + tcpm_set_rx_enable( 1); #endif /* CONFIG_USB_PD_TCPM_TCPCI */ - set_state(port, PD_STATE_SRC_STARTUP); + set_state(PD_STATE_SRC_STARTUP); break; case PD_STATE_SRC_STARTUP: /* Wait for power source to enable */ - if (pd[port].last_state != pd[port].task_state) { - pd[port].flags |= PD_FLAGS_CHECK_IDENTITY; + if (pd.last_state != pd.task_state) { + pd.flags |= PD_FLAGS_CHECK_IDENTITY; /* reset various counters */ caps_count = 0; - pd[port].msg_id = 0; + pd.msg_id = 0; snk_cap_count = 0; - set_state_timeout(port, + set_state_timeout( #ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP /* * delay for power supply to start up. @@ -2332,7 +2269,7 @@ void pd_run_state_machine(int port) { */ get_time().val + PD_POWER_SUPPLY_TURN_ON_DELAY - - (pd[port].last_state == + (pd.last_state == PD_STATE_SRC_DISCONNECTED_DEBOUNCE ? PD_T_CC_DEBOUNCE : 0), #else @@ -2343,13 +2280,13 @@ void pd_run_state_machine(int port) { } break; case PD_STATE_SRC_DISCOVERY: - if (pd[port].last_state != pd[port].task_state) { + if (pd.last_state != pd.task_state) { /* * If we have had PD connection with this port * partner, then start NoResponseTimer. */ - if (pd[port].flags & PD_FLAGS_PREVIOUS_PD_CONN) - set_state_timeout(port, get_time().val + + if (pd.flags & PD_FLAGS_PREVIOUS_PD_CONN) + set_state_timeout(get_time().val + PD_T_NO_RESPONSE, hard_reset_count < PD_HARD_RESET_COUNT ? @@ -2360,15 +2297,15 @@ void pd_run_state_machine(int port) { /* Send source cap some minimum number of times */ if (caps_count < PD_CAPS_COUNT) { /* Query capabilities of the other side */ - res = send_source_cap(port); + res = send_source_cap(); /* packet was acked => PD capable device) */ if (res >= 0) { - set_state(port, PD_STATE_SRC_NEGOCIATE); + set_state(PD_STATE_SRC_NEGOCIATE); timeout = 10 * MSEC; hard_reset_count = 0; caps_count = 0; /* Port partner is PD capable */ - pd[port].flags |= + pd.flags |= PD_FLAGS_PREVIOUS_PD_CONN; } else { /* failed, retry later */ timeout = PD_T_SEND_SOURCE_CAP; @@ -2378,34 +2315,34 @@ void pd_run_state_machine(int port) { break; case PD_STATE_SRC_NEGOCIATE: /* wait for a "Request" message */ - if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, get_time().val + + if (pd.last_state != pd.task_state) + set_state_timeout(get_time().val + PD_T_SENDER_RESPONSE, PD_STATE_HARD_RESET_SEND); break; case PD_STATE_SRC_ACCEPTED: /* Accept sent, wait for enabling the new voltage */ - if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, get_time().val + + if (pd.last_state != pd.task_state) + set_state_timeout(get_time().val + PD_T_SINK_TRANSITION, PD_STATE_SRC_POWERED); break; case PD_STATE_SRC_POWERED: /* Switch to the new requested voltage */ - if (pd[port].last_state != pd[port].task_state) { - pd_transition_voltage(pd[port].requested_idx); - set_state_timeout(port, get_time().val + + if (pd.last_state != pd.task_state) { + pd_transition_voltage(pd.requested_idx); + set_state_timeout(get_time().val + PD_POWER_SUPPLY_TURN_ON_DELAY, PD_STATE_SRC_TRANSITION); } break; case PD_STATE_SRC_TRANSITION: /* the voltage output is good, notify the source */ - res = send_control(port, PD_CTRL_PS_RDY); + res = send_control(PD_CTRL_PS_RDY); if (res >= 0) { timeout = 10 * MSEC; /* it'a time to ping regularly the sink */ - set_state(port, PD_STATE_SRC_READY); + set_state(PD_STATE_SRC_READY); } else { /* The sink did not ack, cut the power... */ - set_state(port, PD_STATE_SRC_DISCONNECTED); + set_state(PD_STATE_SRC_DISCONNECTED); } break; case PD_STATE_SRC_READY: @@ -2416,25 +2353,25 @@ void pd_run_state_machine(int port) { * incoming packet or if VDO response pending to avoid * collisions. */ - if (incoming_packet || (pd[port].vdm_state == VDM_STATE_BUSY)) + if (incoming_packet || (pd.vdm_state == VDM_STATE_BUSY)) break; /* Send updated source capabilities to our partner */ - if (pd[port].flags & PD_FLAGS_UPDATE_SRC_CAPS) { - res = send_source_cap(port); + if (pd.flags & PD_FLAGS_UPDATE_SRC_CAPS) { + res = send_source_cap(); if (res >= 0) { - set_state(port, PD_STATE_SRC_NEGOCIATE); - pd[port].flags &= ~PD_FLAGS_UPDATE_SRC_CAPS; + set_state(PD_STATE_SRC_NEGOCIATE); + pd.flags &= ~PD_FLAGS_UPDATE_SRC_CAPS; } break; } /* Send get sink cap if haven't received it yet */ - if (!(pd[port].flags & PD_FLAGS_SNK_CAP_RECVD)) { + if (!(pd.flags & PD_FLAGS_SNK_CAP_RECVD)) { if (++snk_cap_count <= PD_SNK_CAP_RETRIES) { /* Get sink cap to know if dual-role device */ - send_control(port, PD_CTRL_GET_SINK_CAP); - set_state(port, PD_STATE_SRC_GET_SINK_CAP); + send_control(PD_CTRL_GET_SINK_CAP); + set_state(PD_STATE_SRC_GET_SINK_CAP); break; } else if (debug_level >= 2 && snk_cap_count == PD_SNK_CAP_RETRIES + 1) { @@ -2443,50 +2380,50 @@ void pd_run_state_machine(int port) { } /* Check power role policy, which may trigger a swap */ - if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) { - pd_check_pr_role(port, PD_ROLE_SOURCE, pd[port].flags); - pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE; + if (pd.flags & PD_FLAGS_CHECK_PR_ROLE) { + pd_check_pr_role( PD_ROLE_SOURCE, pd.flags); + pd.flags &= ~PD_FLAGS_CHECK_PR_ROLE; break; } /* Check data role policy, which may trigger a swap */ - if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) { - pd_check_dr_role(port, pd[port].data_role, pd[port].flags); - pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE; + if (pd.flags & PD_FLAGS_CHECK_DR_ROLE) { + pd_check_dr_role(pd.data_role, pd.flags); + pd.flags &= ~PD_FLAGS_CHECK_DR_ROLE; break; } /* Send discovery SVDMs last */ - if (pd[port].data_role == PD_ROLE_DFP - && (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) { + if (pd.data_role == PD_ROLE_DFP + && (pd.flags & PD_FLAGS_CHECK_IDENTITY)) { #ifndef CONFIG_USB_PD_SIMPLE_DFP - pd_send_vdm(port, USB_SID_PD, + pd_send_vdm( USB_SID_PD, CMD_DISCOVER_IDENT, NULL, 0); #endif - pd[port].flags &= ~PD_FLAGS_CHECK_IDENTITY; + pd.flags &= ~PD_FLAGS_CHECK_IDENTITY; break; } - if (!(pd[port].flags & PD_FLAGS_PING_ENABLED)) + if (!(pd.flags & PD_FLAGS_PING_ENABLED)) break; /* Verify that the sink is alive */ - res = send_control(port, PD_CTRL_PING); + res = send_control(PD_CTRL_PING); if (res >= 0) break; /* Ping dropped. Try soft reset. */ - set_state(port, PD_STATE_SOFT_RESET); + set_state(PD_STATE_SOFT_RESET); timeout = 10 * MSEC; break; case PD_STATE_SRC_GET_SINK_CAP: - if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, get_time().val + + if (pd.last_state != pd.task_state) + set_state_timeout(get_time().val + PD_T_SENDER_RESPONSE, PD_STATE_SRC_READY); break; case PD_STATE_DR_SWAP: - if (pd[port].last_state != pd[port].task_state) { - res = send_control(port, PD_CTRL_DR_SWAP); + if (pd.last_state != pd.task_state) { + res = send_control(PD_CTRL_DR_SWAP); if (res < 0) { timeout = 10 * MSEC; /* @@ -2494,20 +2431,19 @@ void pd_run_state_machine(int port) { * soft reset, otherwise ignore * failure. */ - set_state(port, - res == -1 ? - PD_STATE_SOFT_RESET : READY_RETURN_STATE(port)); + set_state( + res == -1 ? PD_STATE_SOFT_RESET : READY_RETURN_STATE()); break; } /* Wait for accept or reject */ - set_state_timeout(port, get_time().val + - PD_T_SENDER_RESPONSE, READY_RETURN_STATE(port)); + set_state_timeout(get_time().val + + PD_T_SENDER_RESPONSE, READY_RETURN_STATE()); } break; #ifdef CONFIG_USB_PD_DUAL_ROLE case PD_STATE_SRC_SWAP_INIT: - if (pd[port].last_state != pd[port].task_state) { - res = send_control(port, PD_CTRL_PR_SWAP); + if (pd.last_state != pd.task_state) { + res = send_control(PD_CTRL_PR_SWAP); if (res < 0) { timeout = 10 * MSEC; /* @@ -2515,44 +2451,43 @@ void pd_run_state_machine(int port) { * soft reset, otherwise ignore * failure. */ - set_state(port, - res == -1 ? PD_STATE_SOFT_RESET : PD_STATE_SRC_READY); + set_state(res == -1 ? PD_STATE_SOFT_RESET : PD_STATE_SRC_READY); break; } /* Wait for accept or reject */ - set_state_timeout(port, get_time().val + + set_state_timeout(get_time().val + PD_T_SENDER_RESPONSE, PD_STATE_SRC_READY); } break; case PD_STATE_SRC_SWAP_SNK_DISABLE: /* Give time for sink to stop drawing current */ - if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, get_time().val + + if (pd.last_state != pd.task_state) + set_state_timeout(get_time().val + PD_T_SINK_TRANSITION, PD_STATE_SRC_SWAP_SRC_DISABLE); break; case PD_STATE_SRC_SWAP_SRC_DISABLE: /* Turn power off */ - if (pd[port].last_state != pd[port].task_state) { - pd_power_supply_reset(port); - set_state_timeout(port, get_time().val + + if (pd.last_state != pd.task_state) { + pd_power_supply_reset(); + set_state_timeout(get_time().val + PD_POWER_SUPPLY_TURN_OFF_DELAY, PD_STATE_SRC_SWAP_STANDBY); } break; case PD_STATE_SRC_SWAP_STANDBY: /* Send PS_RDY to let sink know our power is off */ - if (pd[port].last_state != pd[port].task_state) { + if (pd.last_state != pd.task_state) { /* Send PS_RDY */ - res = send_control(port, PD_CTRL_PS_RDY); + res = send_control(PD_CTRL_PS_RDY); if (res < 0) { timeout = 10 * MSEC; - set_state(port, PD_STATE_SRC_DISCONNECTED); + set_state(PD_STATE_SRC_DISCONNECTED); break; } /* Switch to Rd and swap roles to sink */ - tcpm_set_cc(port, TYPEC_CC_RD); - pd[port].power_role = PD_ROLE_SINK; + tcpm_set_cc(TYPEC_CC_RD); + pd.power_role = PD_ROLE_SINK; /* Wait for PS_RDY from new source */ - set_state_timeout(port, get_time().val + + set_state_timeout(get_time().val + PD_T_PS_SOURCE_ON, PD_STATE_SNK_DISCONNECTED); } break; @@ -2561,30 +2496,30 @@ void pd_run_state_machine(int port) { int rstatus; #endif CPRINTS("TCPC p%d suspended!", port); - pd[port].req_suspend_state = 0; + pd.req_suspend_state = 0; #ifdef CONFIG_USB_PD_TCPC - pd_rx_disable_monitoring(port); - pd_hw_release(port); - pd_power_supply_reset(port); + pd_rx_disable_monitoring(); + pd_hw_release(); + pd_power_supply_reset(); #else - rstatus = tcpm_release(port); + rstatus = tcpm_release(); if (rstatus != 0 && rstatus != EC_ERROR_UNIMPLEMENTED) CPRINTS("TCPC p%d release failed!", port); #endif /* Wait for resume */ // getting rid of task stuff - //while (pd[port].task_state == PD_STATE_SUSPENDED) + //while (pd.task_state == PD_STATE_SUSPENDED) // task_wait_event(-1); #ifdef CONFIG_USB_PD_TCPC - pd_hw_init(port, PD_ROLE_DEFAULT(port)); + pd_hw_init( PD_ROLE_DEFAULT()); CPRINTS("TCPC p%d resumed!", port); #else - if (rstatus != EC_ERROR_UNIMPLEMENTED && pd_restart_tcpc(port) != 0) { + if (rstatus != EC_ERROR_UNIMPLEMENTED && pd_restart_tcpc() != 0) { /* stay in PD_STATE_SUSPENDED */ CPRINTS("TCPC p%d restart failed!", port); break; } - set_state(port, PD_DEFAULT_STATE(port)); + set_state(PD_DEFAULT_STATE()); CPRINTS("TCPC p%d resumed!", port); #endif break; @@ -2596,7 +2531,7 @@ void pd_run_state_machine(int port) { #else timeout = 10 * MSEC; #endif - tcpm_get_cc(port, &cc1, &cc2); + tcpm_get_cc(&cc1, &cc2); #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE /* @@ -2604,11 +2539,11 @@ void pd_run_state_machine(int port) { * not already auto toggling and not try.src */ if (auto_toggle_supported && - !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) && - !(pd[port].flags & PD_FLAGS_TRY_SRC) && + !(pd.flags & PD_FLAGS_TCPC_DRP_TOGGLE) && + !(pd.flags & PD_FLAGS_TRY_SRC) && (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN)) { - set_state(port, PD_STATE_DRP_AUTO_TOGGLE); + set_state( PD_STATE_DRP_AUTO_TOGGLE); timeout = 2*MSEC; break; } @@ -2616,12 +2551,12 @@ void pd_run_state_machine(int port) { /* Source connection monitoring */ if (cc1 != TYPEC_CC_VOLT_OPEN || cc2 != TYPEC_CC_VOLT_OPEN) { - pd[port].cc_state = PD_CC_NONE; + pd.cc_state = PD_CC_NONE; hard_reset_count = 0; new_cc_state = PD_CC_NONE; - pd[port].cc_debounce = get_time().val + + pd.cc_debounce = get_time().val + PD_T_CC_DEBOUNCE; - set_state(port, PD_STATE_SNK_DISCONNECTED_DEBOUNCE); + set_state (PD_STATE_SNK_DISCONNECTED_DEBOUNCE); timeout = 10 * MSEC; break; } @@ -2632,18 +2567,18 @@ void pd_run_state_machine(int port) { * normal dual role toggle until tDRPTryWait timer * expires. */ - if (pd[port].flags & PD_FLAGS_TRY_SRC) { - if (get_time().val > pd[port].try_src_marker) - pd[port].flags &= ~PD_FLAGS_TRY_SRC; + if (pd.flags & PD_FLAGS_TRY_SRC) { + if (get_time().val > pd.try_src_marker) + pd.flags &= ~PD_FLAGS_TRY_SRC; break; } /* If no source detected, check for role toggle. */ if (drp_state == PD_DRP_TOGGLE_ON && get_time().val >= next_role_swap) { /* Swap roles to source */ - pd[port].power_role = PD_ROLE_SOURCE; - set_state(port, PD_STATE_SRC_DISCONNECTED); - tcpm_set_cc(port, TYPEC_CC_RP); + pd.power_role = PD_ROLE_SOURCE; + set_state(PD_STATE_SRC_DISCONNECTED); + tcpm_set_cc(TYPEC_CC_RP); next_role_swap = get_time().val + PD_T_DRP_SRC; /* Swap states quickly */ @@ -2651,7 +2586,7 @@ void pd_run_state_machine(int port) { } break; case PD_STATE_SNK_DISCONNECTED_DEBOUNCE: - tcpm_get_cc(port, &cc1, &cc2); + tcpm_get_cc(&cc1, &cc2); if (cc_is_rp(cc1) && cc_is_rp(cc2)) { /* Debug accessory */ @@ -2660,7 +2595,7 @@ void pd_run_state_machine(int port) { new_cc_state = PD_CC_DFP_ATTACHED; } else { /* No connection any more */ - set_state(port, PD_STATE_SNK_DISCONNECTED); + set_state (PD_STATE_SNK_DISCONNECTED); timeout = 5 * MSEC; break; } @@ -2668,59 +2603,59 @@ void pd_run_state_machine(int port) { timeout = 20 * MSEC; /* Debounce the cc state */ - if (new_cc_state != pd[port].cc_state) { - pd[port].cc_debounce = get_time().val + + if (new_cc_state != pd.cc_state) { + pd.cc_debounce = get_time().val + PD_T_CC_DEBOUNCE; - pd[port].cc_state = new_cc_state; + pd.cc_state = new_cc_state; break; } /* Wait for CC debounce and VBUS present */ - if (get_time().val < pd[port].cc_debounce || !pd_is_vbus_present(port)) + if (get_time().val < pd.cc_debounce || !pd_is_vbus_present()) break; - if (pd_try_src_enable && !(pd[port].flags & PD_FLAGS_TRY_SRC)) { + if (pd_try_src_enable && !(pd.flags & PD_FLAGS_TRY_SRC)) { /* * If TRY_SRC is enabled, but not active, * then force attempt to connect as source. */ - pd[port].try_src_marker = get_time().val + PD_T_TRY_SRC; + pd.try_src_marker = get_time().val + PD_T_TRY_SRC; /* Swap roles to source */ - pd[port].power_role = PD_ROLE_SOURCE; - tcpm_set_cc(port, TYPEC_CC_RP); + pd.power_role = PD_ROLE_SOURCE; + tcpm_set_cc(TYPEC_CC_RP); timeout = 2 * MSEC; - set_state(port, PD_STATE_SRC_DISCONNECTED); + set_state(PD_STATE_SRC_DISCONNECTED); /* Set flag after the state change */ - pd[port].flags |= PD_FLAGS_TRY_SRC; + pd.flags |= PD_FLAGS_TRY_SRC; break; } /* We are attached */ - pd[port].polarity = get_snk_polarity(cc1, cc2); - tcpm_set_polarity(port, pd[port].polarity); + pd.polarity = get_snk_polarity(cc1, cc2); + tcpm_set_polarity(pd.polarity); /* reset message ID on connection */ - pd[port].msg_id = 0; + pd.msg_id = 0; /* initial data role for sink is UFP */ - pd_set_data_role(port, PD_ROLE_UFP); + pd_set_data_role( PD_ROLE_UFP); #if defined(CONFIG_CHARGE_MANAGER) - typec_curr = get_typec_current_limit(pd[port].polarity, cc1, cc2); + typec_curr = get_typec_current_limit(pd.polarity, cc1, cc2); //typec_set_input_current_limit( // port, typec_curr, TYPE_C_VOLTAGE); #endif /* If PD comm is enabled, enable TCPC RX */ - if (pd_comm_is_enabled(port)) - tcpm_set_rx_enable(port, 1); + if (pd_comm_is_enabled()) + tcpm_set_rx_enable(1); /* DFP is attached */ if (new_cc_state == PD_CC_DFP_ATTACHED || new_cc_state == PD_CC_DEBUG_ACC) { - pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE | + pd.flags |= PD_FLAGS_CHECK_PR_ROLE | PD_FLAGS_CHECK_DR_ROLE | PD_FLAGS_CHECK_IDENTITY; if (new_cc_state == PD_CC_DEBUG_ACC) - pd[port].flags |= + pd.flags |= PD_FLAGS_TS_DTS_PARTNER; - send_control(port, PD_CTRL_GET_SOURCE_CAP); - set_state(port, PD_STATE_SNK_DISCOVERY); + send_control(PD_CTRL_GET_SOURCE_CAP); + set_state (PD_STATE_SNK_DISCOVERY); timeout = 10 * MSEC; //hook_call_deferred( // &pd_usb_billboard_deferred_data, @@ -2728,50 +2663,50 @@ void pd_run_state_machine(int port) { } break; case PD_STATE_SNK_HARD_RESET_RECOVER: - if (pd[port].last_state != pd[port].task_state) - pd[port].flags |= PD_FLAGS_CHECK_IDENTITY; + if (pd.last_state != pd.task_state) + pd.flags |= PD_FLAGS_CHECK_IDENTITY; #ifdef CONFIG_USB_PD_VBUS_DETECT_NONE /* * Can't measure vbus state so this is the maximum * recovery time for the source. */ - if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, get_time().val + + if (pd.last_state != pd.task_state) + set_state_timeout( get_time().val + PD_T_SAFE_0V + PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON, PD_STATE_SNK_DISCONNECTED); #else /* Wait for VBUS to go low and then high*/ - if (pd[port].last_state != pd[port].task_state) { + if (pd.last_state != pd.task_state) { snk_hard_reset_vbus_off = 0; - set_state_timeout(port, get_time().val + + set_state_timeout(get_time().val + PD_T_SAFE_0V, hard_reset_count < PD_HARD_RESET_COUNT ? PD_STATE_HARD_RESET_SEND : PD_STATE_SNK_DISCOVERY); } - if (!pd_is_vbus_present(port) && !snk_hard_reset_vbus_off) { + if (!pd_is_vbus_present() && !snk_hard_reset_vbus_off) { /* VBUS has gone low, reset timeout */ snk_hard_reset_vbus_off = 1; - set_state_timeout(port, get_time().val + + set_state_timeout(get_time().val + PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON, PD_STATE_SNK_DISCONNECTED); } - if (pd_is_vbus_present(port) && snk_hard_reset_vbus_off) { + if (pd_is_vbus_present() && snk_hard_reset_vbus_off) { #ifdef CONFIG_USB_PD_TCPM_TCPCI /* * After transmitting hard reset, TCPM writes * to RECEIVE_MESSAGE register to enable * PD message passing. */ - if (pd_comm_is_enabled(port)) - tcpm_set_rx_enable(port, 1); + if (pd_comm_is_enabled()) + tcpm_set_rx_enable( 1); #endif /* CONFIG_USB_PD_TCPM_TCPCI */ /* VBUS went high again */ - set_state(port, PD_STATE_SNK_DISCOVERY); + set_state (PD_STATE_SNK_DISCOVERY); timeout = 10 * MSEC; } @@ -2783,16 +2718,16 @@ void pd_run_state_machine(int port) { break; case PD_STATE_SNK_DISCOVERY: /* Wait for source cap expired only if we are enabled */ - if ((pd[port].last_state != pd[port].task_state) - && pd_comm_is_enabled(port)) { + if ((pd.last_state != pd.task_state) + && pd_comm_is_enabled()) { /* * If VBUS has never been low, and we timeout * waiting for source cap, try a soft reset * first, in case we were already in a stable * contract before this boot. */ - if (pd[port].flags & PD_FLAGS_VBUS_NEVER_LOW) - set_state_timeout(port, get_time().val + + if (pd.flags & PD_FLAGS_VBUS_NEVER_LOW) + set_state_timeout(get_time().val + PD_T_SINK_WAIT_CAP, PD_STATE_SOFT_RESET); /* * If we haven't passed hard reset counter, @@ -2800,12 +2735,12 @@ void pd_run_state_machine(int port) { * NoResponseTimer. */ else if (hard_reset_count < PD_HARD_RESET_COUNT) - set_state_timeout(port, get_time().val + + set_state_timeout(get_time().val + PD_T_SINK_WAIT_CAP, PD_STATE_HARD_RESET_SEND); - else if (pd[port].flags & + else if (pd.flags & PD_FLAGS_PREVIOUS_PD_CONN) /* ErrorRecovery */ - set_state_timeout(port, get_time().val + + set_state_timeout(get_time().val + PD_T_NO_RESPONSE, PD_STATE_SNK_DISCONNECTED); #if defined(CONFIG_CHARGE_MANAGER) /* @@ -2814,7 +2749,7 @@ void pd_run_state_machine(int port) { * typec current limit. So, set to 0 so that * we guarantee this is revised below. */ - if (pd[port].last_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE) + if (pd.last_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE) typec_curr = 0; #endif } @@ -2823,13 +2758,13 @@ void pd_run_state_machine(int port) { timeout = PD_T_SINK_ADJ - PD_T_DEBOUNCE; /* Check if CC pull-up has changed */ - tcpm_get_cc(port, &cc1, &cc2); + tcpm_get_cc(&cc1, &cc2); if (typec_curr - != get_typec_current_limit(pd[port].polarity, cc1, cc2)) { + != get_typec_current_limit(pd.polarity, cc1, cc2)) { /* debounce signal by requiring two reads */ if (typec_curr_change) { /* set new input current limit */ - typec_curr = get_typec_current_limit(pd[port].polarity, cc1, + typec_curr = get_typec_current_limit(pd.polarity, cc1, cc2); //typec_set_input_current_limit( // port, typec_curr, TYPE_C_VOLTAGE); @@ -2845,16 +2780,16 @@ void pd_run_state_machine(int port) { break; case PD_STATE_SNK_REQUESTED: /* Wait for ACCEPT or REJECT */ - if (pd[port].last_state != pd[port].task_state) { + if (pd.last_state != pd.task_state) { hard_reset_count = 0; - set_state_timeout(port, get_time().val + + set_state_timeout(get_time().val + PD_T_SENDER_RESPONSE, PD_STATE_HARD_RESET_SEND); } break; case PD_STATE_SNK_TRANSITION: /* Wait for PS_RDY */ - if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, get_time().val + + if (pd.last_state != pd.task_state) + set_state_timeout(get_time().val + PD_T_PS_TRANSITION, PD_STATE_HARD_RESET_SEND); break; case PD_STATE_SNK_READY: @@ -2865,36 +2800,36 @@ void pd_run_state_machine(int port) { * incoming packet or if VDO response pending to avoid * collisions. */ - if (incoming_packet || (pd[port].vdm_state == VDM_STATE_BUSY)) + if (incoming_packet || (pd.vdm_state == VDM_STATE_BUSY)) break; /* Check for new power to request */ - if (pd[port].new_power_request) { - if (pd_send_request_msg(port, 0) != EC_SUCCESS) - set_state(port, PD_STATE_SOFT_RESET); + if (pd.new_power_request) { + if (pd_send_request_msg(0) != EC_SUCCESS) + set_state(PD_STATE_SOFT_RESET); break; } /* Check power role policy, which may trigger a swap */ - if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) { - pd_check_pr_role(port, PD_ROLE_SINK, pd[port].flags); - pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE; + if (pd.flags & PD_FLAGS_CHECK_PR_ROLE) { + pd_check_pr_role( PD_ROLE_SINK, pd.flags); + pd.flags &= ~PD_FLAGS_CHECK_PR_ROLE; break; } /* Check data role policy, which may trigger a swap */ - if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) { - pd_check_dr_role(port, pd[port].data_role, pd[port].flags); - pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE; + if (pd.flags & PD_FLAGS_CHECK_DR_ROLE) { + pd_check_dr_role(pd.data_role, pd.flags); + pd.flags &= ~PD_FLAGS_CHECK_DR_ROLE; break; } /* If DFP, send discovery SVDMs */ - if (pd[port].data_role == PD_ROLE_DFP - && (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) { - pd_send_vdm(port, USB_SID_PD, + if (pd.data_role == PD_ROLE_DFP + && (pd.flags & PD_FLAGS_CHECK_IDENTITY)) { + pd_send_vdm( USB_SID_PD, CMD_DISCOVER_IDENT, NULL, 0); - pd[port].flags &= ~PD_FLAGS_CHECK_IDENTITY; + pd.flags &= ~PD_FLAGS_CHECK_IDENTITY; break; } @@ -2902,8 +2837,8 @@ void pd_run_state_machine(int port) { timeout = 200 * MSEC; break; case PD_STATE_SNK_SWAP_INIT: - if (pd[port].last_state != pd[port].task_state) { - res = send_control(port, PD_CTRL_PR_SWAP); + if (pd.last_state != pd.task_state) { + res = send_control(PD_CTRL_PR_SWAP); if (res < 0) { timeout = 10 * MSEC; /* @@ -2911,74 +2846,73 @@ void pd_run_state_machine(int port) { * soft reset, otherwise ignore * failure. */ - set_state(port, - res == -1 ? PD_STATE_SOFT_RESET : PD_STATE_SNK_READY); + set_state(res == -1 ? PD_STATE_SOFT_RESET : PD_STATE_SNK_READY); break; } /* Wait for accept or reject */ - set_state_timeout(port, get_time().val + + set_state_timeout(get_time().val + PD_T_SENDER_RESPONSE, PD_STATE_SNK_READY); } break; case PD_STATE_SNK_SWAP_SNK_DISABLE: /* Stop drawing power */ - pd_set_input_current_limit(port, 0, 0); + pd_set_input_current_limit(0, 0); #ifdef CONFIG_CHARGE_MANAGER - //typec_set_input_current_limit(port, 0, 0); - //charge_manager_set_ceil(port, + //typec_set_input_current_limit( 0, 0); + //charge_manager_set_ceil( // CEIL_REQUESTOR_PD, // CHARGE_CEIL_NONE); #endif - set_state(port, PD_STATE_SNK_SWAP_SRC_DISABLE); + set_state (PD_STATE_SNK_SWAP_SRC_DISABLE); timeout = 10 * MSEC; break; case PD_STATE_SNK_SWAP_SRC_DISABLE: /* Wait for PS_RDY */ - if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, get_time().val + + if (pd.last_state != pd.task_state) + set_state_timeout(get_time().val + PD_T_PS_SOURCE_OFF, PD_STATE_HARD_RESET_SEND); break; case PD_STATE_SNK_SWAP_STANDBY: - if (pd[port].last_state != pd[port].task_state) { + if (pd.last_state != pd.task_state) { /* Switch to Rp and enable power supply */ - tcpm_set_cc(port, TYPEC_CC_RP); - if (pd_set_power_supply_ready(port)) { + tcpm_set_cc(TYPEC_CC_RP); + if (pd_set_power_supply_ready()) { /* Restore Rd */ - tcpm_set_cc(port, TYPEC_CC_RD); + tcpm_set_cc(TYPEC_CC_RD); timeout = 10 * MSEC; - set_state(port, PD_STATE_SNK_DISCONNECTED); + set_state (PD_STATE_SNK_DISCONNECTED); break; } /* Wait for power supply to turn on */ - set_state_timeout(port, get_time().val + + set_state_timeout(get_time().val + PD_POWER_SUPPLY_TURN_ON_DELAY, PD_STATE_SNK_SWAP_COMPLETE); } break; case PD_STATE_SNK_SWAP_COMPLETE: /* Send PS_RDY and change to source role */ - res = send_control(port, PD_CTRL_PS_RDY); + res = send_control(PD_CTRL_PS_RDY); if (res < 0) { /* Restore Rd */ - tcpm_set_cc(port, TYPEC_CC_RD); - pd_power_supply_reset(port); + tcpm_set_cc(TYPEC_CC_RD); + pd_power_supply_reset(); timeout = 10 * MSEC; - set_state(port, PD_STATE_SNK_DISCONNECTED); + set_state (PD_STATE_SNK_DISCONNECTED); break; } /* Don't send GET_SINK_CAP on swap */ snk_cap_count = PD_SNK_CAP_RETRIES + 1; caps_count = 0; - pd[port].msg_id = 0; - pd[port].power_role = PD_ROLE_SOURCE; - pd_update_roles(port); - set_state(port, PD_STATE_SRC_DISCOVERY); + pd.msg_id = 0; + pd.power_role = PD_ROLE_SOURCE; + pd_update_roles(); + set_state(PD_STATE_SRC_DISCOVERY); timeout = 10 * MSEC; break; #ifdef CONFIG_USBC_VCONN_SWAP case PD_STATE_VCONN_SWAP_SEND: - if (pd[port].last_state != pd[port].task_state) { - res = send_control(port, PD_CTRL_VCONN_SWAP); + if (pd.last_state != pd.task_state) { + res = send_control( PD_CTRL_VCONN_SWAP); if (res < 0) { timeout = 10*MSEC; /* @@ -2986,39 +2920,39 @@ void pd_run_state_machine(int port) { * soft reset, otherwise ignore * failure. */ - set_state(port, res == -1 ? + set_state( res == -1 ? PD_STATE_SOFT_RESET : - READY_RETURN_STATE(port)); + READY_RETURN_STATE()); break; } /* Wait for accept or reject */ - set_state_timeout(port, + set_state_timeout( get_time().val + PD_T_SENDER_RESPONSE, - READY_RETURN_STATE(port)); + READY_RETURN_STATE()); } break; case PD_STATE_VCONN_SWAP_INIT: - if (pd[port].last_state != pd[port].task_state) { - if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) { + if (pd.last_state != pd.task_state) { + if (!(pd.flags & PD_FLAGS_VCONN_ON)) { /* Turn VCONN on and wait for it */ - tcpm_set_vconn(port, 1); - set_state_timeout(port, + tcpm_set_vconn( 1); + set_state_timeout( get_time().val + PD_VCONN_SWAP_DELAY, PD_STATE_VCONN_SWAP_READY); } else { - set_state_timeout(port, + set_state_timeout( get_time().val + PD_T_VCONN_SOURCE_ON, - READY_RETURN_STATE(port)); + READY_RETURN_STATE()); } } break; case PD_STATE_VCONN_SWAP_READY: - if (pd[port].last_state != pd[port].task_state) { - if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) { + if (pd.last_state != pd.task_state) { + if (!(pd.flags & PD_FLAGS_VCONN_ON)) { /* VCONN is now on, send PS_RDY */ - pd[port].flags |= PD_FLAGS_VCONN_ON; - res = send_control(port, + pd.flags |= PD_FLAGS_VCONN_ON; + res = send_control( PD_CTRL_PS_RDY); if (res == -1) { timeout = 10*MSEC; @@ -3026,67 +2960,67 @@ void pd_run_state_machine(int port) { * If failed to get goodCRC, * send soft reset */ - set_state(port, + set_state( PD_STATE_SOFT_RESET); break; } - set_state(port, - READY_RETURN_STATE(port)); + set_state( + READY_RETURN_STATE()); } else { /* Turn VCONN off and wait for it */ - tcpm_set_vconn(port, 0); - pd[port].flags &= ~PD_FLAGS_VCONN_ON; - set_state_timeout(port, + tcpm_set_vconn( 0); + pd.flags &= ~PD_FLAGS_VCONN_ON; + set_state_timeout( get_time().val + PD_VCONN_SWAP_DELAY, - READY_RETURN_STATE(port)); + READY_RETURN_STATE()); } } break; #endif /* CONFIG_USBC_VCONN_SWAP */ #endif /* CONFIG_USB_PD_DUAL_ROLE */ case PD_STATE_SOFT_RESET: - if (pd[port].last_state != pd[port].task_state) { + if (pd.last_state != pd.task_state) { /* Message ID of soft reset is always 0 */ - pd[port].msg_id = 0; - res = send_control(port, PD_CTRL_SOFT_RESET); + pd.msg_id = 0; + res = send_control(PD_CTRL_SOFT_RESET); /* if soft reset failed, try hard reset. */ if (res < 0) { - set_state(port, PD_STATE_HARD_RESET_SEND); + set_state(PD_STATE_HARD_RESET_SEND); timeout = 5 * MSEC; break; } - set_state_timeout(port, get_time().val + PD_T_SENDER_RESPONSE, + set_state_timeout(get_time().val + PD_T_SENDER_RESPONSE, PD_STATE_HARD_RESET_SEND); } break; case PD_STATE_HARD_RESET_SEND: hard_reset_count++; - if (pd[port].last_state != pd[port].task_state) + if (pd.last_state != pd.task_state) hard_reset_sent = 0; #ifdef CONFIG_CHARGE_MANAGER - if (pd[port].last_state == PD_STATE_SNK_DISCOVERY - || (pd[port].last_state == PD_STATE_SOFT_RESET - && (pd[port].flags & PD_FLAGS_VBUS_NEVER_LOW))) { - pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW; - /* - * If discovery timed out, assume that we - * have a dedicated charger attached. This - * may not be a correct assumption according - * to the specification, but it generally - * works in practice and the harmful - * effects of a wrong assumption here - * are minimal. - */ - //charge_manager_update_dualrole(port, - // CAP_DEDICATED); - } +// if (pd.last_state == PD_STATE_SNK_DISCOVERY +// || (pd.last_state == PD_STATE_SOFT_RESET +// && (pd.flags & PD_FLAGS_VBUS_NEVER_LOW))) { +// pd.flags &= ~PD_FLAGS_VBUS_NEVER_LOW; +// /* +// * If discovery timed out, assume that we +// * have a dedicated charger attached. This +// * may not be a correct assumption according +// * to the specification, but it generally +// * works in practice and the harmful +// * effects of a wrong assumption here +// * are minimal. +// */ +// //charge_manager_update_dualrole( +// // CAP_DEDICATED); +// } #endif /* try sending hard reset until it succeeds */ if (!hard_reset_sent) { - if (pd_transmit(port, TCPC_TX_HARD_RESET, 0, NULL) < 0) { + if (pd_transmit(TCPC_TX_HARD_RESET, 0, NULL) < 0) { timeout = 10 * MSEC; break; } @@ -3097,13 +3031,10 @@ void pd_run_state_machine(int port) { * If we are source, delay before cutting power * to allow sink time to get hard reset. */ - if (pd[port].power_role == PD_ROLE_SOURCE) { - set_state_timeout(port, get_time().val + PD_T_PS_HARD_RESET, - PD_STATE_HARD_RESET_EXECUTE); - } else { - set_state(port, PD_STATE_HARD_RESET_EXECUTE); - timeout = 10 * MSEC; - } + + set_state(PD_STATE_HARD_RESET_EXECUTE); + timeout = 10 * MSEC; + } break; case PD_STATE_HARD_RESET_EXECUTE: @@ -3112,30 +3043,30 @@ void pd_run_state_machine(int port) { * If hard reset while in the last stages of power * swap, then we need to restore our CC resistor. */ - if (pd[port].last_state == PD_STATE_SNK_SWAP_STANDBY) - tcpm_set_cc(port, TYPEC_CC_RD); + if (pd.last_state == PD_STATE_SNK_SWAP_STANDBY) + tcpm_set_cc(TYPEC_CC_RD); #endif /* reset our own state machine */ - pd_execute_hard_reset(port); + pd_execute_hard_reset(); timeout = 10 * MSEC; break; #ifdef CONFIG_COMMON_RUNTIME case PD_STATE_BIST_RX: - send_bist_cmd(port); + send_bist_cmd(); /* Delay at least enough for partner to finish BIST */ timeout = PD_T_BIST_RECEIVE + 20*MSEC; /* Set to appropriate port disconnected state */ - set_state(port, DUAL_ROLE_IF_ELSE(port, + set_state( DUAL_ROLE_IF_ELSE( PD_STATE_SNK_DISCONNECTED, PD_STATE_SRC_DISCONNECTED)); break; case PD_STATE_BIST_TX: - pd_transmit(port, TCPC_TX_BIST_MODE_2, 0, NULL); + pd_transmit( TCPC_TX_BIST_MODE_2, 0, NULL); /* Delay at least enough to finish sending BIST */ timeout = PD_T_BIST_TRANSMIT + 20*MSEC; /* Set to appropriate port disconnected state */ - set_state(port, DUAL_ROLE_IF_ELSE(port, + set_state( DUAL_ROLE_IF_ELSE( PD_STATE_SNK_DISCONNECTED, PD_STATE_SRC_DISCONNECTED)); break; @@ -3148,7 +3079,7 @@ void pd_run_state_machine(int port) { assert(auto_toggle_supported); /* Check for connection */ - tcpm_get_cc(port, &cc1, &cc2); + tcpm_get_cc( &cc1, &cc2); /* Set to appropriate port state */ if (cc1 == TYPEC_CC_VOLT_OPEN && @@ -3172,29 +3103,29 @@ void pd_run_state_machine(int port) { next_state = PD_STATE_DRP_AUTO_TOGGLE; if (next_state != PD_STATE_DRP_AUTO_TOGGLE) { - tcpm_set_drp_toggle(port, 0); + tcpm_set_drp_toggle( 0); #ifdef CONFIG_USB_PD_TCPC_LOW_POWER CPRINTS("TCPC p%d Exit Low Power Mode", port); #endif } if (next_state == PD_STATE_SNK_DISCONNECTED) { - tcpm_set_cc(port, TYPEC_CC_RD); - pd[port].power_role = PD_ROLE_SINK; + tcpm_set_cc( TYPEC_CC_RD); + pd.power_role = PD_ROLE_SINK; timeout = 2*MSEC; } else if (next_state == PD_STATE_SRC_DISCONNECTED) { - tcpm_set_cc(port, TYPEC_CC_RP); - pd[port].power_role = PD_ROLE_SOURCE; + tcpm_set_cc( TYPEC_CC_RP); + pd.power_role = PD_ROLE_SOURCE; timeout = 2*MSEC; } else { - tcpm_set_drp_toggle(port, 1); - pd[port].flags |= PD_FLAGS_TCPC_DRP_TOGGLE; + tcpm_set_drp_toggle( 1); + pd.flags |= PD_FLAGS_TCPC_DRP_TOGGLE; timeout = -1; #ifdef CONFIG_USB_PD_TCPC_LOW_POWER CPRINTS("TCPC p%d Low Power Mode", port); #endif } - set_state(port, next_state); + set_state( next_state); break; } @@ -3203,69 +3134,41 @@ void pd_run_state_machine(int port) { break; } - pd[port].last_state = this_state; + pd.last_state = this_state; /* * Check for state timeout, and if not check if need to adjust * timeout value to wake up on the next state timeout. */ now = get_time(); - if (pd[port].timeout) { - if (now.val >= pd[port].timeout) { - set_state(port, pd[port].timeout_state); + if (pd.timeout) { + if (now.val >= pd.timeout) { + set_state(pd.timeout_state); /* On a state timeout, run next state soon */ timeout = timeout < 10 * MSEC ? timeout : 10 * MSEC; - } else if (pd[port].timeout - now.val < timeout) { - timeout = pd[port].timeout - now.val; + } else if (pd.timeout - now.val < timeout) { + timeout = pd.timeout - now.val; } } /* Check for disconnection if we're connected */ - if (!pd_is_connected(port)) + if (!pd_is_connected()) return; #ifdef CONFIG_USB_PD_DUAL_ROLE - if (pd_is_power_swapping(port)) + if (pd_is_power_swapping()) return; #endif - if (pd[port].power_role == PD_ROLE_SOURCE) { - /* Source: detect disconnect by monitoring CC */ - tcpm_get_cc(port, &cc1, &cc2); - if (pd[port].polarity) - cc1 = cc2; - if (cc1 == TYPEC_CC_VOLT_OPEN) { - set_state(port, PD_STATE_SRC_DISCONNECTED); - /* Debouncing */ - timeout = 10 * MSEC; -#ifdef CONFIG_USB_PD_DUAL_ROLE - /* - * If Try.SRC is configured, then ATTACHED_SRC - * needs to transition to TryWait.SNK. Change - * power role to SNK and start state timer. - */ - if (pd_try_src_enable) { - /* Swap roles to sink */ - pd[port].power_role = PD_ROLE_SINK; - tcpm_set_cc(port, TYPEC_CC_RD); - /* Set timer for TryWait.SNK state */ - pd[port].try_src_marker = get_time().val + PD_T_TRY_WAIT; - /* Advance to TryWait.SNK state */ - set_state(port, PD_STATE_SNK_DISCONNECTED); - /* Mark state as TryWait.SNK */ - pd[port].flags |= PD_FLAGS_TRY_SRC; - } -#endif - } - } + #ifdef CONFIG_USB_PD_DUAL_ROLE /* * Sink disconnect if VBUS is low and we are not recovering * a hard reset. */ - if (pd[port].power_role == PD_ROLE_SINK && !pd_is_vbus_present(port) - && pd[port].task_state != PD_STATE_SNK_HARD_RESET_RECOVER - && pd[port].task_state != PD_STATE_HARD_RESET_EXECUTE) { + if (pd.power_role == PD_ROLE_SINK && !pd_is_vbus_present() + && pd.task_state != PD_STATE_SNK_HARD_RESET_RECOVER + && pd.task_state != PD_STATE_HARD_RESET_EXECUTE) { /* Sink: detect disconnect by monitoring VBUS */ - set_state(port, PD_STATE_SNK_DISCONNECTED); + set_state (PD_STATE_SNK_DISCONNECTED); /* set timeout small to reconnect fast */ timeout = 5 * MSEC; } @@ -3320,34 +3223,34 @@ void pd_run_state_machine(int port) { * port's default state. */ -void pd_set_suspend(int port, int enable) +void pd_set_suspend( int enable) { int tries = 300; if (enable) { - pd[port].req_suspend_state = 1; + pd.req_suspend_state = 1; do { // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); - if (pd[port].task_state == PD_STATE_SUSPENDED) + //task_wake(PD_PORT_TO_TASK_ID()); + if (pd.task_state == PD_STATE_SUSPENDED) break; msleep(1); } while (--tries != 0); if (!tries) CPRINTS("TCPC p%d set_suspend failed!", port); } else { - if (pd[port].task_state != PD_STATE_SUSPENDED) + if (pd.task_state != PD_STATE_SUSPENDED) CPRINTS("TCPC p%d suspend disable request " "while not suspended!", port); - set_state(port, PD_DEFAULT_STATE(port)); + set_state( PD_DEFAULT_STATE()); // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } } -int pd_is_port_enabled(int port) +int pd_is_port_enabled() { - switch (pd[port].task_state) { + switch (pd.task_state) { case PD_STATE_DISABLED: case PD_STATE_SUSPENDED: return 0; @@ -3423,22 +3326,22 @@ static int remote_flashing(int argc, char **argv) flash_offset[port] += argc * 4; } - pd_send_vdm(port, USB_VID_GOOGLE, cmd, data, cnt); + pd_send_vdm( USB_VID_GOOGLE, cmd, data, cnt); /* Wait until VDM is done */ - while (pd[port].vdm_state > 0) + while (pd.vdm_state > 0) task_wait_event(100*MSEC); - ccprintf("DONE %d\n", pd[port].vdm_state); + ccprintf("DONE %d\n", pd.vdm_state); return EC_SUCCESS; } #endif /* defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) */ #if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP) -void pd_send_hpd(int port, enum hpd_event hpd) +void pd_send_hpd( enum hpd_event hpd) { uint32_t data[1]; - int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT); + int opos = pd_alt_mode( USB_SID_DISPLAYPORT); if (!opos) return; @@ -3450,7 +3353,7 @@ void pd_send_hpd(int port, enum hpd_event hpd) 1, /* enabled */ 0, /* power low */ 0x2); - pd_send_vdm(port, USB_SID_DISPLAYPORT, + pd_send_vdm( USB_SID_DISPLAYPORT, VDO_OPOS(opos) | CMD_ATTENTION, data, 1); /* Wait until VDM is done. */ while (pd[0].vdm_state > 0) @@ -3458,70 +3361,70 @@ void pd_send_hpd(int port, enum hpd_event hpd) } #endif -int pd_fetch_acc_log_entry(int port) +int pd_fetch_acc_log_entry() { timestamp_t timeout; /* Cannot send a VDM now, the host should retry */ - if (pd[port].vdm_state > 0) - return pd[port].vdm_state == VDM_STATE_BUSY ? + if (pd.vdm_state > 0) + return pd.vdm_state == VDM_STATE_BUSY ? EC_RES_BUSY : EC_RES_UNAVAILABLE; - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_GET_LOG, NULL, 0); + pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_GET_LOG, NULL, 0); timeout.val = get_time().val + 75*MSEC; /* Wait until VDM is done */ - while ((pd[port].vdm_state > 0) && + while ((pd.vdm_state > 0) && (get_time().val < timeout.val)) task_wait_event(10*MSEC); - if (pd[port].vdm_state > 0) + if (pd.vdm_state > 0) return EC_RES_TIMEOUT; - else if (pd[port].vdm_state < 0) + else if (pd.vdm_state < 0) return EC_RES_ERROR; return EC_RES_SUCCESS; } #ifdef CONFIG_USB_PD_DUAL_ROLE -void pd_request_source_voltage(int port, int mv) +void pd_request_source_voltage( int mv) { pd_set_max_voltage(mv); - if (pd[port].task_state == PD_STATE_SNK_READY || - pd[port].task_state == PD_STATE_SNK_TRANSITION) { + if (pd.task_state == PD_STATE_SNK_READY || + pd.task_state == PD_STATE_SNK_TRANSITION) { /* Set flag to send new power request in pd_task */ - pd[port].new_power_request = 1; + pd.new_power_request = 1; } else { - pd[port].power_role = PD_ROLE_SINK; - tcpm_set_cc(port, TYPEC_CC_RD); - set_state(port, PD_STATE_SNK_DISCONNECTED); + pd.power_role = PD_ROLE_SINK; + tcpm_set_cc( TYPEC_CC_RD); + set_state( PD_STATE_SNK_DISCONNECTED); } // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } -void pd_set_external_voltage_limit(int port, int mv) +void pd_set_external_voltage_limit( int mv) { pd_set_max_voltage(mv); - if (pd[port].task_state == PD_STATE_SNK_READY || - pd[port].task_state == PD_STATE_SNK_TRANSITION) { + if (pd.task_state == PD_STATE_SNK_READY || + pd.task_state == PD_STATE_SNK_TRANSITION) { /* Set flag to send new power request in pd_task */ - pd[port].new_power_request = 1; + pd.new_power_request = 1; // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } } -void pd_update_contract(int port) +void pd_update_contract() { - if ((pd[port].task_state >= PD_STATE_SRC_NEGOCIATE) && - (pd[port].task_state <= PD_STATE_SRC_GET_SINK_CAP)) { - pd[port].flags |= PD_FLAGS_UPDATE_SRC_CAPS; + if ((pd.task_state >= PD_STATE_SRC_NEGOCIATE) && + (pd.task_state <= PD_STATE_SRC_GET_SINK_CAP)) { + pd.flags |= PD_FLAGS_UPDATE_SRC_CAPS; // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } } @@ -3628,25 +3531,25 @@ static int command_pd(int argc, char **argv) #if defined(CONFIG_CMD_PD) && defined(CONFIG_USB_PD_DUAL_ROLE) if (!strcasecmp(argv[2], "tx")) { - set_state(port, PD_STATE_SNK_DISCOVERY); + set_state( PD_STATE_SNK_DISCOVERY); // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } else if (!strcasecmp(argv[2], "bist_rx")) { - set_state(port, PD_STATE_BIST_RX); + set_state( PD_STATE_BIST_RX); // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } else if (!strcasecmp(argv[2], "bist_tx")) { if (*e) return EC_ERROR_PARAM3; - set_state(port, PD_STATE_BIST_TX); + set_state( PD_STATE_BIST_TX); // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } else if (!strcasecmp(argv[2], "charger")) { - pd[port].power_role = PD_ROLE_SOURCE; - tcpm_set_cc(port, TYPEC_CC_RP); - set_state(port, PD_STATE_SRC_DISCONNECTED); + pd.power_role = PD_ROLE_SOURCE; + tcpm_set_cc( TYPEC_CC_RP); + set_state( PD_STATE_SRC_DISCONNECTED); // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } else if (!strncasecmp(argv[2], "dev", 3)) { int max_volt; if (argc >= 4) @@ -3654,42 +3557,42 @@ static int command_pd(int argc, char **argv) else max_volt = pd_get_max_voltage(); - pd_request_source_voltage(port, max_volt); + pd_request_source_voltage( max_volt); ccprintf("max req: %dmV\n", max_volt); } else if (!strcasecmp(argv[2], "disable")) { - pd_comm_enable(port, 0); + pd_comm_enable( 0); ccprintf("Port C%d disable\n", port); return EC_SUCCESS; } else if (!strcasecmp(argv[2], "enable")) { - pd_comm_enable(port, 1); + pd_comm_enable( 1); ccprintf("Port C%d enabled\n", port); return EC_SUCCESS; } else if (!strncasecmp(argv[2], "hard", 4)) { - set_state(port, PD_STATE_HARD_RESET_SEND); + set_state( PD_STATE_HARD_RESET_SEND); // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } else if (!strncasecmp(argv[2], "info", 4)) { int i; ccprintf("Hash "); for (i = 0; i < PD_RW_HASH_SIZE / 4; i++) - ccprintf("%08x ", pd[port].dev_rw_hash[i]); + ccprintf("%08x ", pd.dev_rw_hash[i]); ccprintf("\nImage %s\n", system_image_copy_t_to_string( - pd[port].current_image)); + pd.current_image)); } else if (!strncasecmp(argv[2], "soft", 4)) { - set_state(port, PD_STATE_SOFT_RESET); + set_state( PD_STATE_SOFT_RESET); // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(port)); + //task_wake(PD_PORT_TO_TASK_ID()); } else if (!strncasecmp(argv[2], "swap", 4)) { if (argc < 4) return EC_ERROR_PARAM_COUNT; if (!strncasecmp(argv[3], "power", 5)) - pd_request_power_swap(port); + pd_request_power_swap(); else if (!strncasecmp(argv[3], "data", 4)) - pd_request_data_swap(port); + pd_request_data_swap(); #ifdef CONFIG_USBC_VCONN_SWAP else if (!strncasecmp(argv[3], "vconn", 5)) - pd_request_vconn_swap(port); + pd_request_vconn_swap(); #endif else return EC_ERROR_PARAM3; @@ -3700,11 +3603,11 @@ static int command_pd(int argc, char **argv) enable = strtoi(argv[3], &e, 10); if (*e) return EC_ERROR_PARAM3; - pd_ping_enable(port, enable); + pd_ping_enable( enable); } ccprintf("Pings %s\n", - (pd[port].flags & PD_FLAGS_PING_ENABLED) ? + (pd.flags & PD_FLAGS_PING_ENABLED) ? "on" : "off"); } else if (!strncasecmp(argv[2], "vdm", 3)) { if (argc < 4) @@ -3717,13 +3620,13 @@ static int command_pd(int argc, char **argv) enable = strtoi(argv[4], &e, 10); if (*e) return EC_ERROR_PARAM4; - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_PING_ENABLE, + pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_PING_ENABLE, &enable, 1); } else if (!strncasecmp(argv[3], "curr", 4)) { - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_CURRENT, + pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_CURRENT, NULL, 0); } else if (!strncasecmp(argv[3], "vers", 4)) { - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_VERSION, + pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_VERSION, NULL, 0); } else { return EC_ERROR_PARAM_COUNT; @@ -3737,13 +3640,13 @@ static int command_pd(int argc, char **argv) if (!strncasecmp(argv[2], "state", 5)) { ccprintf("Port C%d CC%d, %s - Role: %s-%s%s " "State: %s, Flags: 0x%04x\n", - port, pd[port].polarity + 1, - pd_comm_is_enabled(port) ? "Ena" : "Dis", - pd[port].power_role == PD_ROLE_SOURCE ? "SRC" : "SNK", - pd[port].data_role == PD_ROLE_DFP ? "DFP" : "UFP", - (pd[port].flags & PD_FLAGS_VCONN_ON) ? "-VC" : "", - pd_state_names[pd[port].task_state], - pd[port].flags); + port, pd.polarity + 1, + pd_comm_is_enabled() ? "Ena" : "Dis", + pd.power_role == PD_ROLE_SOURCE ? "SRC" : "SNK", + pd.data_role == PD_ROLE_DFP ? "DFP" : "UFP", + (pd.flags & PD_FLAGS_VCONN_ON) ? "-VC" : "", + pd_state_names[pd.task_state], + pd.flags); } else { return EC_ERROR_PARAM1; } @@ -3894,12 +3797,12 @@ static int hc_remote_flash(struct host_cmd_handler_args *args) * Busy still with a VDM that host likely generated. 1 deep VDM queue * so just return for retry logic on host side to deal with. */ - if (pd[port].vdm_state > 0) + if (pd.vdm_state > 0) return EC_RES_BUSY; switch (p->cmd) { case USB_PD_FW_REBOOT: - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0); + pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0); /* * Return immediately to free pending i2c bus. Host needs to @@ -3908,7 +3811,7 @@ static int hc_remote_flash(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; case USB_PD_FW_FLASH_ERASE: - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_ERASE, NULL, 0); + pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_FLASH_ERASE, NULL, 0); /* * Return immediately. Host needs to manage delays here which @@ -3917,7 +3820,7 @@ static int hc_remote_flash(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; case USB_PD_FW_ERASE_SIG: - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0); + pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0); timeout.val = get_time().val + 500*MSEC; break; @@ -3928,16 +3831,16 @@ static int hc_remote_flash(struct host_cmd_handler_args *args) size = p->size / 4; for (i = 0; i < size; i += VDO_MAX_SIZE - 1) { - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE, + pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE, data + i, MIN(size - i, VDO_MAX_SIZE - 1)); timeout.val = get_time().val + 500*MSEC; /* Wait until VDM is done */ - while ((pd[port].vdm_state > 0) && + while ((pd.vdm_state > 0) && (get_time().val < timeout.val)) task_wait_event(10*MSEC); - if (pd[port].vdm_state > 0) + if (pd.vdm_state > 0) return EC_RES_TIMEOUT; } return EC_RES_SUCCESS; @@ -3948,13 +3851,13 @@ static int hc_remote_flash(struct host_cmd_handler_args *args) } /* Wait until VDM is done or timeout */ - while ((pd[port].vdm_state > 0) && (get_time().val < timeout.val)) + while ((pd.vdm_state > 0) && (get_time().val < timeout.val)) task_wait_event(50*MSEC); - if ((pd[port].vdm_state > 0) || - (pd[port].vdm_state == VDM_STATE_ERR_TMOUT)) + if ((pd.vdm_state > 0) || + (pd.vdm_state == VDM_STATE_ERR_TMOUT)) rv = EC_RES_TIMEOUT; - else if (pd[port].vdm_state < 0) + else if (pd.vdm_state < 0) rv = EC_RES_ERROR; return rv; diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h b/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h index 982dcf37..e44504fb 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h +++ b/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h @@ -18,110 +18,93 @@ #endif #ifndef CONFIG_USB_PD_TCPC -extern const struct tcpc_config_t tcpc_config[]; +extern const struct tcpc_config_t tcpc_config; /* I2C wrapper functions - get I2C port / slave addr from config struct. */ -int tcpc_write(int port, int reg, int val); -int tcpc_write16(int port, int reg, int val); -int tcpc_read(int port, int reg, int *val); -int tcpc_read16(int port, int reg, int *val); -int tcpc_xfer(int port, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, +int tcpc_write(int reg, int val); +int tcpc_write16(int reg, int val); +int tcpc_read(int reg, int *val); +int tcpc_read16(int reg, int *val); +int tcpc_xfer(const uint8_t *out, int out_size, uint8_t *in, int in_size, int flags); /* TCPM driver wrapper function */ -static inline int tcpm_init(int port) -{ +static inline int tcpm_init() { int rv; - rv = tcpc_config[port].drv->init(port); + rv = tcpc_config.drv->init(); if (rv) return rv; /* Board specific post TCPC init */ if (board_tcpc_post_init) - rv = board_tcpc_post_init(port); + rv = board_tcpc_post_init(); return rv; } -static inline int tcpm_release(int port) -{ - return tcpc_config[port].drv->release(port); +static inline int tcpm_release() { + return tcpc_config.drv->release(); } -static inline int tcpm_get_cc(int port, int *cc1, int *cc2) -{ - return tcpc_config[port].drv->get_cc(port, cc1, cc2); +static inline int tcpm_get_cc(int *cc1, int *cc2) { + return tcpc_config.drv->get_cc(cc1, cc2); } -static inline int tcpm_get_vbus_level(int port) -{ - return tcpc_config[port].drv->get_vbus_level(port); +static inline int tcpm_get_vbus_level() { + return tcpc_config.drv->get_vbus_level(); } -static inline int tcpm_select_rp_value(int port, int rp) -{ - return tcpc_config[port].drv->select_rp_value(port, rp); +static inline int tcpm_select_rp_value(int rp) { + return tcpc_config.drv->select_rp_value(rp); } -static inline int tcpm_set_cc(int port, int pull) -{ - return tcpc_config[port].drv->set_cc(port, pull); +static inline int tcpm_set_cc(int pull) { + return tcpc_config.drv->set_cc(pull); } -static inline int tcpm_set_polarity(int port, int polarity) -{ - return tcpc_config[port].drv->set_polarity(port, polarity); +static inline int tcpm_set_polarity(int polarity) { + return tcpc_config.drv->set_polarity(polarity); } -static inline int tcpm_set_vconn(int port, int enable) -{ - return tcpc_config[port].drv->set_vconn(port, enable); +static inline int tcpm_set_vconn(int enable) { + return tcpc_config.drv->set_vconn(enable); } -static inline int tcpm_set_msg_header(int port, int power_role, int data_role) -{ - return tcpc_config[port].drv->set_msg_header(port, power_role, - data_role); +static inline int tcpm_set_msg_header(int power_role, int data_role) { + return tcpc_config.drv->set_msg_header(power_role, data_role); } -static inline int tcpm_set_rx_enable(int port, int enable) -{ - return tcpc_config[port].drv->set_rx_enable(port, enable); +static inline int tcpm_set_rx_enable(int enable) { + return tcpc_config.drv->set_rx_enable(enable); } -static inline int tcpm_get_message(int port, uint32_t *payload, int *head) -{ - return tcpc_config[port].drv->get_message(port, payload, head); +static inline int tcpm_get_message(uint32_t *payload, int *head) { + return tcpc_config.drv->get_message(payload, head); } -static inline int tcpm_transmit(int port, enum tcpm_transmit_type type, - uint16_t header, const uint32_t *data) -{ - return tcpc_config[port].drv->transmit(port, type, header, data); +static inline int tcpm_transmit(enum tcpm_transmit_type type, uint16_t header, + const uint32_t *data) { + return tcpc_config.drv->transmit(type, header, data); } -static inline void tcpc_alert(int port) -{ - tcpc_config[port].drv->tcpc_alert(port); +static inline void tcpc_alert() { + tcpc_config.drv->tcpc_alert(); } -static inline void tcpc_discharge_vbus(int port, int enable) -{ - tcpc_config[port].drv->tcpc_discharge_vbus(port, enable); +static inline void tcpc_discharge_vbus(int enable) { + tcpc_config.drv->tcpc_discharge_vbus(enable); } #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE -static inline int tcpm_auto_toggle_supported(int port) +static inline int tcpm_auto_toggle_supported() { - return !!tcpc_config[port].drv->drp_toggle; + return !!tcpc_config.drv->drp_toggle; } -static inline int tcpm_set_drp_toggle(int port, int enable) +static inline int tcpm_set_drp_toggle( int enable) { - return tcpc_config[port].drv->drp_toggle(port, enable); + return tcpc_config.drv->drp_toggle( enable); } #endif @@ -129,21 +112,20 @@ static inline int tcpm_set_drp_toggle(int port, int enable) static inline int tcpc_i2c_read(const int port, const int addr, const int reg, int *data) { - return tcpc_read(port, reg, data); + return tcpc_read( reg, data); } static inline int tcpc_i2c_write(const int port, const int addr, const int reg, int data) { - return tcpc_write(port, reg, data); + return tcpc_write( reg, data); } #endif -static inline int tcpm_get_chip_info(int port, int renew, - struct ec_response_pd_chip_info **info) -{ - if (tcpc_config[port].drv->get_chip_info) - return tcpc_config[port].drv->get_chip_info(port, renew, info); +static inline int tcpm_get_chip_info(int renew, + struct ec_response_pd_chip_info **info) { + if (tcpc_config.drv->get_chip_info) + return tcpc_config.drv->get_chip_info(renew, info); return EC_ERROR_UNIMPLEMENTED; } @@ -156,7 +138,7 @@ static inline int tcpm_get_chip_info(int port, int renew, * * @return EC_SUCCESS or error */ -int tcpm_init(int port); +int tcpm_init(); /** * Read the CC line status. @@ -167,7 +149,7 @@ int tcpm_init(int port); * * @return EC_SUCCESS or error */ -int tcpm_get_cc(int port, int *cc1, int *cc2); +int tcpm_get_cc( int *cc1, int *cc2); /** * Read VBUS @@ -176,7 +158,7 @@ int tcpm_get_cc(int port, int *cc1, int *cc2); * * @return 0 => VBUS not detected, 1 => VBUS detected */ -int tcpm_get_vbus_level(int port); +int tcpm_get_vbus_level(); /** * Set the value of the CC pull-up used when we are a source. @@ -186,7 +168,7 @@ int tcpm_get_vbus_level(int port); * * @return EC_SUCCESS or error */ -int tcpm_select_rp_value(int port, int rp); +int tcpm_select_rp_value( int rp); /** * Set the CC pull resistor. This sets our role as either source or sink. @@ -196,7 +178,7 @@ int tcpm_select_rp_value(int port, int rp); * * @return EC_SUCCESS or error */ -int tcpm_set_cc(int port, int pull); +int tcpm_set_cc( int pull); /** * Set polarity @@ -206,7 +188,7 @@ int tcpm_set_cc(int port, int pull); * * @return EC_SUCCESS or error */ -int tcpm_set_polarity(int port, int polarity); +int tcpm_set_polarity( int polarity); /** * Set Vconn. @@ -216,7 +198,7 @@ int tcpm_set_polarity(int port, int polarity); * * @return EC_SUCCESS or error */ -int tcpm_set_vconn(int port, int enable); +int tcpm_set_vconn( int enable); /** * Set PD message header to use for goodCRC @@ -227,7 +209,7 @@ int tcpm_set_vconn(int port, int enable); * * @return EC_SUCCESS or error */ -int tcpm_set_msg_header(int port, int power_role, int data_role); +int tcpm_set_msg_header( int power_role, int data_role); /** * Set RX enable flag @@ -237,7 +219,7 @@ int tcpm_set_msg_header(int port, int power_role, int data_role); * * @return EC_SUCCESS or error */ -int tcpm_set_rx_enable(int port, int enable); +int tcpm_set_rx_enable( int enable); /** * Read last received PD message. @@ -248,7 +230,7 @@ int tcpm_set_rx_enable(int port, int enable); * * @return EC_SUCCESS or error */ -int tcpm_get_message(int port, uint32_t *payload, int *head); +int tcpm_get_message( uint32_t *payload, int *head); /** * Transmit PD message @@ -261,7 +243,7 @@ int tcpm_get_message(int port, uint32_t *payload, int *head); * * @return EC_SUCCESS or error */ -int tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header, +int tcpm_transmit( enum tcpm_transmit_type type, uint16_t header, const uint32_t *data); /** @@ -269,7 +251,7 @@ int tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header, * * @param port Type-C port number */ -void tcpc_alert(int port); +void tcpc_alert(); #endif diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h b/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h index 947a88c9..86a4fbb3 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h +++ b/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h @@ -71,7 +71,7 @@ enum ec_error_list { /* Module-internal error codes may use this range. */ EC_ERROR_INTERNAL_FIRST = 0x10000, - EC_ERROR_INTERNAL_LAST = 0x1FFFF + EC_ERROR_INTERNAL_LAST = 0x1FFFF }; /* Flags for i2c_xfer() */ @@ -95,17 +95,11 @@ enum tcpc_cc_voltage_status { }; enum tcpc_cc_pull { - TYPEC_CC_RA = 0, - TYPEC_CC_RP = 1, - TYPEC_CC_RD = 2, - TYPEC_CC_OPEN = 3, + TYPEC_CC_RA = 0, TYPEC_CC_RP = 1, TYPEC_CC_RD = 2, TYPEC_CC_OPEN = 3, }; enum tcpc_rp_value { - TYPEC_RP_USB = 0, - TYPEC_RP_1A5 = 1, - TYPEC_RP_3A0 = 2, - TYPEC_RP_RESERVED = 3, + TYPEC_RP_USB = 0, TYPEC_RP_1A5 = 1, TYPEC_RP_3A0 = 2, TYPEC_RP_RESERVED = 3, }; enum tcpm_transmit_type { @@ -120,9 +114,9 @@ enum tcpm_transmit_type { }; enum tcpc_transmit_complete { - TCPC_TX_COMPLETE_SUCCESS = 0, + TCPC_TX_COMPLETE_SUCCESS = 0, TCPC_TX_COMPLETE_DISCARDED = 1, - TCPC_TX_COMPLETE_FAILED = 2, + TCPC_TX_COMPLETE_FAILED = 2, }; struct tcpm_drv { @@ -133,7 +127,7 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*init)(int port); + int (*init)(); /** * Release the TCPM hardware and disconnect the driver. @@ -143,7 +137,7 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*release)(int port); + int (*release)(); /** * Read the CC line status. @@ -154,7 +148,7 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*get_cc)(int port, int *cc1, int *cc2); + int (*get_cc)(int *cc1, int *cc2); /** * Read VBUS @@ -163,7 +157,7 @@ struct tcpm_drv { * * @return 0 => VBUS not detected, 1 => VBUS detected */ - int (*get_vbus_level)(int port); + int (*get_vbus_level)(); /** * Set the value of the CC pull-up used when we are a source. @@ -173,7 +167,7 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*select_rp_value)(int port, int rp); + int (*select_rp_value)(int rp); /** * Set the CC pull resistor. This sets our role as either source or sink. @@ -183,7 +177,7 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*set_cc)(int port, int pull); + int (*set_cc)(int pull); /** * Set polarity @@ -193,7 +187,7 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*set_polarity)(int port, int polarity); + int (*set_polarity)(int polarity); /** * Set Vconn. @@ -203,7 +197,7 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*set_vconn)(int port, int enable); + int (*set_vconn)(int enable); /** * Set PD message header to use for goodCRC @@ -214,7 +208,7 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*set_msg_header)(int port, int power_role, int data_role); + int (*set_msg_header)(int power_role, int data_role); /** * Set RX enable flag @@ -224,7 +218,7 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*set_rx_enable)(int port, int enable); + int (*set_rx_enable)(int enable); /** * Read last received PD message. @@ -235,7 +229,7 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*get_message)(int port, uint32_t *payload, int *head); + int (*get_message)(uint32_t *payload, int *head); /** * Transmit PD message @@ -248,15 +242,15 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*transmit)(int port, enum tcpm_transmit_type type, uint16_t header, - const uint32_t *data); + int (*transmit)(enum tcpm_transmit_type type, uint16_t header, + const uint32_t *data); /** * TCPC is asserting alert * * @param port Type-C port number */ - void (*tcpc_alert)(int port); + void (*tcpc_alert)(); /** * Discharge PD VBUS on src/sink disconnect & power role swap @@ -264,7 +258,7 @@ struct tcpm_drv { * @param port Type-C port number * @param enable Discharge enable or disable */ - void (*tcpc_discharge_vbus)(int port, int enable); + void (*tcpc_discharge_vbus)(int enable); #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE /** @@ -275,7 +269,7 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*drp_toggle)(int port, int enable); + int (*drp_toggle)( int enable); #endif /** @@ -287,20 +281,16 @@ struct tcpm_drv { * * @return EC_SUCCESS or error */ - int (*get_chip_info)(int port, int renew, - struct ec_response_pd_chip_info **info); + int (*get_chip_info)(int renew, struct ec_response_pd_chip_info **info); }; enum tcpc_alert_polarity { - TCPC_ALERT_ACTIVE_LOW, - TCPC_ALERT_ACTIVE_HIGH, + TCPC_ALERT_ACTIVE_LOW, TCPC_ALERT_ACTIVE_HIGH, }; struct tcpc_config_t { - int i2c_host_port; int i2c_slave_addr; const struct tcpm_drv *drv; - enum tcpc_alert_polarity pol; }; /** @@ -317,21 +307,21 @@ uint16_t tcpc_get_alert_status(void); * @param port Type-C port number * @param mode 0: off/sleep, 1: on/awake */ -void board_set_tcpc_power_mode(int port, int mode) __attribute__((weak)); +void board_set_tcpc_power_mode(int mode) __attribute__((weak)); /** * Initialize TCPC. * * @param port Type-C port number */ -void tcpc_init(int port); +void tcpc_init(); /** * TCPC is asserting alert * * @param port Type-C port number */ -void tcpc_alert_clear(int port); +void tcpc_alert_clear(); /** * Run TCPC task once. This checks for incoming messages, processes @@ -340,7 +330,7 @@ void tcpc_alert_clear(int port); * @param port Type-C port number * @param evt Event type that woke up this task */ -int tcpc_run(int port, int evt); +int tcpc_run(int evt); /** * Initialize board specific TCPC functions post TCPC initialization. @@ -349,6 +339,6 @@ int tcpc_run(int port, int evt); * * @return EC_SUCCESS or error */ -int board_tcpc_post_init(int port) __attribute__((weak)); +int board_tcpc_post_init() __attribute__((weak)); #endif /* __CROS_EC_USB_PD_TCPM_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp b/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp index d133ebb4..bf8b60fb 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp @@ -8,36 +8,36 @@ #include "tcpm_driver.h" #include "I2C_Wrapper.hpp" #include "I2CBB.hpp" -extern const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT]; +extern const struct tcpc_config_t tcpc_config; #define STATUS_OK 0 /* I2C wrapper functions - get I2C port / slave addr from config struct. */ -int tcpc_write(int port, int reg, int val) { +int tcpc_write(int reg, int val) { - I2CBB::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) &val, 1); + I2CBB::Mem_Write(tcpc_config.i2c_slave_addr, reg, (uint8_t*) &val, 1); return STATUS_OK; } -int tcpc_write16(int port, int reg, int val) { +int tcpc_write16(int reg, int val) { uint8_t data[2]; data[0] = (0xFF) & val; data[1] = (0xFF) & (val >> 8); - I2CBB::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, 2); + I2CBB::Mem_Write(tcpc_config.i2c_slave_addr, reg, (uint8_t*) data, 2); return STATUS_OK; } -int tcpc_read(int port, int reg, int *val) { +int tcpc_read(int reg, int *val) { uint8_t data[1]; - I2CBB::Mem_Read(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, 1); + I2CBB::Mem_Read(tcpc_config.i2c_slave_addr, reg, (uint8_t*) data, 1); *val = data[0]; return STATUS_OK; } -int tcpc_read16(int port, int reg, int *val) { +int tcpc_read16(int reg, int *val) { uint8_t data[2]; - I2CBB::Mem_Write(tcpc_config[port].i2c_slave_addr, reg, (uint8_t*) data, 2); + I2CBB::Mem_Write(tcpc_config.i2c_slave_addr, reg, (uint8_t*) data, 2); *val = data[0]; *val |= (data[1] << 8); @@ -45,8 +45,8 @@ int tcpc_read16(int port, int reg, int *val) { return STATUS_OK; } -int tcpc_xfer(int port, const uint8_t *out, int out_size, uint8_t *in, - int in_size, int flags) { +int tcpc_xfer(const uint8_t *out, int out_size, uint8_t *in, int in_size, + int flags) { // Write out the I2C port to the given slave address // Write out the out byte array to the device (sending a stop if the flag is set) // Then issue a read from the device @@ -54,12 +54,12 @@ int tcpc_xfer(int port, const uint8_t *out, int out_size, uint8_t *in, if (flags & I2C_XFER_STOP) { //Issuing a stop between the requests //Send as a Tx followed by a Rx - I2CBB::Transmit(tcpc_config[port].i2c_slave_addr, (uint8_t*) out, + I2CBB::Transmit(tcpc_config.i2c_slave_addr, (uint8_t*) out, out_size); - I2CBB::Receive(tcpc_config[port].i2c_slave_addr, in, in_size); + I2CBB::Receive(tcpc_config.i2c_slave_addr, in, in_size); } else { //issue as a continious transmit & recieve - I2CBB::TransmitReceive(tcpc_config[port].i2c_slave_addr, (uint8_t*) out, + I2CBB::TransmitReceive(tcpc_config.i2c_slave_addr, (uint8_t*) out, out_size, in, in_size); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp index 772bc52a..7036633d 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp @@ -26,15 +26,15 @@ uint32_t pd_task_set_event(uint32_t event, int wait_for_reply) { } const uint32_t pd_src_pdo[] = { PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), }; + const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); -const uint32_t pd_snk_pdo[] = { PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), - PDO_FIXED(9000, 500, PDO_FIXED_FLAGS), PDO_FIXED(20000, 500, +const uint32_t pd_snk_pdo[] = { PDO_FIXED(5000, 1000, PDO_FIXED_FLAGS), + PDO_FIXED(9000, 1500, PDO_FIXED_FLAGS), PDO_FIXED(12000, 3500, PDO_FIXED_FLAGS), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); -void pd_set_input_current_limit(int port, uint32_t max_ma, - uint32_t supply_voltage) { +void pd_set_input_current_limit(uint32_t max_ma, uint32_t supply_voltage) { } @@ -42,7 +42,7 @@ int pd_is_valid_input_voltage(int mv) { return 1; } -int pd_snk_is_vbus_provided(int port) { +int pd_snk_is_vbus_provided() { return 1; } @@ -58,20 +58,20 @@ timestamp_t get_time(void) { return t; } -void pd_power_supply_reset(int port) { +void pd_power_supply_reset() { return; } -void pd_execute_data_swap(int port, int data_role) { +void pd_execute_data_swap(int data_role) { /* Do nothing */ } -int pd_check_data_swap(int port, int data_role) { +int pd_check_data_swap(int data_role) { // Never allow data swap return 0; } -int pd_check_power_swap(int port) { +int pd_check_power_swap() { /* Always refuse power swap */ return 0; } @@ -80,17 +80,8 @@ int pd_board_checks(void) { return EC_SUCCESS; } -int pd_set_power_supply_ready(int port) { -#if 0 - /* Disable charging */ - gpio_set_level(GPIO_USB_C0_CHARGE_L, 1); - - /* Enable VBUS source */ - gpio_set_level(GPIO_USB_C0_5V_EN, 1); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); -#endif // if 0 +int pd_set_power_supply_ready() { +//Tells other device if we can supply power return EC_SUCCESS; /* we are ready */ } @@ -132,7 +123,7 @@ void pd_transition_voltage(int idx) { } -void pd_check_dr_role(int port, int dr_role, int flags) { +void pd_check_dr_role(int dr_role, int flags) { #if 0 /* If UFP, try to switch to DFP */ if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP) @@ -140,7 +131,7 @@ void pd_check_dr_role(int port, int dr_role, int flags) { #endif } -void pd_check_pr_role(int port, int pr_role, int flags) { +void pd_check_pr_role(int pr_role, int flags) { #if 0 /* * If partner is dual-role power and dualrole toggling is on, consider @@ -162,40 +153,28 @@ void pd_check_pr_role(int port, int pr_role, int flags) { #endif // if 0 } -void pd_process_source_cap_callback(int port, int cnt, uint32_t *src_caps) { -// char str[256]; -// int i; -// uint32_t ma, mv, pdo; -// uint8_t old_display; -// -// old_display = display_screen; -// display_screen = SCREEN_POWER; -// memset(display_buffer[SCREEN_POWER], 0x00, DISP_MEM_SIZE); -// -// sprintf(str, "Has Power Delivery"); -// UG_PutString(0, 8, str); -// -// for (i = 0; i < cnt; i++) -// { -// pd_extract_pdo_power(src_caps[i], &ma, &mv); -// sprintf(str, "%5.2f V, %5.2f A", (float)mv/1000, (float)ma/1000); -// UG_PutString(0, 8*(i+2), str); -// } -// -// display_screen = old_display; -// display_needs_update = 1; +void pd_process_source_cap_callback(int cnt, uint32_t *src_caps) { + char str[256]; + int i; + uint32_t ma, mv, pdo; + + for (i = 0; i < cnt; i++) { + pd_extract_pdo_power(src_caps[i], &ma, &mv); + //Charger can supply power at mv & mA + //TODO we want to ask for the charger to select the closest to our ideal (12V) + //And fall back to 9V + } //TODO Handle information on supported voltages? } /* ----------------- Vendor Defined Messages ------------------ */ /* Holds valid object position (opos) for entered mode */ -static int alt_mode[PD_AMODE_COUNT]; const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ 1, /* data caps as USB device */ -IDH_PTYPE_AMA, /* Alternate mode */ -1, /* supports alt modes */ +IDH_PTYPE_PERIPH, /* Alternate mode */ +0, /* Does not support alt modes */ USB_VID_GOOGLE); const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); @@ -205,21 +184,19 @@ const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS, 0, /* Vconn power */ 0, /* Vconn power required */ 1, /* Vbus power required */ - AMA_USBSS_BBONLY /* USB SS support */); + AMA_USBSS_U2_ONLY /* USB 2.0 support */); -static int svdm_response_identity(int port, uint32_t *payload) { +static int svdm_response_identity(uint32_t *payload) { payload[VDO_I(IDH)] = vdo_idh; - /* TODO(tbroch): Do we plan to obtain TID (test ID) */ payload[VDO_I(CSTAT)] = VDO_CSTAT(0); payload[VDO_I(PRODUCT)] = vdo_product; payload[VDO_I(AMA)] = vdo_ama; return VDO_I(AMA) + 1; } - -static int svdm_response_svids(int port, uint32_t *payload) { - payload[1] = VDO_SVID(USB_SID_DISPLAYPORT, USB_VID_GOOGLE); - payload[2] = 0; - return 3; +//No custom svdm +static int svdm_response_svids(uint32_t *payload) { + payload[1] = 0; + return 2; } #define OPOS_DP 1 @@ -233,21 +210,11 @@ MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ MODE_DP_SNK) /* Its a sink only */ }; -const uint32_t vdo_goog_modes[1] = { VDO_MODE_GOOGLE(MODE_GOOGLE_FU) }; - -static int svdm_response_modes(int port, uint32_t *payload) { - if (PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) { - memcpy(payload + 1, vdo_dp_modes, sizeof(vdo_dp_modes)); - return ARRAY_SIZE(vdo_dp_modes) + 1; - } else if (PD_VDO_VID(payload[0]) == USB_VID_GOOGLE) { - memcpy(payload + 1, vdo_goog_modes, sizeof(vdo_goog_modes)); - return ARRAY_SIZE(vdo_goog_modes) + 1; - } else { - return 0; /* nak */ - } +static int svdm_response_modes(uint32_t *payload) { + return 0; /* nak */ } -static int dp_status(int port, uint32_t *payload) { +static int dp_status(uint32_t *payload) { int opos = PD_VDO_OPOS(payload[0]); int hpd = 0; // gpio_get_level(GPIO_DP_HPD); if (opos != OPOS_DP) @@ -264,57 +231,22 @@ static int dp_status(int port, uint32_t *payload) { return 2; } -static int dp_config(int port, uint32_t *payload) { - if (PD_DP_CFG_DPON(payload[1])) - 0; //gpio_set_level(GPIO_PD_SBU_ENABLE, 1); +static int dp_config(uint32_t *payload) { return 1; } -static int svdm_enter_mode(int port, uint32_t *payload) { +static int svdm_enter_mode(uint32_t *payload) { int rv = 0; /* will generate a NAK */ - char str[256]; - uint8_t old_display; - /* SID & mode request is valid */ - if ((PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) - && (PD_VDO_OPOS(payload[0]) == OPOS_DP)) { - alt_mode[PD_AMODE_DISPLAYPORT] = OPOS_DP; - rv = 1; - //pd_log_event(PD_EVENT_VIDEO_DP_MODE, 0, 1, NULL); - } else if ((PD_VDO_VID(payload[0]) == USB_VID_GOOGLE) - && (PD_VDO_OPOS(payload[0]) == OPOS_GFU)) { - alt_mode[PD_AMODE_GOOGLE] = OPOS_GFU; - rv = 1; - } - -// if (rv) - /* - * If we failed initial mode entry we'll have enumerated the USB - * Billboard class. If so we should disconnect. - */ - //usb_disconnect(); -// old_display = display_screen; -// display_screen = SCREEN_ALTMODE; -// memset(display_buffer[SCREEN_ALTMODE], 0x00, DISP_MEM_SIZE); -// -// sprintf(str, "Requested Alt Mode"); -// UG_PutString(0, 8, str); -// -// display_screen = old_display; -// display_needs_update = 1; -//TODO handle alt mode ? return rv; } -int pd_alt_mode(int port, uint16_t svid) { - if (svid == USB_SID_DISPLAYPORT) - return alt_mode[PD_AMODE_DISPLAYPORT]; - else if (svid == USB_VID_GOOGLE) - return alt_mode[PD_AMODE_GOOGLE]; +int pd_alt_mode(uint16_t svid) { + return 0; } -static int svdm_exit_mode(int port, uint32_t *payload) { +static int svdm_exit_mode(uint32_t *payload) { return 1; /* Must return ACK */ } @@ -324,91 +256,3 @@ const struct svdm_response svdm_rsp = { &svdm_response_identity, &svdm_response_svids, &svdm_response_modes, &svdm_enter_mode, &svdm_exit_mode, &dp_fx, }; -int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { - int rsize; - - if (PD_VDO_VID(payload[0]) != USB_VID_GOOGLE || !alt_mode[PD_AMODE_GOOGLE]) - return 0; - - *rpayload = payload; - - rsize = pd_custom_flash_vdm(port, cnt, payload); - if (!rsize) { - int cmd = PD_VDO_CMD(payload[0]); - switch (cmd) { - case VDO_CMD_GET_LOG: - rsize = pd_vdm_get_log_entry(payload); - break; - default: - /* Unknown : do not answer */ - return 0; - } - } - - /* respond (positively) to the request */ - payload[0] |= VDO_SRC_RESPONDER; - - return rsize; -} - -int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload) { - static int flash_offset; - int rsize = 1; /* default is just VDM header returned */ - - switch (PD_VDO_CMD(payload[0])) { -#if 0 - case VDO_CMD_VERSION: - memcpy(payload + 1, ¤t_image_data.version, 24); - rsize = 7; - break; - case VDO_CMD_REBOOT: - /* ensure the power supply is in a safe state */ - pd_power_supply_reset(0); - system_reset(0); - break; - case VDO_CMD_READ_INFO: - /* copy info into response */ - pd_get_info(payload + 1); - rsize = 7; - break; - case VDO_CMD_FLASH_ERASE: - /* do not kill the code under our feet */ - if (system_get_image_copy() != SYSTEM_IMAGE_RO) - break; - pd_log_event(PD_EVENT_ACC_RW_ERASE, 0, 0, NULL); - flash_offset = CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF; - flash_physical_erase(CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF, CONFIG_RW_SIZE); - rw_flash_changed = 1; - break; - case VDO_CMD_FLASH_WRITE: - /* do not kill the code under our feet */ - if ((system_get_image_copy() != SYSTEM_IMAGE_RO) || - (flash_offset < CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF)) - break; - flash_physical_write(flash_offset, 4*(cnt - 1), - (const char *)(payload+1)); - flash_offset += 4*(cnt - 1); - rw_flash_changed = 1; - break; - case VDO_CMD_ERASE_SIG: - /* this is not touching the code area */ - { - uint32_t zero = 0; - int offset; - /* zeroes the area containing the RSA signature */ - for (offset = FW_RW_END - RSANUMBYTES; - offset < FW_RW_END; offset += 4) - flash_physical_write(offset, 4, - (const char *)&zero); - } - break; -#endif // 0 - default: - /* Unknown : do not answer */ - return 0; - } - return rsize; -} diff --git a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h index 1a560b1a..18100253 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h +++ b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h @@ -17,9 +17,9 @@ #define CONFIG_CHARGE_MANAGER //#define CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP //#define CONFIG_USBC_VCONN_SWAP -#define CONFIG_USB_PD_ALT_MODE +//#define CONFIG_USB_PD_ALT_MODE //#define CONFIG_USB_PD_CHROMEOS -#define CONFIG_USB_PD_DUAL_ROLE +//#define CONFIG_USB_PD_DUAL_ROLE //#define CONFIG_USB_PD_GIVE_BACK //#define CONFIG_USB_PD_SIMPLE_DFP //#define CONFIG_USB_PD_TCPM_TCPCI diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index 2fe91a24..16730c9e 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -353,8 +353,7 @@ static void settings_setInputPRange(void) { static void settings_displayInputPRange(void) { printShortDescription(0, 5); //0 = 9V, 1=12V (Fixed Voltages, these imply 1.5A limits) - //2 = 18W, 2=24W (Auto Adjusting V, estimated from the tip resistance???) # TODO - // Need to come back and look at these ^ as there were issues with voltage hunting + /// TODO TS80P switch (systemSettings.cutoutSetting) { case 0: OLED::printNumber(9, 2); From f196c5f1c99994838cc43baad68aa21a16bd5e97 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 14 Jun 2020 16:32:11 +1000 Subject: [PATCH 05/53] Moving PD framework + big thread cleanup --- workspace/TS100/Core/BSP/BSP.h | 2 + workspace/TS100/Core/BSP/Miniware/Pins.h | 2 + workspace/TS100/Core/BSP/Miniware/Power.cpp | 17 +- .../TS100/Core/BSP/Miniware/postRTOS.cpp | 8 +- workspace/TS100/Core/BSP/Miniware/preRTOS.cpp | 5 + .../TS100/Core/Drivers/FUSB302/FUSB302.cpp | 935 ---- .../TS100/Core/Drivers/FUSB302/FUSB302.h | 217 - .../Core/Drivers/FUSB302/USBC_PD/usb_pd.h | 1797 -------- .../Drivers/FUSB302/USBC_PD/usb_pd_policy.cpp | 882 ---- .../FUSB302/USBC_PD/usb_pd_protocol.cpp | 4029 ----------------- .../Core/Drivers/FUSB302/USBC_TCPM/tcpm.h | 258 -- .../Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h | 344 -- .../TS100/Core/Drivers/FUSB302/fusb302b.cpp | 204 + .../TS100/Core/Drivers/FUSB302/fusb302b.h | 303 ++ .../TS100/Core/Drivers/FUSB302/fusbpd.cpp | 38 + workspace/TS100/Core/Drivers/FUSB302/fusbpd.h | 18 + .../TS100/Core/Drivers/FUSB302/hard_reset.cpp | 148 + .../TS100/Core/Drivers/FUSB302/hard_reset.h | 63 + .../TS100/Core/Drivers/FUSB302/int_n.cpp | 97 + workspace/TS100/Core/Drivers/FUSB302/int_n.h | 56 + workspace/TS100/Core/Drivers/FUSB302/pd.h | 402 ++ .../TS100/Core/Drivers/FUSB302/pdb_conf.h | 47 + .../TS100/Core/Drivers/FUSB302/pdb_msg.h | 55 + .../Core/Drivers/FUSB302/policy_engine.cpp | 799 ++++ .../Core/Drivers/FUSB302/policy_engine.h | 197 + .../Drivers/FUSB302/policy_engine_user.cpp | 305 ++ .../Core/Drivers/FUSB302/protocol_rx.cpp | 171 + .../TS100/Core/Drivers/FUSB302/protocol_rx.h | 61 + .../Core/Drivers/FUSB302/protocol_tx.cpp | 285 ++ .../TS100/Core/Drivers/FUSB302/protocol_tx.h | 91 + .../Core/Drivers/FUSB302/tcpm_driver.cpp | 72 - .../TS100/Core/Drivers/FUSB302/tcpm_driver.h | 22 - .../Core/Drivers/FUSB302/usb_pd_driver.cpp | 258 -- .../Core/Drivers/FUSB302/usb_pd_driver.h | 104 - workspace/TS100/Core/Inc/FreeRTOSConfig.h | 344 +- workspace/TS100/Core/Src/FreeRTOSHooks.c | 10 + 36 files changed, 3540 insertions(+), 9106 deletions(-) delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/FUSB302.cpp delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/FUSB302.h delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.cpp delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.cpp delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp create mode 100644 workspace/TS100/Core/Drivers/FUSB302/fusb302b.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp create mode 100644 workspace/TS100/Core/Drivers/FUSB302/fusbpd.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp create mode 100644 workspace/TS100/Core/Drivers/FUSB302/hard_reset.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/int_n.cpp create mode 100644 workspace/TS100/Core/Drivers/FUSB302/int_n.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/pd.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/pdb_conf.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/pdb_msg.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp create mode 100644 workspace/TS100/Core/Drivers/FUSB302/policy_engine.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp create mode 100644 workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp create mode 100644 workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h create mode 100644 workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp create mode 100644 workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.h delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp delete mode 100644 workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h diff --git a/workspace/TS100/Core/BSP/BSP.h b/workspace/TS100/Core/BSP/BSP.h index 8c8ce624..2cc0f522 100644 --- a/workspace/TS100/Core/BSP/BSP.h +++ b/workspace/TS100/Core/BSP/BSP.h @@ -51,6 +51,8 @@ uint8_t showBootLogoIfavailable(); void delay_ms(uint16_t count); //Used to allow knowledge of if usb_pd is being used uint8_t usb_pd_detect(); +//Returns 0 when the irq line is pulled down +uint8_t pd_irq_read(); #ifdef __cplusplus } #endif diff --git a/workspace/TS100/Core/BSP/Miniware/Pins.h b/workspace/TS100/Core/BSP/Miniware/Pins.h index ea30222f..ff6586b6 100644 --- a/workspace/TS100/Core/BSP/Miniware/Pins.h +++ b/workspace/TS100/Core/BSP/Miniware/Pins.h @@ -81,6 +81,8 @@ #define SCL2_GPIO_Port GPIOA #define SDA2_Pin GPIO_PIN_1 #define SDA2_GPIO_Port GPIOA +#define INT_PD_Pin GPIO_PIN_9 +#define INT_PD_GPIO_Port GPIOA #endif diff --git a/workspace/TS100/Core/BSP/Miniware/Power.cpp b/workspace/TS100/Core/BSP/Miniware/Power.cpp index cd552479..4421151e 100644 --- a/workspace/TS100/Core/BSP/Miniware/Power.cpp +++ b/workspace/TS100/Core/BSP/Miniware/Power.cpp @@ -2,7 +2,8 @@ #include "BSP_Power.h" #include "QC3.h" #include "Settings.h" -#include "FUSB302.h" +#include "Pins.h" +#include "fusbpd.h" bool FUSB302_present = false; void power_probe() { // If TS80 probe for QC @@ -20,13 +21,6 @@ void power_probe() { void power_check() { #ifdef MODEL_TS80 QC_resync(); - if (FUSB302_present) { - pd_run_state_machine(); - if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9) == GPIO_PIN_RESET) { - tcpc_alert(); - } - } - #endif } uint8_t usb_pd_detect() { @@ -44,3 +38,10 @@ uint8_t usb_pd_detect() { #endif return false; } +uint8_t pd_irq_read() { +#ifdef MODEL_TS80 + return HAL_GPIO_ReadPin(INT_PD_GPIO_Port, INT_PD_Pin) == GPIO_PIN_SET ? + 1 : 0; +#endif + return 0; +} diff --git a/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp b/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp index 7b596758..7255f201 100644 --- a/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp +++ b/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp @@ -8,14 +8,8 @@ #include "stdlib.h" #include "task.h" #include "I2C_Wrapper.hpp" -#include "USBC_TCPM/tcpm.h" + void postRToSInit() { // Any after RTos setup FRToSI2C::FRToSInit(); -#ifdef MODEL_TS80 - tcpm_init(); - osDelay(50); - pd_init(); - osDelay(50); -#endif } diff --git a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp index 674a850c..2e81642a 100644 --- a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp +++ b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp @@ -10,6 +10,7 @@ #include "Setup.h" #include "Pins.h" #include "I2CBB.hpp" +#include "fusbpd.h" void preRToSInit() { /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ @@ -19,5 +20,9 @@ void preRToSInit() { HAL_Delay(50); HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET); HAL_Delay(50); +#ifdef MODEL_TS80 I2CBB::init(); + //Spawn all of the USB-C processors + fusb302_start_processing(); +#endif } diff --git a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.cpp b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.cpp deleted file mode 100644 index f4f657bb..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.cpp +++ /dev/null @@ -1,935 +0,0 @@ -/* - FUSB302.c - Library for interacting with the FUSB302B chip. - Copyright 2015 The Chromium OS Authors - Copyright 2017 Jason Cerundolo - Released under an MIT license. See LICENSE file. - */ - -#include "FUSB302.h" -#include "USBC_TCPM/usb_pd_tcpm.h" -#include "USBC_TCPM/tcpm.h" -#include "USBC_PD/usb_pd.h" -#include -#include "cmsis_os.h" -#include "I2C_Wrapper.hpp" -#define PACKET_IS_GOOD_CRC(head) (PD_HEADER_TYPE(head) == PD_CTRL_GOOD_CRC && \ - PD_HEADER_CNT(head) == 0) -const struct tcpc_config_t tcpc_config = { -fusb302_I2C_SLAVE_ADDR, &fusb302_tcpm_drv }; -static struct fusb302_chip_state { - int cc_polarity; - int vconn_enabled; - /* 1 = pulling up (DFP) 0 = pulling down (UFP) */ - int pulling_up; - int rx_enable; - uint8_t mdac_vnc; - uint8_t mdac_rd; -} state; - -/* - * Bring the FUSB302 out of reset after Hard Reset signaling. This will - * automatically flush both the Rx and Tx FIFOs. - */ -static void fusb302_pd_reset() { - - tcpc_write( TCPC_REG_RESET, TCPC_REG_RESET_PD_RESET); - -} - -/* - * Flush our Rx FIFO. To prevent packet framing issues, this function should - * only be called when Rx is disabled. - */ -static void fusb302_flush_rx_fifo() { - /* - * other bits in the register _should_ be 0 - * until the day we support other SOP* types... - * then we'll have to keep a shadow of what this register - * value should be so we don't clobber it here! - */ - - tcpc_write( TCPC_REG_CONTROL1, TCPC_REG_CONTROL1_RX_FLUSH); - -} - -static void fusb302_flush_tx_fifo() { - int reg; - - tcpc_read( TCPC_REG_CONTROL0, ®); - reg |= TCPC_REG_CONTROL0_TX_FLUSH; - tcpc_write( TCPC_REG_CONTROL0, reg); - -} - -static void fusb302_auto_goodcrc_enable(int enable) { - int reg; - - tcpc_read( TCPC_REG_SWITCHES1, ®); - - if (enable) - reg |= TCPC_REG_SWITCHES1_AUTO_GCRC; - else - reg &= ~TCPC_REG_SWITCHES1_AUTO_GCRC; - - tcpc_write( TCPC_REG_SWITCHES1, reg); - -} - -/* Convert BC LVL values (in FUSB302) to Type-C CC Voltage Status */ -static int convert_bc_lvl(int bc_lvl) { - /* assume OPEN unless one of the following conditions is true... */ - int ret = TYPEC_CC_VOLT_OPEN; - - if (state.pulling_up) { - if (bc_lvl == 0x00) - ret = TYPEC_CC_VOLT_RA; - else if (bc_lvl < 0x3) - ret = TYPEC_CC_VOLT_RD; - } else { - if (bc_lvl == 0x1) - ret = TYPEC_CC_VOLT_SNK_DEF; - else if (bc_lvl == 0x2) - ret = TYPEC_CC_VOLT_SNK_1_5; - else if (bc_lvl == 0x3) - ret = TYPEC_CC_VOLT_SNK_3_0; - } - - return ret; -} - -static int measure_cc_pin_source(int cc_measure) { - int switches0_reg; - int reg; - int cc_lvl; - - /* Read status register */ - tcpc_read( TCPC_REG_SWITCHES0, ®); - /* Save current value */ - switches0_reg = reg; - /* Clear pull-up register settings and measure bits */ - reg &= ~(TCPC_REG_SWITCHES0_MEAS_CC1 | TCPC_REG_SWITCHES0_MEAS_CC2); - /* Set desired pullup register bit */ - if (cc_measure == TCPC_REG_SWITCHES0_MEAS_CC1) - reg |= TCPC_REG_SWITCHES0_CC1_PU_EN; - else - reg |= TCPC_REG_SWITCHES0_CC2_PU_EN; - /* Set CC measure bit */ - reg |= cc_measure; - - /* Set measurement switch */ - tcpc_write( TCPC_REG_SWITCHES0, reg); - - /* Set MDAC for Open vs Rd/Ra comparison */ - tcpc_write( TCPC_REG_MEASURE, state.mdac_vnc); - - /* Wait on measurement */ - usleep(250); - - /* Read status register */ - tcpc_read( TCPC_REG_STATUS0, ®); - - /* Assume open */ - cc_lvl = TYPEC_CC_VOLT_OPEN; - - /* CC level is below the 'no connect' threshold (vOpen) */ - if ((reg & TCPC_REG_STATUS0_COMP) == 0) { - /* Set MDAC for Rd vs Ra comparison */ - tcpc_write( TCPC_REG_MEASURE, state.mdac_rd); - - /* Wait on measurement */ - usleep(250); - - /* Read status register */ - tcpc_read( TCPC_REG_STATUS0, ®); - - cc_lvl = - (reg & TCPC_REG_STATUS0_COMP) ? - TYPEC_CC_VOLT_RD : TYPEC_CC_VOLT_RA; - } - - /* Restore SWITCHES0 register to its value prior */ - tcpc_write( TCPC_REG_SWITCHES0, switches0_reg); - - return cc_lvl; -} - -/* Determine cc pin state for source when in manual detect mode */ -static void detect_cc_pin_source_manual(int *cc1_lvl, int *cc2_lvl) { - int cc1_measure = TCPC_REG_SWITCHES0_MEAS_CC1; - int cc2_measure = TCPC_REG_SWITCHES0_MEAS_CC2; - - if (state.vconn_enabled) { - /* If VCONN enabled, measure cc_pin that matches polarity */ - if (state.cc_polarity) - *cc2_lvl = measure_cc_pin_source(cc2_measure); - else - *cc1_lvl = measure_cc_pin_source(cc1_measure); - } else { - /* If VCONN not enabled, measure both cc1 and cc2 */ - *cc1_lvl = measure_cc_pin_source(cc1_measure); - *cc2_lvl = measure_cc_pin_source(cc2_measure); - } - -} - -/* Determine cc pin state for sink */ -static void detect_cc_pin_sink(int *cc1, int *cc2) { - int reg; - int orig_meas_cc1; - int orig_meas_cc2; - int bc_lvl_cc1; - int bc_lvl_cc2; - - /* - * Measure CC1 first. - */ - tcpc_read( TCPC_REG_SWITCHES0, ®); - - /* save original state to be returned to later... */ - if (reg & TCPC_REG_SWITCHES0_MEAS_CC1) - orig_meas_cc1 = 1; - else - orig_meas_cc1 = 0; - - if (reg & TCPC_REG_SWITCHES0_MEAS_CC2) - orig_meas_cc2 = 1; - else - orig_meas_cc2 = 0; - - /* Disable CC2 measurement switch, enable CC1 measurement switch */ - reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; - reg |= TCPC_REG_SWITCHES0_MEAS_CC1; - - tcpc_write( TCPC_REG_SWITCHES0, reg); - - /* CC1 is now being measured by FUSB302. */ - - /* Wait on measurement */ - usleep(250); - - tcpc_read( TCPC_REG_STATUS0, &bc_lvl_cc1); - - /* mask away unwanted bits */ - bc_lvl_cc1 &= (TCPC_REG_STATUS0_BC_LVL0 | TCPC_REG_STATUS0_BC_LVL1); - - /* - * Measure CC2 next. - */ - - tcpc_read( TCPC_REG_SWITCHES0, ®); - - /* Disable CC1 measurement switch, enable CC2 measurement switch */ - reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1; - reg |= TCPC_REG_SWITCHES0_MEAS_CC2; - - tcpc_write( TCPC_REG_SWITCHES0, reg); - - /* CC2 is now being measured by FUSB302. */ - - /* Wait on measurement */ - usleep(250); - - tcpc_read( TCPC_REG_STATUS0, &bc_lvl_cc2); - - /* mask away unwanted bits */ - bc_lvl_cc2 &= (TCPC_REG_STATUS0_BC_LVL0 | TCPC_REG_STATUS0_BC_LVL1); - - *cc1 = convert_bc_lvl(bc_lvl_cc1); - *cc2 = convert_bc_lvl(bc_lvl_cc2); - - /* return MEAS_CC1/2 switches to original state */ - tcpc_read( TCPC_REG_SWITCHES0, ®); - if (orig_meas_cc1) - reg |= TCPC_REG_SWITCHES0_MEAS_CC1; - else - reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1; - if (orig_meas_cc2) - reg |= TCPC_REG_SWITCHES0_MEAS_CC2; - else - reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; - - tcpc_write( TCPC_REG_SWITCHES0, reg); - -} - -/* Parse header bytes for the size of packet */ -static int get_num_bytes(uint16_t header) { - int rv; - - /* Grab the Number of Data Objects field.*/ - rv = PD_HEADER_CNT(header); - - /* Multiply by four to go from 32-bit words -> bytes */ - rv *= 4; - - /* Plus 2 for header */ - rv += 2; - - return rv; -} - -static int fusb302_send_message(uint16_t header, const uint32_t *data, - uint8_t *buf, int buf_pos) { - int rv; - int reg; - int len; - - len = get_num_bytes(header); - - /* - * packsym tells the TXFIFO that the next X bytes are payload, - * and should not be interpreted as special tokens. - * The 5 LSBs represent X, the number of bytes. - */ - reg = fusb302_TKN_PACKSYM; - reg |= (len & 0x1F); - - buf[buf_pos++] = reg; - - /* write in the header */ - reg = header; - buf[buf_pos++] = reg & 0xFF; - - reg >>= 8; - buf[buf_pos++] = reg & 0xFF; - - /* header is done, subtract from length to make this for-loop simpler */ - len -= 2; - - /* write data objects, if present */ - memcpy(&buf[buf_pos], data, len); - buf_pos += len; - - /* put in the CRC */ - buf[buf_pos++] = fusb302_TKN_JAMCRC; - - /* put in EOP */ - buf[buf_pos++] = fusb302_TKN_EOP; - - /* Turn transmitter off after sending message */ - buf[buf_pos++] = fusb302_TKN_TXOFF; - - /* Start transmission */ - reg = fusb302_TKN_TXON; - buf[buf_pos++] = fusb302_TKN_TXON; - - /* burst write for speed! */ - - rv = tcpc_xfer(buf, buf_pos, 0, 0, I2C_XFER_SINGLE); - - return rv; -} - -static int fusb302_tcpm_select_rp_value(int rp) { - int reg; - int rv; - uint8_t vnc, rd; - - rv = tcpc_read( TCPC_REG_CONTROL0, ®); - if (rv) - return rv; - - /* Set the current source for Rp value */ - reg &= ~TCPC_REG_CONTROL0_HOST_CUR_MASK; - switch (rp) { - case TYPEC_RP_1A5: - reg |= TCPC_REG_CONTROL0_HOST_CUR_1A5; - vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_1_5_VNC_MV); - rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_1_5_RD_THRESH_MV); - break; - case TYPEC_RP_3A0: - reg |= TCPC_REG_CONTROL0_HOST_CUR_3A0; - vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_3_0_VNC_MV); - rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_3_0_RD_THRESH_MV); - break; - case TYPEC_RP_USB: - default: - reg |= TCPC_REG_CONTROL0_HOST_CUR_USB; - vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_VNC_MV); - rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_RD_THRESH_MV); - } - state.mdac_vnc = vnc; - state.mdac_rd = rd; - rv = tcpc_write( TCPC_REG_CONTROL0, reg); - - return rv; -} - -static int fusb302_tcpm_init() { - int reg; - - /* set default */ - state.cc_polarity = -1; - - /* set the voltage threshold for no connect detection (vOpen) */ - state.mdac_vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_VNC_MV); - /* set the voltage threshold for Rd vs Ra detection */ - state.mdac_rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_RD_THRESH_MV); - - /* all other variables assumed to default to 0 */ - - /* Restore default settings */ - tcpc_write( TCPC_REG_RESET, TCPC_REG_RESET_SW_RESET); - - /* Turn on retries and set number of retries */ - tcpc_read( TCPC_REG_CONTROL3, ®); - reg |= TCPC_REG_CONTROL3_AUTO_RETRY; - reg |= (PD_RETRY_COUNT & 0x3) << - TCPC_REG_CONTROL3_N_RETRIES_POS; - tcpc_write( TCPC_REG_CONTROL3, reg); - - /* Create interrupt masks */ - reg = 0xFF; - /* CC level changes */ - reg &= ~TCPC_REG_MASK_BC_LVL; - /* collisions */ - reg &= ~TCPC_REG_MASK_COLLISION; - /* misc alert */ - reg &= ~TCPC_REG_MASK_ALERT; - /* packet received with correct CRC */ - reg &= ~TCPC_REG_MASK_CRC_CHK; - tcpc_write( TCPC_REG_MASK, reg); - - reg = 0xFF; - /* when all pd message retries fail... */ - reg &= ~TCPC_REG_MASKA_RETRYFAIL; - /* when fusb302 send a hard reset. */ - reg &= ~TCPC_REG_MASKA_HARDSENT; - /* when fusb302 receives GoodCRC ack for a pd message */ - reg &= ~TCPC_REG_MASKA_TX_SUCCESS; - /* when fusb302 receives a hard reset */ - reg &= ~TCPC_REG_MASKA_HARDRESET; - tcpc_write( TCPC_REG_MASKA, reg); - - reg = 0xFF; - /* when fusb302 sends GoodCRC to ack a pd message */ - reg &= ~TCPC_REG_MASKB_GCRCSENT; - tcpc_write( TCPC_REG_MASKB, reg); - - /* Interrupt Enable */ - tcpc_read( TCPC_REG_CONTROL0, ®); - reg &= ~TCPC_REG_CONTROL0_INT_MASK; - tcpc_write( TCPC_REG_CONTROL0, reg); - - /* Set VCONN switch defaults */ - tcpm_set_polarity(0); - tcpm_set_vconn(0); - - /* Turn on the power! */ - /* TODO: Reduce power consumption */ - tcpc_write( TCPC_REG_POWER, TCPC_REG_POWER_PWR_ALL); - - return 0; -} - -static int fusb302_tcpm_release() { - return EC_ERROR_UNIMPLEMENTED; -} - -static int fusb302_tcpm_get_cc(int *cc1, int *cc2) { - if (state.pulling_up) { - /* Source mode? */ - detect_cc_pin_source_manual(cc1, cc2); - } else { - /* Sink mode? */ - detect_cc_pin_sink(cc1, cc2); - } - - return 0; -} - -static int fusb302_tcpm_set_cc(int pull) { - int reg; - - /* NOTE: FUSB302 toggles a single pull-up between CC1 and CC2 */ - /* NOTE: FUSB302 Does not support Ra. */ - switch (pull) { - case TYPEC_CC_RP: - /* enable the pull-up we know to be necessary */ - tcpc_read( TCPC_REG_SWITCHES0, ®); - - reg &= ~(TCPC_REG_SWITCHES0_CC2_PU_EN | - TCPC_REG_SWITCHES0_CC1_PU_EN | - TCPC_REG_SWITCHES0_CC1_PD_EN | - TCPC_REG_SWITCHES0_CC2_PD_EN | - TCPC_REG_SWITCHES0_VCONN_CC1 | - TCPC_REG_SWITCHES0_VCONN_CC2); - - reg |= TCPC_REG_SWITCHES0_CC1_PU_EN | - TCPC_REG_SWITCHES0_CC2_PU_EN; - - if (state.vconn_enabled) - reg |= state.cc_polarity ? - TCPC_REG_SWITCHES0_VCONN_CC1 : - TCPC_REG_SWITCHES0_VCONN_CC2; - - tcpc_write( TCPC_REG_SWITCHES0, reg); - - state.pulling_up = 1; - break; - case TYPEC_CC_RD: - /* Enable UFP Mode */ - - /* turn off toggle */ - tcpc_read( TCPC_REG_CONTROL2, ®); - reg &= ~TCPC_REG_CONTROL2_TOGGLE; - tcpc_write( TCPC_REG_CONTROL2, reg); - - /* enable pull-downs, disable pullups */ - tcpc_read( TCPC_REG_SWITCHES0, ®); - - reg &= ~(TCPC_REG_SWITCHES0_CC2_PU_EN); - reg &= ~(TCPC_REG_SWITCHES0_CC1_PU_EN); - reg |= (TCPC_REG_SWITCHES0_CC1_PD_EN); - reg |= (TCPC_REG_SWITCHES0_CC2_PD_EN); - tcpc_write( TCPC_REG_SWITCHES0, reg); - - state.pulling_up = 0; - break; - case TYPEC_CC_OPEN: - /* Disable toggling */ - tcpc_read( TCPC_REG_CONTROL2, ®); - reg &= ~TCPC_REG_CONTROL2_TOGGLE; - tcpc_write( TCPC_REG_CONTROL2, reg); - - /* Ensure manual switches are opened */ - tcpc_read( TCPC_REG_SWITCHES0, ®); - reg &= ~TCPC_REG_SWITCHES0_CC1_PU_EN; - reg &= ~TCPC_REG_SWITCHES0_CC2_PU_EN; - reg &= ~TCPC_REG_SWITCHES0_CC1_PD_EN; - reg &= ~TCPC_REG_SWITCHES0_CC2_PD_EN; - tcpc_write( TCPC_REG_SWITCHES0, reg); - - state.pulling_up = 0; - break; - default: - /* Unsupported... */ - return EC_ERROR_UNIMPLEMENTED; - } - - return 0; -} - -static int fusb302_tcpm_set_polarity(int polarity) { - /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */ - int reg; - - tcpc_read( TCPC_REG_SWITCHES0, ®); - - /* clear VCONN switch bits */ - reg &= ~TCPC_REG_SWITCHES0_VCONN_CC1; - reg &= ~TCPC_REG_SWITCHES0_VCONN_CC2; - - if (state.vconn_enabled) { - /* set VCONN switch to be non-CC line */ - if (polarity) - reg |= TCPC_REG_SWITCHES0_VCONN_CC1; - else - reg |= TCPC_REG_SWITCHES0_VCONN_CC2; - } - - /* clear meas_cc bits (RX line select) */ - reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1; - reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; - - /* set rx polarity */ - if (polarity) - reg |= TCPC_REG_SWITCHES0_MEAS_CC2; - else - reg |= TCPC_REG_SWITCHES0_MEAS_CC1; - - tcpc_write( TCPC_REG_SWITCHES0, reg); - - tcpc_read( TCPC_REG_SWITCHES1, ®); - - /* clear tx_cc bits */ - reg &= ~TCPC_REG_SWITCHES1_TXCC1_EN; - reg &= ~TCPC_REG_SWITCHES1_TXCC2_EN; - - /* set tx polarity */ - if (polarity) - reg |= TCPC_REG_SWITCHES1_TXCC2_EN; - else - reg |= TCPC_REG_SWITCHES1_TXCC1_EN; - - tcpc_write( TCPC_REG_SWITCHES1, reg); - - /* Save the polarity for later */ - state.cc_polarity = polarity; - - return 0; -} - -static int fusb302_tcpm_set_vconn(int enable) { - /* - * FUSB302 does not have dedicated VCONN Enable switch. - * We'll get through this by disabling both of the - * VCONN - CC* switches to disable, and enabling the - * saved polarity when enabling. - * Therefore at startup, tcpm_set_polarity should be called first, - * or else live with the default put into tcpm_init. - */ - int reg; - - /* save enable state for later use */ - state.vconn_enabled = enable; - - if (enable) { - /* set to saved polarity */ - tcpm_set_polarity(state.cc_polarity); - } else { - - tcpc_read( TCPC_REG_SWITCHES0, ®); - - /* clear VCONN switch bits */ - reg &= ~TCPC_REG_SWITCHES0_VCONN_CC1; - reg &= ~TCPC_REG_SWITCHES0_VCONN_CC2; - - tcpc_write( TCPC_REG_SWITCHES0, reg); - - } - - return 0; -} - -static int fusb302_tcpm_set_msg_header(int power_role, int data_role) { - int reg; - - tcpc_read( TCPC_REG_SWITCHES1, ®); - - reg &= ~TCPC_REG_SWITCHES1_POWERROLE; - reg &= ~TCPC_REG_SWITCHES1_DATAROLE; - - if (power_role) - reg |= TCPC_REG_SWITCHES1_POWERROLE; - if (data_role) - reg |= TCPC_REG_SWITCHES1_DATAROLE; - - tcpc_write( TCPC_REG_SWITCHES1, reg); - - return 0; -} - -static int fusb302_tcpm_set_rx_enable(int enable) { - int reg; - - state.rx_enable = enable; - - /* Get current switch state */ - tcpc_read( TCPC_REG_SWITCHES0, ®); - - /* Clear CC1/CC2 measure bits */ - reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1; - reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; - - if (enable) { - switch (state.cc_polarity) { - /* if CC polarity hasnt been determined, can't enable */ - case -1: - return EC_ERROR_UNKNOWN; - case 0: - reg |= TCPC_REG_SWITCHES0_MEAS_CC1; - break; - case 1: - reg |= TCPC_REG_SWITCHES0_MEAS_CC2; - break; - default: - /* "shouldn't get here" */ - return EC_ERROR_UNKNOWN; - } - tcpc_write( TCPC_REG_SWITCHES0, reg); - - /* Disable BC_LVL interrupt when enabling PD comm */ - if (!tcpc_read( TCPC_REG_MASK, ®)) - tcpc_write( TCPC_REG_MASK, reg | TCPC_REG_MASK_BC_LVL); - - /* flush rx fifo in case messages have been coming our way */ - fusb302_flush_rx_fifo(); - - } else { - tcpc_write( TCPC_REG_SWITCHES0, reg); - - /* Enable BC_LVL interrupt when disabling PD comm */ - if (!tcpc_read( TCPC_REG_MASK, ®)) - tcpc_write( TCPC_REG_MASK, reg & ~TCPC_REG_MASK_BC_LVL); - } - - fusb302_auto_goodcrc_enable(enable); - - return 0; -} - -/* Return true if our Rx FIFO is empty */ -static int fusb302_rx_fifo_is_empty() { - int reg, ret; - - ret = (!tcpc_read( TCPC_REG_STATUS1, ®)) - && (reg & TCPC_REG_STATUS1_RX_EMPTY); - - return ret; -} - -static int fusb302_tcpm_get_message(uint32_t *payload, int *head) { - /* - * This is the buffer that will get the burst-read data - * from the fusb302. - * - * It's re-used in a couple different spots, the worst of which - * is the PD packet (not header) and CRC. - * maximum size necessary = 28 + 4 = 32 - */ - uint8_t buf[32]; - int rv, len; - - /* If our FIFO is empty then we have no packet */ - if (fusb302_rx_fifo_is_empty()) - return EC_ERROR_UNKNOWN; - - /* Read until we have a non-GoodCRC packet or an empty FIFO */ - do { - buf[0] = TCPC_REG_FIFOS; - - /* - * PART 1 OF BURST READ: Write in register address. - * Issue a START, no STOP. - */ - rv = tcpc_xfer(buf, 1, 0, 0, I2C_XFER_START); - - /* - * PART 2 OF BURST READ: Read up to the header. - * Issue a repeated START, no STOP. - * only grab three bytes so we can get the header - * and determine how many more bytes we need to read. - * TODO: Check token to ensure valid packet. - */ - rv |= tcpc_xfer(0, 0, buf, 3, I2C_XFER_START); - - /* Grab the header */ - *head = (buf[1] & 0xFF); - *head |= ((buf[2] << 8) & 0xFF00); - - /* figure out packet length, subtract header bytes */ - len = get_num_bytes(*head) - 2; - - /* - * PART 3 OF BURST READ: Read everything else. - * No START, but do issue a STOP at the end. - * add 4 to len to read CRC out - */ - rv |= tcpc_xfer(0, 0, buf, len + 4, I2C_XFER_STOP); - - } while (!rv && PACKET_IS_GOOD_CRC(*head) && !fusb302_rx_fifo_is_empty()); - - if (!rv) { - /* Discard GoodCRC packets */ - if (PACKET_IS_GOOD_CRC(*head)) - rv = EC_ERROR_UNKNOWN; - else - memcpy(payload, buf, len); - } - - /* - * If our FIFO is non-empty then we may have a packet, we may get - * fewer interrupts than packets due to interrupt latency. - */ - //if (!fusb302_rx_fifo_is_empty(port)) - // task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_RX, 0); - return rv; -} - -static int fusb302_tcpm_transmit(enum tcpm_transmit_type type, uint16_t header, - const uint32_t *data) { - /* - * this is the buffer that will be burst-written into the fusb302 - * maximum size necessary = - * 1: FIFO register address - * 4: SOP* tokens - * 1: Token that signifies "next X bytes are not tokens" - * 30: 2 for header and up to 7*4 = 28 for rest of message - * 1: "Insert CRC" Token - * 1: EOP Token - * 1: "Turn transmitter off" token - * 1: "Star Transmission" Command - * - - * 40: 40 bytes worst-case - */ - uint8_t buf[40]; - int buf_pos = 0; - - int reg; - - /* Flush the TXFIFO */ - fusb302_flush_tx_fifo (); - - switch (type) { - case TCPC_TX_SOP: - - /* put register address first for of burst tcpc write */ - buf[buf_pos++] = TCPC_REG_FIFOS; - - /* Write the SOP Ordered Set into TX FIFO */ - buf[buf_pos++] = fusb302_TKN_SYNC1; - buf[buf_pos++] = fusb302_TKN_SYNC1; - buf[buf_pos++] = fusb302_TKN_SYNC1; - buf[buf_pos++] = fusb302_TKN_SYNC2; - - fusb302_send_message(header, data, buf, buf_pos); -// wait for the GoodCRC to come back before we let the rest -// of the code do stuff like change polarity and miss it -// delay_us(600); - osDelay(1); - break; - case TCPC_TX_HARD_RESET: - - /* Simply hit the SEND_HARD_RESET bit */ - tcpc_read( TCPC_REG_CONTROL3, ®); - reg |= TCPC_REG_CONTROL3_SEND_HARDRESET; - tcpc_write( TCPC_REG_CONTROL3, reg); - - break; - case TCPC_TX_BIST_MODE_2: - - /* Hit the BIST_MODE2 bit and start TX */ - tcpc_read( TCPC_REG_CONTROL1, ®); - reg |= TCPC_REG_CONTROL1_BIST_MODE2; - tcpc_write( TCPC_REG_CONTROL1, reg); - - tcpc_read( TCPC_REG_CONTROL0, ®); - reg |= TCPC_REG_CONTROL0_TX_START; - tcpc_write( TCPC_REG_CONTROL0, reg); - -//task_wait_event(PD_T_BIST_TRANSMIT); - - /* Clear BIST mode bit, TX_START is self-clearing */ - tcpc_read( TCPC_REG_CONTROL1, ®); - reg &= ~TCPC_REG_CONTROL1_BIST_MODE2; - tcpc_write( TCPC_REG_CONTROL1, reg); - - break; - default: - return EC_ERROR_UNIMPLEMENTED; - } - - return 0; -} - -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC -static int fusb302_tcpm_get_vbus_level() -{ - int reg; - - /* Read status register */ - - tcpc_read( TCPC_REG_STATUS0, ®); - - return (reg & TCPC_REG_STATUS0_VBUSOK) ? 1 : 0; -} -#endif - -void fusb302_tcpc_alert() { - /* interrupt has been received */ - int interrupt; - int interrupta; - int interruptb; - - /* reading interrupt registers clears them */ - - tcpc_read( TCPC_REG_INTERRUPT, &interrupt); - tcpc_read( TCPC_REG_INTERRUPTA, &interrupta); - tcpc_read( TCPC_REG_INTERRUPTB, &interruptb); - - /* - * Ignore BC_LVL changes when transmitting / receiving PD, - * since CC level will constantly change. - */ - if (state.rx_enable) - interrupt &= ~TCPC_REG_INTERRUPT_BC_LVL; - - if (interrupt & TCPC_REG_INTERRUPT_BC_LVL) { - /* CC Status change */ -//task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0); - } - - if (interrupt & TCPC_REG_INTERRUPT_COLLISION) { - /* packet sending collided */ - pd_transmit_complete(TCPC_TX_COMPLETE_FAILED); - } - - /* GoodCRC was received, our FIFO is now non-empty */ - if (interrupta & TCPC_REG_INTERRUPTA_TX_SUCCESS) { -//task_set_event(PD_PORT_TO_TASK_ID(port), -// PD_EVENT_RX, 0); - - pd_transmit_complete(TCPC_TX_COMPLETE_SUCCESS); - } - - if (interrupta & TCPC_REG_INTERRUPTA_RETRYFAIL) { - /* all retries have failed to get a GoodCRC */ - pd_transmit_complete(TCPC_TX_COMPLETE_FAILED); - } - - if (interrupta & TCPC_REG_INTERRUPTA_HARDSENT) { - /* hard reset has been sent */ - - /* bring FUSB302 out of reset */ - fusb302_pd_reset(); - - pd_transmit_complete(TCPC_TX_COMPLETE_SUCCESS); - } - - if (interrupta & TCPC_REG_INTERRUPTA_HARDRESET) { - /* hard reset has been received */ - - /* bring FUSB302 out of reset */ - fusb302_pd_reset(); - - pd_execute_hard_reset (); - -//task_wake(PD_PORT_TO_TASK_ID(port)); - } - - if (interruptb & TCPC_REG_INTERRUPTB_GCRCSENT) { - /* Packet received and GoodCRC sent */ - /* (this interrupt fires after the GoodCRC finishes) */ - if (state.rx_enable) { - //task_set_event(PD_PORT_TO_TASK_ID(port), - // PD_EVENT_RX, 0); - } else { - /* flush rx fifo if rx isn't enabled */ - fusb302_flush_rx_fifo(); - } - } -} - -/* For BIST receiving */ -void tcpm_set_bist_test_data() { - int reg; - - /* Read control3 register */ - tcpc_read( TCPC_REG_CONTROL3, ®); - - /* Set the BIST_TMODE bit (Clears on Hard Reset) */ - reg |= TCPC_REG_CONTROL3_BIST_TMODE; - - /* Write the updated value */ - tcpc_write( TCPC_REG_CONTROL3, reg); - -} - -const struct tcpm_drv fusb302_tcpm_drv = { &fusb302_tcpm_init, //init - &fusb302_tcpm_release, //.release - &fusb302_tcpm_get_cc, //get_cc - NULL, //get_vbus_level - &fusb302_tcpm_select_rp_value, //select_rp_value - &fusb302_tcpm_set_cc, //set_cc - &fusb302_tcpm_set_polarity, //set_polarity - &fusb302_tcpm_set_vconn, //set_vconn - &fusb302_tcpm_set_msg_header, //set_msg_header - &fusb302_tcpm_set_rx_enable, //set_rx_enable - &fusb302_tcpm_get_message, //get_message - &fusb302_tcpm_transmit, //transmit - &fusb302_tcpc_alert, //tcpc_alert - NULL, //tcpc_discharge_vbus - NULL, //get_chip_info - }; - diff --git a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.h b/workspace/TS100/Core/Drivers/FUSB302/FUSB302.h deleted file mode 100644 index 5a0455aa..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/FUSB302.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - FUSB302.h - Library for interacting with the FUSB302B chip. - Copyright 2010 The Chromium OS Authors - Copyright 2017 Jason Cerundolo - Released under an MIT license. See LICENSE file. -*/ - -#ifndef fusb302_H -#define fusb302_H - -#include -#include "USBC_TCPM/usb_pd_tcpm.h" -#include "USBC_PD/usb_pd.h" - -/* Chip Device ID - 302A or 302B */ -#define fusb302_DEVID_302A 0x08 -#define fusb302_DEVID_302B 0x09 - -/* I2C slave address varies by part number */ -/* FUSB302BUCX / FUSB302BMPX */ -#define fusb302_I2C_SLAVE_ADDR 0x22<<1 // 7-bit address -/* FUSB302B01MPX */ -#define fusb302_I2C_SLAVE_ADDR_B01 0x23<<1 -/* FUSB302B10MPX */ -#define fusb302_I2C_SLAVE_ADDR_B10 0x24<<1 -/* FUSB302B11MPX */ -#define fusb302_I2C_SLAVE_ADDR_B11 0x25<<1 - -/* Default retry count for transmitting */ -#define PD_RETRY_COUNT 3 - -/* Time to wait for TCPC to complete transmit */ -#define PD_T_TCPC_TX_TIMEOUT (100*MSEC) - -#define TCPC_REG_DEVICE_ID 0x01 - -#define TCPC_REG_SWITCHES0 0x02 -#define TCPC_REG_SWITCHES0_CC2_PU_EN (1<<7) -#define TCPC_REG_SWITCHES0_CC1_PU_EN (1<<6) -#define TCPC_REG_SWITCHES0_VCONN_CC2 (1<<5) -#define TCPC_REG_SWITCHES0_VCONN_CC1 (1<<4) -#define TCPC_REG_SWITCHES0_MEAS_CC2 (1<<3) -#define TCPC_REG_SWITCHES0_MEAS_CC1 (1<<2) -#define TCPC_REG_SWITCHES0_CC2_PD_EN (1<<1) -#define TCPC_REG_SWITCHES0_CC1_PD_EN (1<<0) - -#define TCPC_REG_SWITCHES1 0x03 -#define TCPC_REG_SWITCHES1_POWERROLE (1<<7) -#define TCPC_REG_SWITCHES1_SPECREV1 (1<<6) -#define TCPC_REG_SWITCHES1_SPECREV0 (1<<5) -#define TCPC_REG_SWITCHES1_DATAROLE (1<<4) -#define TCPC_REG_SWITCHES1_AUTO_GCRC (1<<2) -#define TCPC_REG_SWITCHES1_TXCC2_EN (1<<1) -#define TCPC_REG_SWITCHES1_TXCC1_EN (1<<0) - -#define TCPC_REG_MEASURE 0x04 -#define TCPC_REG_MEASURE_VBUS (1<<6) -#define TCPC_REG_MEASURE_MDAC_MV(mv) (((mv)/42) & 0x3f) - -#define TCPC_REG_CONTROL0 0x06 -#define TCPC_REG_CONTROL0_TX_FLUSH (1<<6) -#define TCPC_REG_CONTROL0_INT_MASK (1<<5) -#define TCPC_REG_CONTROL0_HOST_CUR_MASK (3<<2) -#define TCPC_REG_CONTROL0_HOST_CUR_3A0 (3<<2) -#define TCPC_REG_CONTROL0_HOST_CUR_1A5 (2<<2) -#define TCPC_REG_CONTROL0_HOST_CUR_USB (1<<2) -#define TCPC_REG_CONTROL0_TX_START (1<<0) - -#define TCPC_REG_CONTROL1 0x07 -#define TCPC_REG_CONTROL1_ENSOP2DB (1<<6) -#define TCPC_REG_CONTROL1_ENSOP1DB (1<<5) -#define TCPC_REG_CONTROL1_BIST_MODE2 (1<<4) -#define TCPC_REG_CONTROL1_RX_FLUSH (1<<2) -#define TCPC_REG_CONTROL1_ENSOP2 (1<<1) -#define TCPC_REG_CONTROL1_ENSOP1 (1<<0) - -#define TCPC_REG_CONTROL2 0x08 -/* two-bit field, valid values below */ -#define TCPC_REG_CONTROL2_MODE (1<<1) -#define TCPC_REG_CONTROL2_MODE_DFP (0x3) -#define TCPC_REG_CONTROL2_MODE_UFP (0x2) -#define TCPC_REG_CONTROL2_MODE_DRP (0x1) -#define TCPC_REG_CONTROL2_MODE_POS (1) -#define TCPC_REG_CONTROL2_TOGGLE (1<<0) - -#define TCPC_REG_CONTROL3 0x09 -#define TCPC_REG_CONTROL3_SEND_HARDRESET (1<<6) -#define TCPC_REG_CONTROL3_BIST_TMODE (1<<5) /* 302B Only */ -#define TCPC_REG_CONTROL3_AUTO_HARDRESET (1<<4) -#define TCPC_REG_CONTROL3_AUTO_SOFTRESET (1<<3) -/* two-bit field */ -#define TCPC_REG_CONTROL3_N_RETRIES (1<<1) -#define TCPC_REG_CONTROL3_N_RETRIES_POS (1) -#define TCPC_REG_CONTROL3_N_RETRIES_SIZE (2) -#define TCPC_REG_CONTROL3_AUTO_RETRY (1<<0) - -#define TCPC_REG_MASK 0x0A -#define TCPC_REG_MASK_VBUSOK (1<<7) -#define TCPC_REG_MASK_ACTIVITY (1<<6) -#define TCPC_REG_MASK_COMP_CHNG (1<<5) -#define TCPC_REG_MASK_CRC_CHK (1<<4) -#define TCPC_REG_MASK_ALERT (1<<3) -#define TCPC_REG_MASK_WAKE (1<<2) -#define TCPC_REG_MASK_COLLISION (1<<1) -#define TCPC_REG_MASK_BC_LVL (1<<0) - -#define TCPC_REG_POWER 0x0B -#define TCPC_REG_POWER_PWR (1<<0) /* four-bit field */ -#define TCPC_REG_POWER_PWR_LOW 0x1 /* Bandgap + Wake circuitry */ -#define TCPC_REG_POWER_PWR_MEDIUM 0x3 /* LOW + Receiver + Current refs */ -#define TCPC_REG_POWER_PWR_HIGH 0x7 /* MEDIUM + Measure block */ -#define TCPC_REG_POWER_PWR_ALL 0xF /* HIGH + Internal Oscillator */ - -#define TCPC_REG_RESET 0x0C -#define TCPC_REG_RESET_PD_RESET (1<<1) -#define TCPC_REG_RESET_SW_RESET (1<<0) - -#define TCPC_REG_MASKA 0x0E -#define TCPC_REG_MASKA_OCP_TEMP (1<<7) -#define TCPC_REG_MASKA_TOGDONE (1<<6) -#define TCPC_REG_MASKA_SOFTFAIL (1<<5) -#define TCPC_REG_MASKA_RETRYFAIL (1<<4) -#define TCPC_REG_MASKA_HARDSENT (1<<3) -#define TCPC_REG_MASKA_TX_SUCCESS (1<<2) -#define TCPC_REG_MASKA_SOFTRESET (1<<1) -#define TCPC_REG_MASKA_HARDRESET (1<<0) - -#define TCPC_REG_MASKB 0x0F -#define TCPC_REG_MASKB_GCRCSENT (1<<0) - -#define TCPC_REG_STATUS0A 0x3C -#define TCPC_REG_STATUS0A_SOFTFAIL (1<<5) -#define TCPC_REG_STATUS0A_RETRYFAIL (1<<4) -#define TCPC_REG_STATUS0A_POWER (1<<2) /* two-bit field */ -#define TCPC_REG_STATUS0A_RX_SOFT_RESET (1<<1) -#define TCPC_REG_STATUS0A_RX_HARD_RESET (1<<0) - -#define TCPC_REG_STATUS1A 0x3D -/* three-bit field, valid values below */ -#define TCPC_REG_STATUS1A_TOGSS (1<<3) -#define TCPC_REG_STATUS1A_TOGSS_RUNNING 0x0 -#define TCPC_REG_STATUS1A_TOGSS_SRC1 0x1 -#define TCPC_REG_STATUS1A_TOGSS_SRC2 0x2 -#define TCPC_REG_STATUS1A_TOGSS_SNK1 0x5 -#define TCPC_REG_STATUS1A_TOGSS_SNK2 0x6 -#define TCPC_REG_STATUS1A_TOGSS_AA 0x7 -#define TCPC_REG_STATUS1A_TOGSS_POS (3) -#define TCPC_REG_STATUS1A_TOGSS_MASK (0x7) - -#define TCPC_REG_STATUS1A_RXSOP2DB (1<<2) -#define TCPC_REG_STATUS1A_RXSOP1DB (1<<1) -#define TCPC_REG_STATUS1A_RXSOP (1<<0) - -#define TCPC_REG_INTERRUPTA 0x3E -#define TCPC_REG_INTERRUPTA_OCP_TEMP (1<<7) -#define TCPC_REG_INTERRUPTA_TOGDONE (1<<6) -#define TCPC_REG_INTERRUPTA_SOFTFAIL (1<<5) -#define TCPC_REG_INTERRUPTA_RETRYFAIL (1<<4) -#define TCPC_REG_INTERRUPTA_HARDSENT (1<<3) -#define TCPC_REG_INTERRUPTA_TX_SUCCESS (1<<2) -#define TCPC_REG_INTERRUPTA_SOFTRESET (1<<1) -#define TCPC_REG_INTERRUPTA_HARDRESET (1<<0) - -#define TCPC_REG_INTERRUPTB 0x3F -#define TCPC_REG_INTERRUPTB_GCRCSENT (1<<0) - -#define TCPC_REG_STATUS0 0x40 -#define TCPC_REG_STATUS0_VBUSOK (1<<7) -#define TCPC_REG_STATUS0_ACTIVITY (1<<6) -#define TCPC_REG_STATUS0_COMP (1<<5) -#define TCPC_REG_STATUS0_CRC_CHK (1<<4) -#define TCPC_REG_STATUS0_ALERT (1<<3) -#define TCPC_REG_STATUS0_WAKE (1<<2) -#define TCPC_REG_STATUS0_BC_LVL1 (1<<1) /* two-bit field */ -#define TCPC_REG_STATUS0_BC_LVL0 (1<<0) /* two-bit field */ - -#define TCPC_REG_STATUS1 0x41 -#define TCPC_REG_STATUS1_RXSOP2 (1<<7) -#define TCPC_REG_STATUS1_RXSOP1 (1<<6) -#define TCPC_REG_STATUS1_RX_EMPTY (1<<5) -#define TCPC_REG_STATUS1_RX_FULL (1<<4) -#define TCPC_REG_STATUS1_TX_EMPTY (1<<3) -#define TCPC_REG_STATUS1_TX_FULL (1<<2) - -#define TCPC_REG_INTERRUPT 0x42 -#define TCPC_REG_INTERRUPT_VBUSOK (1<<7) -#define TCPC_REG_INTERRUPT_ACTIVITY (1<<6) -#define TCPC_REG_INTERRUPT_COMP_CHNG (1<<5) -#define TCPC_REG_INTERRUPT_CRC_CHK (1<<4) -#define TCPC_REG_INTERRUPT_ALERT (1<<3) -#define TCPC_REG_INTERRUPT_WAKE (1<<2) -#define TCPC_REG_INTERRUPT_COLLISION (1<<1) -#define TCPC_REG_INTERRUPT_BC_LVL (1<<0) - -#define TCPC_REG_FIFOS 0x43 - -/* Tokens defined for the FUSB302 TX FIFO */ -enum fusb302_txfifo_tokens { - fusb302_TKN_TXON = 0xA1, - fusb302_TKN_SYNC1 = 0x12, - fusb302_TKN_SYNC2 = 0x13, - fusb302_TKN_SYNC3 = 0x1B, - fusb302_TKN_RST1 = 0x15, - fusb302_TKN_RST2 = 0x16, - fusb302_TKN_PACKSYM = 0x80, - fusb302_TKN_JAMCRC = 0xFF, - fusb302_TKN_EOP = 0x14, - fusb302_TKN_TXOFF = 0xFE, -}; - -extern const struct tcpm_drv fusb302_tcpm_drv; - -//returns 1 if the FUSB302 is on the I2C bus -uint8_t fusb302_detect(); - -#endif /* fusb302_H */ - diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h deleted file mode 100644 index e863e5ff..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd.h +++ /dev/null @@ -1,1797 +0,0 @@ -/* Copyright (c) 2014 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 Power delivery module */ - -#ifndef __USB_PD_H -#define __USB_PD_H - -#include "tcpm_driver.h" -#include "usb_pd_driver.h" - -/* Time units in microseconds */ -#define MSEC (1000) -#define SECOND (1000000) -#define MINUTE (60000000) -#define HOUR (3600000000ull) /* Too big to fit in a signed int */ - -/* PD Host command timeout */ -#define PD_HOST_COMMAND_TIMEOUT_US SECOND - -#ifdef CONFIG_USB_PD_PORT_COUNT -/* - * Define PD_PORT_TO_TASK_ID() and TASK_ID_TO_PD_PORT() macros to - * go between PD port number and task ID. Assume that TASK_ID_PD_C0 is the - * lowest task ID and IDs are on a continuous range. - */ -#ifdef HAS_TASK_PD_C0 -#define PD_PORT_TO_TASK_ID(port) (TASK_ID_PD_C0 + (port)) -#define TASK_ID_TO_PD_PORT(id) ((id) - TASK_ID_PD_C0) -#else -#define PD_PORT_TO_TASK_ID(port) -1 /* dummy task ID */ -#define TASK_ID_TO_PD_PORT(id) 0 -#endif /* CONFIG_COMMON_RUNTIME */ -#endif /* CONFIG_USB_PD_PORT_COUNT */ - -enum pd_rx_errors { - PD_RX_ERR_INVAL = -1, /* Invalid packet */ - PD_RX_ERR_HARD_RESET = -2, /* Got a Hard-Reset packet */ - PD_RX_ERR_CRC = -3, /* CRC mismatch */ - PD_RX_ERR_ID = -4, /* Invalid ID number */ - PD_RX_ERR_UNSUPPORTED_SOP = -5, /* Unsupported SOP */ - PD_RX_ERR_CABLE_RESET = -6 /* Got a Cable-Reset packet */ -}; - -/* Events for USB PD task */ -#define PD_EVENT_RX (1<<2) /* Incoming packet event */ -#define PD_EVENT_TX (1<<3) /* Outgoing packet event */ -#define PD_EVENT_CC (1<<4) /* CC line change event */ -#define PD_EVENT_TCPC_RESET (1<<5) /* TCPC has reset */ -#define PD_EVENT_UPDATE_DUAL_ROLE (1<<6) /* DRP state has changed */ - -/* --- PD data message helpers --- */ -#define PDO_MAX_OBJECTS 7 -#define PDO_MODES (PDO_MAX_OBJECTS - 1) - -/* PDO : Power Data Object */ -/* - * 1. The vSafe5V Fixed Supply Object shall always be the first object. - * 2. The remaining Fixed Supply Objects, - * if present, shall be sent in voltage order; lowest to highest. - * 3. The Battery Supply Objects, - * if present shall be sent in Minimum Voltage order; lowest to highest. - * 4. The Variable Supply (non battery) Objects, - * if present, shall be sent in Minimum Voltage order; lowest to highest. - * 5. (PD3.0) The Augmented PDO is defined to allow extension beyond the 4 PDOs - * above by examining bits <29:28> to determine the additional PDO function. - */ -#define PDO_TYPE_FIXED (0 << 30) -#define PDO_TYPE_BATTERY (1 << 30) -#define PDO_TYPE_VARIABLE (2 << 30) -#define PDO_TYPE_AUGMENTED (3 << 30) -#define PDO_TYPE_MASK (3 << 30) - -#define PDO_FIXED_DUAL_ROLE (1 << 29) /* Dual role device */ -#define PDO_FIXED_SUSPEND (1 << 28) /* USB Suspend supported */ -#define PDO_FIXED_EXTERNAL (1 << 27) /* Externally powered */ -#define PDO_FIXED_COMM_CAP (1 << 26) /* USB Communications Capable */ -#define PDO_FIXED_DATA_SWAP (1 << 25) /* Data role swap command supported */ -#define PDO_FIXED_PEAK_CURR () /* [21..20] Peak current */ -#define PDO_FIXED_VOLT(mv) (((mv)/50) << 10) /* Voltage in 50mV units */ -#define PDO_FIXED_CURR(ma) (((ma)/10) << 0) /* Max current in 10mA units */ - -#define PDO_FIXED(mv, ma, flags) (PDO_FIXED_VOLT(mv) |\ - PDO_FIXED_CURR(ma) | (flags)) - -#define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20) -#define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10) -#define PDO_VAR_OP_CURR(ma) ((((ma) / 10) & 0x3FF) << 0) - -#define PDO_VAR(min_mv, max_mv, op_ma) \ - (PDO_VAR_MIN_VOLT(min_mv) | \ - PDO_VAR_MAX_VOLT(max_mv) | \ - PDO_VAR_OP_CURR(op_ma) | \ - PDO_TYPE_VARIABLE) - -#define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20) -#define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10) -#define PDO_BATT_OP_POWER(mw) ((((mw) / 250) & 0x3FF) << 0) - -#define PDO_BATT(min_mv, max_mv, op_mw) \ - (PDO_BATT_MIN_VOLT(min_mv) | \ - PDO_BATT_MAX_VOLT(max_mv) | \ - PDO_BATT_OP_POWER(op_mw) | \ - PDO_TYPE_BATTERY) - -/* RDO : Request Data Object */ -#define RDO_OBJ_POS(n) (((n) & 0x7) << 28) -#define RDO_POS(rdo) (((rdo) >> 28) & 0x7) -#define RDO_GIVE_BACK (1 << 27) -#define RDO_CAP_MISMATCH (1 << 26) -#define RDO_COMM_CAP (1 << 25) -#define RDO_NO_SUSPEND (1 << 24) -#define RDO_FIXED_VAR_OP_CURR(ma) ((((ma) / 10) & 0x3FF) << 10) -#define RDO_FIXED_VAR_MAX_CURR(ma) ((((ma) / 10) & 0x3FF) << 0) - -#define RDO_BATT_OP_POWER(mw) ((((mw) / 250) & 0x3FF) << 10) -#define RDO_BATT_MAX_POWER(mw) ((((mw) / 250) & 0x3FF) << 10) - -#define RDO_FIXED(n, op_ma, max_ma, flags) \ - (RDO_OBJ_POS(n) | (flags) | \ - RDO_FIXED_VAR_OP_CURR(op_ma) | \ - RDO_FIXED_VAR_MAX_CURR(max_ma)) - - -#define RDO_BATT(n, op_mw, max_mw, flags) \ - (RDO_OBJ_POS(n) | (flags) | \ - RDO_BATT_OP_POWER(op_mw) | \ - RDO_BATT_MAX_POWER(max_mw)) - -/* BDO : BIST Data Object */ -#define BDO_MODE_RECV (0 << 28) -#define BDO_MODE_TRANSMIT (1 << 28) -#define BDO_MODE_COUNTERS (2 << 28) -#define BDO_MODE_CARRIER0 (3 << 28) -#define BDO_MODE_CARRIER1 (4 << 28) -#define BDO_MODE_CARRIER2 (5 << 28) -#define BDO_MODE_CARRIER3 (6 << 28) -#define BDO_MODE_EYE (7 << 28) - -#define BDO(mode, cnt) ((mode) | ((cnt) & 0xFFFF)) - -#define SVID_DISCOVERY_MAX 16 - -/* Timers */ -#define PD_T_SINK_TX (18*MSEC) /* between 16ms and 20 */ -#define PD_T_CHUNK_SENDER_RSP (24*MSEC) /* between 24ms and 30ms */ -#define PD_T_CHUNK_SENDER_REQ (24*MSEC) /* between 24ms and 30ms */ -#define PD_T_SEND_SOURCE_CAP (100*MSEC) /* between 100ms and 200ms */ -#define PD_T_SINK_WAIT_CAP (600*MSEC) /* between 310ms and 620ms */ -#define PD_T_SINK_TRANSITION (35*MSEC) /* between 20ms and 35ms */ -#define PD_T_SOURCE_ACTIVITY (45*MSEC) /* between 40ms and 50ms */ -//#define PD_T_SENDER_RESPONSE (30*MSEC) /* between 24ms and 30ms */ -#define PD_T_SENDER_RESPONSE (100*MSEC) /* between 24ms and 30ms */ -#define PD_T_PS_TRANSITION (500*MSEC) /* between 450ms and 550ms */ -#define PD_T_PS_SOURCE_ON (480*MSEC) /* between 390ms and 480ms */ -#define PD_T_PS_SOURCE_OFF (920*MSEC) /* between 750ms and 920ms */ -#define PD_T_PS_HARD_RESET (25*MSEC) /* between 25ms and 35ms */ -#define PD_T_ERROR_RECOVERY (25*MSEC) /* 25ms */ -#define PD_T_CC_DEBOUNCE (100*MSEC) /* between 100ms and 200ms */ -/* DRP_SNK + DRP_SRC must be between 50ms and 100ms with 30%-70% duty cycle */ -#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_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 */ -#define PD_T_SRC_TURN_ON (275*MSEC) /* 275ms */ -#define PD_T_SAFE_0V (650*MSEC) /* 650ms */ -#define PD_T_NO_RESPONSE (5500*MSEC) /* between 4.5s and 5.5s */ -#define PD_T_BIST_TRANSMIT (50*MSEC) /* 50ms (used for task_wait arg) */ -#define PD_T_BIST_RECEIVE (60*MSEC) /* 60ms (max time to process bist) */ -#define PD_T_VCONN_SOURCE_ON (100*MSEC) /* 100ms */ -#define PD_T_TRY_SRC (125*MSEC) /* Max time for Try.SRC state */ -#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 */ - -/* number of edges and time window to detect CC line is not idle */ -#define PD_RX_TRANSITION_COUNT 3 -#define PD_RX_TRANSITION_WINDOW 20 /* between 12us and 20us */ - -/* from USB Type-C Specification Table 5-1 */ -#define PD_T_AME (1*SECOND) /* timeout from UFP attach to Alt Mode Entry */ - -/* VDM Timers ( USB PD Spec Rev2.0 Table 6-30 )*/ -#define PD_T_VDM_BUSY (100*MSEC) /* at least 100ms */ -#define PD_T_VDM_E_MODE (25*MSEC) /* enter/exit the same max */ -#define PD_T_VDM_RCVR_RSP (15*MSEC) /* max of 15ms */ -#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 */ - -/* function table for entered mode */ -struct amode_fx { - int (*status)( uint32_t *payload); - int (*config)( uint32_t *payload); -}; - -/* function table for alternate mode capable responders */ -struct svdm_response { - int (*identity)( uint32_t *payload); - int (*svids)( uint32_t *payload); - int (*modes)( uint32_t *payload); - int (*enter_mode)( uint32_t *payload); - int (*exit_mode)( uint32_t *payload); - struct amode_fx *amode; -}; - -struct svdm_svid_data { - uint16_t svid; - int mode_cnt; - uint32_t mode_vdo[PDO_MODES]; -}; - -struct svdm_amode_fx { - uint16_t svid; - int (*enter)( uint32_t mode_caps); - int (*status)( uint32_t *payload); - int (*config)( uint32_t *payload); - void (*post_config)(); - int (*attention)( uint32_t *payload); - void (*exit)(); -}; - -/* defined in /usb_pd_policy.c */ -/* All UFP_U should have */ -extern const struct svdm_response svdm_rsp; -/* All DFP_U should have */ -extern const struct svdm_amode_fx supported_modes[]; -extern const int supported_modes_cnt; - -/* DFP data needed to support alternate mode entry and exit */ -struct svdm_amode_data { - const struct svdm_amode_fx *fx; - /* VDM object position */ - int opos; - /* mode capabilities specific to SVID amode. */ - struct svdm_svid_data *data; -}; - -enum hpd_event { - hpd_none, - hpd_low, - hpd_high, - hpd_irq, -}; - -/* DisplayPort flags */ -#define DP_FLAGS_DP_ON (1 << 0) /* Display port mode is on */ -#define DP_FLAGS_HPD_HI_PENDING (1 << 1) /* Pending HPD_HI */ - -/* supported alternate modes */ -enum pd_alternate_modes { - /* not a real mode */ - PD_AMODE_COUNT, -}; - -/* Policy structure for driving alternate mode */ -struct pd_policy { - /* index of svid currently being operated on */ - int svid_idx; - /* count of svids discovered */ - int svid_cnt; - /* SVDM identity info (Id, Cert Stat, 0-4 Typec specific) */ - uint32_t identity[PDO_MAX_OBJECTS - 1]; - /* supported svids & corresponding vdo mode data */ - struct svdm_svid_data svids[SVID_DISCOVERY_MAX]; - /* active modes */ - struct svdm_amode_data amodes[PD_AMODE_COUNT]; - /* Next index to insert DFP alternate mode into amodes */ - int amode_idx; -}; - -/* - * VDO : Vendor Defined Message Object - * VDM object is minimum of VDM header + 6 additional data objects. - */ - -#define VDO_MAX_SIZE 7 - -#define VDM_VER10 0 -#define VDM_VER20 1 - -/* - * VDM header - * ---------- - * <31:16> :: SVID - * <15> :: VDM type ( 1b == structured, 0b == unstructured ) - * <14:13> :: Structured VDM version (00b == Rev 2.0, 01b == Rev 3.0 ) - * <12:11> :: reserved - * <10:8> :: object position (1-7 valid ... used for enter/exit mode only) - * <7:6> :: command type (SVDM only?) - * <5> :: reserved (SVDM), command type (UVDM) - * <4:0> :: command - */ -#define VDO(vid, type, custom) \ - (((vid) << 16) | \ - ((type) << 15) | \ - ((custom) & 0x7FFF)) - -#define VDO_SVDM_TYPE (1 << 15) -#define VDO_SVDM_VERS(x) (x << 13) -#define VDO_OPOS(x) (x << 8) -#define VDO_CMDT(x) (x << 6) -#define VDO_OPOS_MASK VDO_OPOS(0x7) -#define VDO_CMDT_MASK VDO_CMDT(0x3) - -#define CMDT_INIT 0 -#define CMDT_RSP_ACK 1 -#define CMDT_RSP_NAK 2 -#define CMDT_RSP_BUSY 3 - - -/* reserved for SVDM ... for Google UVDM */ -#define VDO_SRC_INITIATOR (0 << 5) -#define VDO_SRC_RESPONDER (1 << 5) - -#define CMD_DISCOVER_IDENT 1 -#define CMD_DISCOVER_SVID 2 -#define CMD_DISCOVER_MODES 3 -#define CMD_ENTER_MODE 4 -#define CMD_EXIT_MODE 5 -#define CMD_ATTENTION 6 -#define CMD_DP_STATUS 16 -#define CMD_DP_CONFIG 17 - -#define VDO_CMD_VENDOR(x) (((10 + (x)) & 0x1f)) - -/* ChromeOS specific commands */ -#define VDO_CMD_VERSION VDO_CMD_VENDOR(0) -#define VDO_CMD_SEND_INFO VDO_CMD_VENDOR(1) -#define VDO_CMD_READ_INFO VDO_CMD_VENDOR(2) -#define VDO_CMD_REBOOT VDO_CMD_VENDOR(5) -#define VDO_CMD_FLASH_ERASE VDO_CMD_VENDOR(6) -#define VDO_CMD_FLASH_WRITE VDO_CMD_VENDOR(7) -#define VDO_CMD_ERASE_SIG VDO_CMD_VENDOR(8) -#define VDO_CMD_PING_ENABLE VDO_CMD_VENDOR(10) -#define VDO_CMD_CURRENT VDO_CMD_VENDOR(11) -#define VDO_CMD_FLIP VDO_CMD_VENDOR(12) -#define VDO_CMD_GET_LOG VDO_CMD_VENDOR(13) -#define VDO_CMD_CCD_EN VDO_CMD_VENDOR(14) - -#define PD_VDO_VID(vdo) ((vdo) >> 16) -#define PD_VDO_SVDM(vdo) (((vdo) >> 15) & 1) -#define PD_VDO_OPOS(vdo) (((vdo) >> 8) & 0x7) -#define PD_VDO_CMD(vdo) ((vdo) & 0x1f) -#define PD_VDO_CMDT(vdo) (((vdo) >> 6) & 0x3) - -/* - * SVDM Identity request -> response - * - * Request is simply properly formatted SVDM header - * - * Response is 4 data objects: - * [0] :: SVDM header - * [1] :: Identitiy header - * [2] :: Cert Stat VDO - * [3] :: (Product | Cable) VDO - * [4] :: AMA VDO - * - */ -#define VDO_INDEX_HDR 0 -#define VDO_INDEX_IDH 1 -#define VDO_INDEX_CSTAT 2 -#define VDO_INDEX_CABLE 3 -#define VDO_INDEX_PRODUCT 3 -#define VDO_INDEX_AMA 4 -#define VDO_I(name) VDO_INDEX_##name - -/* - * SVDM Identity Header - * -------------------- - * <31> :: data capable as a USB host - * <30> :: data capable as a USB device - * <29:27> :: product type - * <26> :: modal operation supported (1b == yes) - * <25:16> :: SBZ - * <15:0> :: USB-IF assigned VID for this cable vendor - */ -#define IDH_PTYPE_UNDEF 0 -#define IDH_PTYPE_HUB 1 -#define IDH_PTYPE_PERIPH 2 -#define IDH_PTYPE_PCABLE 3 -#define IDH_PTYPE_ACABLE 4 -#define IDH_PTYPE_AMA 5 - -#define VDO_IDH(usbh, usbd, ptype, is_modal, vid) \ - ((usbh) << 31 | (usbd) << 30 | ((ptype) & 0x7) << 27 \ - | (is_modal) << 26 | ((vid) & 0xffff)) - -#define PD_IDH_PTYPE(vdo) (((vdo) >> 27) & 0x7) -#define PD_IDH_VID(vdo) ((vdo) & 0xffff) - -/* - * Cert Stat VDO - * ------------- - * <31:20> : SBZ - * <19:0> : USB-IF assigned TID for this cable - */ -#define VDO_CSTAT(tid) ((tid) & 0xfffff) -#define PD_CSTAT_TID(vdo) ((vdo) & 0xfffff) - -/* - * Product VDO - * ----------- - * <31:16> : USB Product ID - * <15:0> : USB bcdDevice - */ -#define VDO_PRODUCT(pid, bcd) (((pid) & 0xffff) << 16 | ((bcd) & 0xffff)) -#define PD_PRODUCT_PID(vdo) (((vdo) >> 16) & 0xffff) - -/* - * Cable VDO - * --------- - * <31:28> :: Cable HW version - * <27:24> :: Cable FW version - * <23:20> :: SBZ - * <19:18> :: type-C to Type-A/B/C (00b == A, 01 == B, 10 == C) - * <17> :: Type-C to Plug/Receptacle (0b == plug, 1b == receptacle) - * <16:13> :: cable latency (0001 == <10ns(~1m length)) - * <12:11> :: cable termination type (11b == both ends active VCONN req) - * <10> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable) - * <9> :: SSTX2 Directionality support - * <8> :: SSRX1 Directionality support - * <7> :: SSRX2 Directionality support - * <6:5> :: Vbus current handling capability - * <4> :: Vbus through cable (0b == no, 1b == yes) - * <3> :: SOP" controller present? (0b == no, 1b == yes) - * <2:0> :: USB SS Signaling support - */ -#define CABLE_ATYPE 0 -#define CABLE_BTYPE 1 -#define CABLE_CTYPE 2 -#define CABLE_PLUG 0 -#define CABLE_RECEPTACLE 1 -#define CABLE_CURR_1A5 0 -#define CABLE_CURR_3A 1 -#define CABLE_CURR_5A 2 -#define CABLE_USBSS_U2_ONLY 0 -#define CABLE_USBSS_U31_GEN1 1 -#define CABLE_USBSS_U31_GEN2 2 -#define VDO_CABLE(hw, fw, cbl, gdr, lat, term, tx1d, tx2d, rx1d, rx2d, cur, vps, sopp, usbss) \ - (((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 | ((cbl) & 0x3) << 18 \ - | (gdr) << 17 | ((lat) & 0x7) << 13 | ((term) & 0x3) << 11 \ - | (tx1d) << 10 | (tx2d) << 9 | (rx1d) << 8 | (rx2d) << 7 \ - | ((cur) & 0x3) << 5 | (vps) << 4 | (sopp) << 3 \ - | ((usbss) & 0x7)) - -/* - * AMA VDO - * --------- - * <31:28> :: Cable HW version - * <27:24> :: Cable FW version - * <23:12> :: SBZ - * <11> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable) - * <10> :: SSTX2 Directionality support - * <9> :: SSRX1 Directionality support - * <8> :: SSRX2 Directionality support - * <7:5> :: Vconn power - * <4> :: Vconn power required - * <3> :: Vbus power required - * <2:0> :: USB SS Signaling support - */ -#define VDO_AMA(hw, fw, tx1d, tx2d, rx1d, rx2d, vcpwr, vcr, vbr, usbss) \ - (((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 \ - | (tx1d) << 11 | (tx2d) << 10 | (rx1d) << 9 | (rx2d) << 8 \ - | ((vcpwr) & 0x3) << 5 | (vcr) << 4 | (vbr) << 3 \ - | ((usbss) & 0x7)) - -#define PD_VDO_AMA_VCONN_REQ(vdo) (((vdo) >> 4) & 1) -#define PD_VDO_AMA_VBUS_REQ(vdo) (((vdo) >> 3) & 1) - -#define AMA_VCONN_PWR_1W 0 -#define AMA_VCONN_PWR_1W5 1 -#define AMA_VCONN_PWR_2W 2 -#define AMA_VCONN_PWR_3W 3 -#define AMA_VCONN_PWR_4W 4 -#define AMA_VCONN_PWR_5W 5 -#define AMA_VCONN_PWR_6W 6 -#define AMA_USBSS_U2_ONLY 0 -#define AMA_USBSS_U31_GEN1 1 -#define AMA_USBSS_U31_GEN2 2 -#define AMA_USBSS_BBONLY 3 - -/* - * SVDM Discover SVIDs request -> response - * - * Request is properly formatted VDM Header with discover SVIDs command. - * Response is a set of SVIDs of all all supported SVIDs with all zero's to - * mark the end of SVIDs. If more than 12 SVIDs are supported command SHOULD be - * repeated. - */ -#define VDO_SVID(svid0, svid1) (((svid0) & 0xffff) << 16 | ((svid1) & 0xffff)) -#define PD_VDO_SVID_SVID0(vdo) ((vdo) >> 16) -#define PD_VDO_SVID_SVID1(vdo) ((vdo) & 0xffff) - -/* - * Google modes capabilities - * <31:8> : reserved - * <7:0> : mode - */ -#define VDO_MODE_GOOGLE(mode) (mode & 0xff) - -#define MODE_GOOGLE_FU 1 /* Firmware Update mode */ - -/* - * Mode Capabilities - * - * Number of VDOs supplied is SID dependent (but <= 6 VDOS?) - */ -#define VDO_MODE_CNT_DISPLAYPORT 1 - -/* - * DisplayPort modes capabilities - * ------------------------------- - * <31:24> : SBZ - * <23:16> : UFP_D pin assignment supported - * <15:8> : DFP_D pin assignment supported - * <7> : USB 2.0 signaling (0b=yes, 1b=no) - * <6> : Plug | Receptacle (0b == plug, 1b == receptacle) - * <5:2> : xxx1: Supports DPv1.3, xx1x Supports USB Gen 2 signaling - * Other bits are reserved. - * <1:0> : signal direction ( 00b=rsv, 01b=sink, 10b=src 11b=both ) - */ -#define VDO_MODE_DP(snkp, srcp, usb, gdr, sign, sdir) \ - (((snkp) & 0xff) << 16 | ((srcp) & 0xff) << 8 \ - | ((usb) & 1) << 7 | ((gdr) & 1) << 6 | ((sign) & 0xF) << 2 \ - | ((sdir) & 0x3)) -#define PD_DP_PIN_CAPS(x) ((((x) >> 6) & 0x1) ? (((x) >> 16) & 0x3f) \ - : (((x) >> 8) & 0x3f)) - -#define MODE_DP_PIN_A 0x01 -#define MODE_DP_PIN_B 0x02 -#define MODE_DP_PIN_C 0x04 -#define MODE_DP_PIN_D 0x08 -#define MODE_DP_PIN_E 0x10 -#define MODE_DP_PIN_F 0x20 - -/* Pin configs B/D/F support multi-function */ -#define MODE_DP_PIN_MF_MASK 0x2a -/* Pin configs A/B support BR2 signaling levels */ -#define MODE_DP_PIN_BR2_MASK 0x3 -/* Pin configs C/D/E/F support DP signaling levels */ -#define MODE_DP_PIN_DP_MASK 0x3c - -#define MODE_DP_V13 0x1 -#define MODE_DP_GEN2 0x2 - -#define MODE_DP_SNK 0x1 -#define MODE_DP_SRC 0x2 -#define MODE_DP_BOTH 0x3 - -/* - * DisplayPort Status VDO - * ---------------------- - * <31:9> : SBZ - * <8> : IRQ_HPD : 1 == irq arrived since last message otherwise 0. - * <7> : HPD state : 0 = HPD_LOW, 1 == HPD_HIGH - * <6> : Exit DP Alt mode: 0 == maintain, 1 == exit - * <5> : USB config : 0 == maintain current, 1 == switch to USB from DP - * <4> : Multi-function preference : 0 == no pref, 1 == MF preferred. - * <3> : enabled : is DPout on/off. - * <2> : power low : 0 == normal or LPM disabled, 1 == DP disabled for LPM - * <1:0> : connect status : 00b == no (DFP|UFP)_D is connected or disabled. - * 01b == DFP_D connected, 10b == UFP_D connected, 11b == both. - */ -#define VDO_DP_STATUS(irq, lvl, amode, usbc, mf, en, lp, conn) \ - (((irq) & 1) << 8 | ((lvl) & 1) << 7 | ((amode) & 1) << 6 \ - | ((usbc) & 1) << 5 | ((mf) & 1) << 4 | ((en) & 1) << 3 \ - | ((lp) & 1) << 2 | ((conn & 0x3) << 0)) - -#define PD_VDO_DPSTS_HPD_IRQ(x) (((x) >> 8) & 1) -#define PD_VDO_DPSTS_HPD_LVL(x) (((x) >> 7) & 1) -#define PD_VDO_DPSTS_MF_PREF(x) (((x) >> 4) & 1) - -/* Per DisplayPort Spec v1.3 Section 3.3 */ -#define HPD_USTREAM_DEBOUNCE_LVL (2*MSEC) -#define HPD_USTREAM_DEBOUNCE_IRQ (250) -#define HPD_DSTREAM_DEBOUNCE_IRQ (500) /* between 500-1000us */ - -/* - * DisplayPort Configure VDO - * ------------------------- - * <31:24> : SBZ - * <23:16> : SBZ - * <15:8> : Pin assignment requested. Choose one from mode caps. - * <7:6> : SBZ - * <5:2> : signalling : 1h == DP v1.3, 2h == Gen 2 - * Oh is only for USB, remaining values are reserved - * <1:0> : cfg : 00 == USB, 01 == DFP_D, 10 == UFP_D, 11 == reserved - */ -#define VDO_DP_CFG(pin, sig, cfg) \ - (((pin) & 0xff) << 8 | ((sig) & 0xf) << 2 | ((cfg) & 0x3)) - -#define PD_DP_CFG_DPON(x) (((x & 0x3) == 1) || ((x & 0x3) == 2)) -/* - * Get the pin assignment mask - * for backward compatibility, if it is null, - * get the former sink pin assignment we used to be in <23:16>. - */ -#define PD_DP_CFG_PIN(x) ((((x) >> 8) & 0xff) ? (((x) >> 8) & 0xff) \ - : (((x) >> 16) & 0xff)) -/* - * ChromeOS specific PD device Hardware IDs. Used to identify unique - * products and used in VDO_INFO. Note this field is 10 bits. - */ -#define USB_PD_HW_DEV_ID_RESERVED 0 -#define USB_PD_HW_DEV_ID_ZINGER 1 -#define USB_PD_HW_DEV_ID_MINIMUFFIN 2 -#define USB_PD_HW_DEV_ID_DINGDONG 3 -#define USB_PD_HW_DEV_ID_HOHO 4 -#define USB_PD_HW_DEV_ID_HONEYBUNS 5 - -/* - * ChromeOS specific VDO_CMD_READ_INFO responds with device info including: - * RW Hash: First 20 bytes of SHA-256 of RW (20 bytes) - * HW Device ID: unique descriptor for each ChromeOS model (2 bytes) - * top 6 bits are minor revision, bottom 10 bits are major - * SW Debug Version: Software version useful for debugging (15 bits) - * IS RW: True if currently in RW, False otherwise (1 bit) - */ -#define VDO_INFO(id, id_minor, ver, is_rw) ((id_minor) << 26 \ - | ((id) & 0x3ff) << 16 \ - | ((ver) & 0x7fff) << 1 \ - | ((is_rw) & 1)) -#define VDO_INFO_HW_DEV_ID(x) ((x) >> 16) -#define VDO_INFO_SW_DBG_VER(x) (((x) >> 1) & 0x7fff) -#define VDO_INFO_IS_RW(x) ((x) & 1) - -#define HW_DEV_ID_MAJ(x) (x & 0x3ff) -#define HW_DEV_ID_MIN(x) ((x) >> 10) - -/* USB-IF SIDs */ -#define USB_SID_PD 0xff00 /* power delivery */ -#define USB_SID_DISPLAYPORT 0xff01 - -#define USB_GOOGLE_TYPEC_URL "http://www.google.com/chrome/devices/typec" -/* USB Vendor ID assigned to Google Inc. */ -#define USB_VID_GOOGLE 0x18d1 - -/* Other Vendor IDs */ -#define USB_VID_APPLE 0x05ac - -/* Timeout for message receive in microseconds */ -#define USB_PD_RX_TMOUT_US 1800 - -/* --- Protocol layer functions --- */ - -enum pd_states { - PD_STATE_DISABLED, - PD_STATE_SUSPENDED, -#ifdef CONFIG_USB_PD_DUAL_ROLE - PD_STATE_SNK_DISCONNECTED, - PD_STATE_SNK_DISCONNECTED_DEBOUNCE, - PD_STATE_SNK_HARD_RESET_RECOVER, - PD_STATE_SNK_DISCOVERY, - PD_STATE_SNK_REQUESTED, - PD_STATE_SNK_TRANSITION, - PD_STATE_SNK_READY, - - PD_STATE_SNK_SWAP_INIT, - PD_STATE_SNK_SWAP_SNK_DISABLE, - PD_STATE_SNK_SWAP_SRC_DISABLE, - PD_STATE_SNK_SWAP_STANDBY, - PD_STATE_SNK_SWAP_COMPLETE, -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - - PD_STATE_SRC_DISCONNECTED, - PD_STATE_SRC_DISCONNECTED_DEBOUNCE, - PD_STATE_SRC_HARD_RESET_RECOVER, - PD_STATE_SRC_STARTUP, - PD_STATE_SRC_DISCOVERY, - PD_STATE_SRC_NEGOCIATE, - PD_STATE_SRC_ACCEPTED, - PD_STATE_SRC_POWERED, - PD_STATE_SRC_TRANSITION, - PD_STATE_SRC_READY, - PD_STATE_SRC_GET_SINK_CAP, - PD_STATE_DR_SWAP, - -#ifdef CONFIG_USB_PD_DUAL_ROLE - PD_STATE_SRC_SWAP_INIT, - PD_STATE_SRC_SWAP_SNK_DISABLE, - PD_STATE_SRC_SWAP_SRC_DISABLE, - PD_STATE_SRC_SWAP_STANDBY, - -#ifdef CONFIG_USBC_VCONN_SWAP - PD_STATE_VCONN_SWAP_SEND, - PD_STATE_VCONN_SWAP_INIT, - PD_STATE_VCONN_SWAP_READY, -#endif /* CONFIG_USBC_VCONN_SWAP */ -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - - PD_STATE_SOFT_RESET, - PD_STATE_HARD_RESET_SEND, - PD_STATE_HARD_RESET_EXECUTE, -#ifdef CONFIG_COMMON_RUNTIME - PD_STATE_BIST_RX, - PD_STATE_BIST_TX, -#endif - -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - PD_STATE_DRP_AUTO_TOGGLE, -#endif - /* Number of states. Not an actual state. */ - PD_STATE_COUNT, -}; - -#define PD_FLAGS_PING_ENABLED (1 << 0) /* SRC_READY pings enabled */ -#define PD_FLAGS_PARTNER_DR_POWER (1 << 1) /* port partner is dualrole power */ -#define PD_FLAGS_PARTNER_DR_DATA (1 << 2) /* port partner is dualrole data */ -#define PD_FLAGS_CHECK_IDENTITY (1 << 3) /* discover identity in READY */ -#define PD_FLAGS_SNK_CAP_RECVD (1 << 4) /* sink capabilities received */ -#define PD_FLAGS_TCPC_DRP_TOGGLE (1 << 5) /* TCPC-controlled DRP toggling */ -#define PD_FLAGS_EXPLICIT_CONTRACT (1 << 6) /* explicit pwr contract in place */ -#define PD_FLAGS_VBUS_NEVER_LOW (1 << 7) /* VBUS input has never been low */ -#define PD_FLAGS_PREVIOUS_PD_CONN (1 << 8) /* previously PD connected */ -#define PD_FLAGS_CHECK_PR_ROLE (1 << 9) /* check power role in READY */ -#define PD_FLAGS_CHECK_DR_ROLE (1 << 10)/* check data role in READY */ -#define PD_FLAGS_PARTNER_EXTPOWER (1 << 11)/* port partner has external pwr */ -#define PD_FLAGS_VCONN_ON (1 << 12)/* vconn is being sourced */ -#define PD_FLAGS_TRY_SRC (1 << 13)/* Try.SRC states are active */ -#define PD_FLAGS_PARTNER_USB_COMM (1 << 14)/* port partner is USB comms */ -#define PD_FLAGS_UPDATE_SRC_CAPS (1 << 15)/* send new source capabilities */ -#define PD_FLAGS_TS_DTS_PARTNER (1 << 16)/* partner has rp/rp or rd/rd */ -/* Flags to clear on a disconnect */ -#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \ - PD_FLAGS_PARTNER_DR_DATA | \ - PD_FLAGS_CHECK_IDENTITY | \ - PD_FLAGS_SNK_CAP_RECVD | \ - PD_FLAGS_TCPC_DRP_TOGGLE | \ - PD_FLAGS_EXPLICIT_CONTRACT | \ - PD_FLAGS_PREVIOUS_PD_CONN | \ - PD_FLAGS_CHECK_PR_ROLE | \ - PD_FLAGS_CHECK_DR_ROLE | \ - PD_FLAGS_PARTNER_EXTPOWER | \ - PD_FLAGS_VCONN_ON | \ - PD_FLAGS_TRY_SRC | \ - PD_FLAGS_PARTNER_USB_COMM | \ - PD_FLAGS_UPDATE_SRC_CAPS | \ - PD_FLAGS_TS_DTS_PARTNER) - -enum pd_cc_states { - PD_CC_NONE, - - /* From DFP perspective */ - PD_CC_NO_UFP, - PD_CC_AUDIO_ACC, - PD_CC_DEBUG_ACC, - PD_CC_UFP_ATTACHED, - - /* From UFP perspective */ - PD_CC_DFP_ATTACHED -}; - -#ifdef CONFIG_USB_PD_DUAL_ROLE -enum pd_dual_role_states { - /* While disconnected, toggle between src and sink */ - PD_DRP_TOGGLE_ON, - /* Stay in src until disconnect, then stay in sink forever */ - PD_DRP_TOGGLE_OFF, - /* Stay in current power role, don't switch. No auto-toggle support */ - PD_DRP_FREEZE, - /* Switch to sink */ - PD_DRP_FORCE_SINK, - /* Switch to source */ - PD_DRP_FORCE_SOURCE, -}; -/** - * Get dual role state - * - * @return Current dual-role state, from enum pd_dual_role_states - */ -enum pd_dual_role_states pd_get_dual_role(void); -/** - * Set dual role state, from among enum pd_dual_role_states - * - * @param state New state of dual-role port, selected from - * enum pd_dual_role_states - */ -void pd_set_dual_role(enum pd_dual_role_states state); - -/** - * Get role, from among PD_ROLE_SINK and PD_ROLE_SOURCE - * - * @param port Port number from which to get role - */ -int pd_get_role(); - -#endif - -/* Control Message type */ -enum pd_ctrl_msg_type { - /* 0 Reserved */ - PD_CTRL_GOOD_CRC = 1, - PD_CTRL_GOTO_MIN = 2, - PD_CTRL_ACCEPT = 3, - PD_CTRL_REJECT = 4, - PD_CTRL_PING = 5, - PD_CTRL_PS_RDY = 6, - PD_CTRL_GET_SOURCE_CAP = 7, - PD_CTRL_GET_SINK_CAP = 8, - PD_CTRL_DR_SWAP = 9, - PD_CTRL_PR_SWAP = 10, - PD_CTRL_VCONN_SWAP = 11, - PD_CTRL_WAIT = 12, - PD_CTRL_SOFT_RESET = 13, - /* 14-15 Reserved */ - - /* Used for REV 3.0 */ - PD_CTRL_NOT_SUPPORTED = 16, - PD_CTRL_GET_SOURCE_CAP_EXT = 17, - PD_CTRL_GET_STATUS = 18, - PD_CTRL_FR_SWAP = 19, - PD_CTRL_GET_PPS_STATUS = 20, - PD_CTRL_GET_COUNTRY_CODES = 21, - /* 22-31 Reserved */ -}; - -/* Battery Status Data Object fields for REV 3.0 */ -#define BSDO_CAP_UNKNOWN 0xffff -#define BSDO_CAP(n) (((n) & 0xffff) << 16) -#define BSDO_INVALID (1 << 8) -#define BSDO_PRESENT (1 << 9) -#define BSDO_DISCHARGING (1 << 10) -#define BSDO_IDLE (1 << 11) - -/* Get Battery Cap Message fields for REV 3.0 */ -#define BATT_CAP_REF(n) (((n) >> 16) & 0xff) - -/* Extended message type for REV 3.0 */ -enum pd_ext_msg_type { - /* 0 Reserved */ - PD_EXT_SOURCE_CAP = 1, - PD_EXT_STATUS = 2, - PD_EXT_GET_BATTERY_CAP = 3, - PD_EXT_GET_BATTERY_STATUS = 4, - PD_EXT_BATTERY_CAP = 5, - PD_EXT_GET_MANUFACTURER_INFO = 6, - PD_EXT_MANUFACTURER_INFO = 7, - PD_EXT_SECURITY_REQUEST = 8, - PD_EXT_SECURITY_RESPONSE = 9, - PD_EXT_FIRMWARE_UPDATE_REQUEST = 10, - PD_EXT_FIRMWARE_UPDATE_RESPONSE = 11, - PD_EXT_PPS_STATUS = 12, - PD_EXT_COUNTRY_INFO = 13, - PD_EXT_COUNTRY_CODES = 14, - /* 15-31 Reserved */ -}; - -/* Data message type */ -enum pd_data_msg_type { - /* 0 Reserved */ - PD_DATA_SOURCE_CAP = 1, - PD_DATA_REQUEST = 2, - PD_DATA_BIST = 3, - PD_DATA_SINK_CAP = 4, - /* 5-14 Reserved for REV 2.0 */ - PD_DATA_BATTERY_STATUS = 5, - PD_DATA_ALERT = 6, - PD_DATA_GET_COUNTRY_INFO = 7, - /* 8-14 Reserved for REV 3.0 */ - PD_DATA_VENDOR_DEF = 15, -}; - -/* Protocol revision */ -#define PD_REV10 0 -#define PD_REV20 1 -#define PD_REV30 2 - -/* Power role */ -#define PD_ROLE_SINK 0 -#define PD_ROLE_SOURCE 1 -/* Data role */ -#define PD_ROLE_UFP 0 -#define PD_ROLE_DFP 1 -/* Vconn role */ -#define PD_ROLE_VCONN_OFF 0 -#define PD_ROLE_VCONN_ON 1 - -/* chunk is a request or response in REV 3.0 */ -#define CHUNK_RESPONSE 0 -#define CHUNK_REQUEST 1 - -/* collision avoidance Rp values in REV 3.0 */ -#define SINK_TX_OK TYPEC_RP_3A0 -#define SINK_TX_NG TYPEC_RP_1A5 - -/* Port role at startup */ -#ifndef PD_ROLE_DEFAULT -#ifdef CONFIG_USB_PD_DUAL_ROLE -#define PD_ROLE_DEFAULT(port) PD_ROLE_SINK -#else -#define PD_ROLE_DEFAULT(port) PD_ROLE_SOURCE -#endif -#endif - -/* Port default state at startup */ -#ifdef CONFIG_USB_PD_DUAL_ROLE -#define PD_DEFAULT_STATE(port) ((PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE) ? \ - PD_STATE_SRC_DISCONNECTED : \ - PD_STATE_SNK_DISCONNECTED) -#else -#define PD_DEFAULT_STATE(port) PD_STATE_SRC_DISCONNECTED -#endif - -/* build extended message header */ -/* All extended messages are chunked, so set bit 15 */ -#define PD_EXT_HEADER(cnum, rchk, dsize) \ - ((1 << 15) | ((cnum) << 11) | \ - ((rchk) << 10) | (dsize)) - -/* build message header */ -#define PD_HEADER(type, prole, drole, id, cnt, rev, ext) \ - ((type) | ((rev) << 6) | \ - ((drole) << 5) | ((prole) << 8) | \ - ((id) << 9) | ((cnt) << 12) | ((ext) << 15)) - -/* Used for processing pd header */ -#define PD_HEADER_EXT(header) (((header) >> 15) & 1) -#define PD_HEADER_CNT(header) (((header) >> 12) & 7) -#define PD_HEADER_TYPE(header) ((header) & 0xF) -#define PD_HEADER_ID(header) (((header) >> 9) & 7) -#define PD_HEADER_REV(header) (((header) >> 6) & 3) - -/* Used for processing pd extended header */ -#define PD_EXT_HEADER_CHUNKED(header) (((header) >> 15) & 1) -#define PD_EXT_HEADER_CHUNK_NUM(header) (((header) >> 11) & 0xf) -#define PD_EXT_HEADER_REQ_CHUNK(header) (((header) >> 10) & 1) -#define PD_EXT_HEADER_DATA_SIZE(header) ((header) & 0x1ff) - -/* K-codes for special symbols */ -#define PD_SYNC1 0x18 -#define PD_SYNC2 0x11 -#define PD_SYNC3 0x06 -#define PD_RST1 0x07 -#define PD_RST2 0x19 -#define PD_EOP 0x0D - -/* Minimum PD supply current (mA) */ -#define PD_MIN_MA 500 - -/* Minimum PD voltage (mV) */ -#define PD_MIN_MV 5000 - -/* No connect voltage threshold for sources based on Rp */ -#define PD_SRC_DEF_VNC_MV 1600 -#define PD_SRC_1_5_VNC_MV 1600 -#define PD_SRC_3_0_VNC_MV 2600 - -/* Rd voltage threshold for sources based on Rp */ -#define PD_SRC_DEF_RD_THRESH_MV 200 -#define PD_SRC_1_5_RD_THRESH_MV 400 -#define PD_SRC_3_0_RD_THRESH_MV 800 - -/* Voltage threshold to detect connection when presenting Rd */ -#define PD_SNK_VA_MV 250 - -/* --- Policy layer functions --- */ - -/* Request types for pd_build_request() */ -enum pd_request_type { - PD_REQUEST_VSAFE5V, - PD_REQUEST_MAX, -}; - -#ifdef CONFIG_USB_PD_REV30 -/** - * Get current PD Revision - * - * @param port USB-C port number - * @return 0 for PD_REV1.0, 1 for PD_REV2.0, 2 for PD_REV3.0 - */ -int pd_get_rev(); - -/** - * Get current PD VDO Version - * - * @param port USB-C port number - * @return 0 for PD_REV1.0, 1 for PD_REV2.0 - */ -int pd_get_vdo_ver(); -#else -#define pd_get_rev(n) PD_REV20 -#define pd_get_vdo_ver(n) VDM_VER10 -#endif -/** - * Decide which PDO to choose from the source capabilities. - * - * @param port USB-C port number - * @param rdo requested Request Data Object. - * @param ma selected current limit (stored on success) - * @param mv selected supply voltage (stored on success) - * @param req_type request type - * @return <0 if invalid, else EC_SUCCESS - */ -int pd_build_request( uint32_t *rdo, uint32_t *ma, uint32_t *mv, - enum pd_request_type req_type); - -/** - * Check if max voltage request is allowed (only used if - * CONFIG_USB_PD_CHECK_MAX_REQUEST_ALLOWED is defined). - * - * @return True if max voltage request allowed, False otherwise - */ -int pd_is_max_request_allowed(void); - -/** - * Callback with source capabilities packet - * - * @param port USB-C port number - * @param cnt the number of Power Data Objects. - * @param src_caps Power Data Objects representing the source capabilities. - */ -void pd_process_source_cap_callback( int cnt, uint32_t *src_caps); - -/** - * Process source capabilities packet - * - * @param port USB-C port number - * @param cnt the number of Power Data Objects. - * @param src_caps Power Data Objects representing the source capabilities. - */ -void pd_process_source_cap( int cnt, uint32_t *src_caps); - -/** - * Find PDO index that offers the most amount of power and stays within - * max_mv voltage. - * - * @param port USB-C port number - * @param max_mv maximum voltage (or -1 if no limit) - * @param pdo raw pdo corresponding to index, or index 0 on error (output) - * @return index of PDO within source cap packet - */ -int pd_find_pdo_index( int max_mv, uint32_t *pdo); - -/** - * Extract power information out of a Power Data Object (PDO) - * - * @param pdo raw pdo to extract - * @param ma current of the PDO (output) - * @param mv voltage of the PDO (output) - */ -void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *mv); - -/** - * Reduce the sink power consumption to a minimum value. - * - * @param port USB-C port number - * @param ma reduce current to minimum value. - * @param mv reduce voltage to minimum value. - */ -void pd_snk_give_back( uint32_t * const ma, uint32_t * const mv); - -/** - * Put a cap on the max voltage requested as a sink. - * @param mv maximum voltage in millivolts. - */ -void pd_set_max_voltage(unsigned mv); - -/** - * Get the max voltage that can be requested as set by pd_set_max_voltage(). - * @return max voltage - */ -unsigned pd_get_max_voltage(void); - -/** - * Check if this board supports the given input voltage. - * - * @mv input voltage - * @return 1 if voltage supported, 0 if not - */ -int pd_is_valid_input_voltage(int mv); - -/** - * Request a new operating voltage. - * - * @param rdo Request Data Object with the selected operating point. - * @param port The port which the request came in on. - * @return EC_SUCCESS if we can get the requested voltage/OP, <0 else. - */ -int pd_check_requested_voltage(uint32_t rdo, const int port); - -/** - * Run board specific checks on request message - * - * @param rdo the request data object word sent by the sink. - * @param pdo_cnt the total number of source PDOs. - * @return EC_SUCCESS if request is ok , <0 else. - */ -int pd_board_check_request(uint32_t rdo, int pdo_cnt); - -/** - * Select a new output voltage. - * - * param idx index of the new voltage in the source PDO table. - */ -void pd_transition_voltage(int idx); - -/** - * Go back to the default/safe state of the power supply - * - * @param port USB-C port number - */ -void pd_power_supply_reset(); - -/** - * Enable or disable VBUS discharge for a given port. - * - * @param port USB-C port number - * @enable 1 if enabling discharge, 0 if disabling - */ -void pd_set_vbus_discharge( int enable); - -/** - * Enable the power supply output after the ready delay. - * - * @param port USB-C port number - * @return EC_SUCCESS if the power supply is ready, <0 else. - */ -int pd_set_power_supply_ready(); - -/** - * Ask the specified voltage from the PD source. - * - * It triggers a new negotiation sequence with the source. - * @param port USB-C port number - * @param mv request voltage in millivolts. - */ -void pd_request_source_voltage( int mv); - -/** - * Set a voltage limit from the PD source. - * - * If the source is currently active, it triggers a new negotiation. - * @param port USB-C port number - * @param mv limit voltage in millivolts. - */ -void pd_set_external_voltage_limit( int mv); - -/** - * Set the PD input current limit. - * - * @param port USB-C port number - * @param max_ma Maximum current limit - * @param supply_voltage Voltage at which current limit is applied - */ -void pd_set_input_current_limit( uint32_t max_ma, - uint32_t supply_voltage); - - -/** - * Update the power contract if it exists. - * - * @param port USB-C port number. - */ -void pd_update_contract(); - -/* Encode DTS status of port partner in current limit parameter */ -typedef uint32_t typec_current_t; -#define TYPEC_CURRENT_DTS_MASK (1 << 31) -#define TYPEC_CURRENT_ILIM_MASK (~TYPEC_CURRENT_DTS_MASK) - -/** - * Set the type-C input current limit. - * - * @param port USB-C port number - * @param max_ma Maximum current limit - * @param supply_voltage Voltage at which current limit is applied - */ -void typec_set_input_current_limit( typec_current_t max_ma, - uint32_t supply_voltage); - -/** - * Set the type-C current limit when sourcing current.. - * - * @param port USB-C port number - * @param rp One of enum tcpc_rp_value (eg TYPEC_RP_3A0) defining the limit. - */ -void typec_set_source_current_limit( int rp); - -/** - * Verify board specific health status : current, voltages... - * - * @return EC_SUCCESS if the board is good, <0 else. - */ -int pd_board_checks(void); - -/** - * Return if VBUS is detected on type-C port - * - * @param port USB-C port number - * @return VBUS is detected - */ -int pd_snk_is_vbus_provided(); - -/** - * Notify PD protocol that VBUS has gone low - * - * @param port USB-C port number - */ -void pd_vbus_low(); - -/** - * Check if power swap is allowed. - * - * @param port USB-C port number - * @return True if power swap is allowed, False otherwise - */ -int pd_check_power_swap(); - -/** - * Check if data swap is allowed. - * - * @param port USB-C port number - * @param data_role current data role - * @return True if data swap is allowed, False otherwise - */ -int pd_check_data_swap( int data_role); - -/** - * Check if vconn swap is allowed. - * - * @param port USB-C port number - * @return True if vconn swap is allowed, False otherwise - */ - -int pd_check_vconn_swap(); - -/** - * Check current power role for potential power swap - * - * @param port USB-C port number - * @param pr_role Our power role - * @param flags PD flags - */ -void pd_check_pr_role( int pr_role, int flags); - -/** - * Check current data role for potential data swap - * - * @param port USB-C port number - * @param dr_role Our data role - * @param flags PD flags - */ -void pd_check_dr_role( int dr_role, int flags); - -/** - * Check if we should charge from this device. This is - * basically a white-list for chargers that are dual-role, - * don't set the externally powered bit, but we should charge - * from by default. - * - * @param vid Port partner Vendor ID - * @param pid Port partner Product ID - */ -int pd_charge_from_device(uint16_t vid, uint16_t pid); - -/** - * Execute data swap. - * - * @param port USB-C port number - * @param data_role new data role - */ -void pd_execute_data_swap( int data_role); - -/** - * Get PD device info used for VDO_CMD_SEND_INFO / VDO_CMD_READ_INFO - * - * @param info_data pointer to info data array - */ -void pd_get_info(uint32_t *info_data); - -/** - * Handle Vendor Defined Messages - * - * @param port USB-C port number - * @param cnt number of data objects in the payload. - * @param payload payload data. - * @param rpayload pointer to the data to send back. - * @return if >0, number of VDOs to send back. - */ -int pd_custom_vdm( int cnt, uint32_t *payload, uint32_t **rpayload); - -/** - * Handle Structured Vendor Defined Messages - * - * @param port USB-C port number - * @param cnt number of data objects in the payload. - * @param payload payload data. - * @param rpayload pointer to the data to send back. - * @return if >0, number of VDOs to send back. - */ -int pd_svdm( int cnt, uint32_t *payload, uint32_t **rpayload); - -/** - * Handle Custom VDMs for flashing. - * - * @param port USB-C port number - * @param cnt number of data objects in the payload. - * @param payload payload data. - * @return if >0, number of VDOs to send back. - */ -int pd_custom_flash_vdm( int cnt, uint32_t *payload); - -/** - * Enter alternate mode on DFP - * - * @param port USB-C port number - * @param svid USB standard or vendor id to exit or zero for DFP amode reset. - * @param opos object position of mode to exit. - * @return vdm for UFP to be sent to enter mode or zero if not. - */ -uint32_t pd_dfp_enter_mode( uint16_t svid, int opos); - -/** - * Get DisplayPort pin mode for DFP to request from UFP's capabilities. - * - * @param port USB-C port number. - * @param status DisplayPort Status VDO. - * @return one-hot PIN config to request. - */ -int pd_dfp_dp_get_pin_mode( uint32_t status); - -/** - * Exit alternate mode on DFP - * - * @param port USB-C port number - * @param svid USB standard or vendor id to exit or zero for DFP amode reset. - * @param opos object position of mode to exit. - * @return 1 if UFP should be sent exit mode VDM. - */ -int pd_dfp_exit_mode( uint16_t svid, int opos); - -/** - * Initialize policy engine for DFP - * - * @param port USB-C port number - */ -void pd_dfp_pe_init(); - -/** - * Return the VID of the USB PD accessory connected to a specified port - * - * @param port USB-C port number - * @return the USB Vendor Identifier or 0 if it doesn't exist - */ -uint16_t pd_get_identity_vid(); - -/** - * Return the PID of the USB PD accessory connected to a specified port - * - * @param port USB-C port number - * @return the USB Product Identifier or 0 if it doesn't exist - */ -uint16_t pd_get_identity_pid(); - -/** - * Store Device ID & RW hash of device - * - * @param port USB-C port number - * @param dev_id device identifier - * @param rw_hash pointer to rw_hash - * @param current_image current image: RW or RO - * @return true if the dev / hash match an existing hash - * in our table, false otherwise - */ -int pd_dev_store_rw_hash( uint16_t dev_id, uint32_t *rw_hash, - uint32_t ec_current_image); - -/** - * Try to fetch one PD log entry from accessory - * - * @param port USB-C accessory port number - * @return EC_RES_SUCCESS if the VDM was sent properly else error code - */ -int pd_fetch_acc_log_entry(); - -/** - * Analyze the log entry received as the VDO_CMD_GET_LOG payload. - * - * @param port USB-C accessory port number - * @param cnt number of data objects in payload - * @param payload payload data - */ -void pd_log_recv_vdm( int cnt, uint32_t *payload); - -/** - * Send Vendor Defined Message - * - * @param port USB-C port number - * @param vid Vendor ID - * @param cmd VDO command number - * @param data Pointer to payload to send - * @param count number of data objects in payload - */ -void pd_send_vdm( uint32_t vid, int cmd, const uint32_t *data, - int count); - -/* Power Data Objects for the source and the sink */ -extern const uint32_t pd_src_pdo[]; -extern const int pd_src_pdo_cnt; -extern const uint32_t pd_src_pdo_max[]; -extern const int pd_src_pdo_max_cnt; -extern const uint32_t pd_snk_pdo[]; -extern const int pd_snk_pdo_cnt; - -/** - * Request that a host event be sent to notify the AP of a PD power event. - * - * @param mask host event mask. - */ -#if defined(HAS_TASK_HOSTCMD) && !defined(TEST_BUILD) -void pd_send_host_event(int mask); -#else -static inline void pd_send_host_event(int mask) { } -#endif - -/** - * Determine if in alternate mode or not. - * - * @param port port number. - * @param svid USB standard or vendor id - * @return object position of mode chosen in alternate mode otherwise zero. - */ -int pd_alt_mode( uint16_t svid); - -/** - * Send hpd over USB PD. - * - * @param port port number. - * @param hpd hotplug detect type. - */ -void pd_send_hpd( enum hpd_event hpd); - -/** - * Enable USB Billboard Device. - */ -extern const struct deferred_data pd_usb_billboard_deferred_data; -/* --- Physical layer functions : chip specific --- */ - -/* Packet preparation/retrieval */ - -/** - * Prepare packet reading state machine. - * - * @param port USB-C port number - */ -void pd_init_dequeue(); - -/** - * Prepare packet reading state machine. - * - * @param port USB-C port number - * @param off current position in the packet buffer. - * @param len minimum size to read in bits. - * @param val the read bits. - * @return new position in the packet buffer. - */ -int pd_dequeue_bits( int off, int len, uint32_t *val); - -/** - * Advance until the end of the preamble. - * - * @param port USB-C port number - * @return new position in the packet buffer. - */ -int pd_find_preamble(); - -/** - * Write the preamble in the TX buffer. - * - * @param port USB-C port number - * @return new position in the packet buffer. - */ -int pd_write_preamble(); - -/** - * Write one 10-period symbol in the TX packet. - * corresponding to a quartet with 4b5b encoding - * and Biphase Mark Coding. - * - * @param port USB-C port number - * @param bit_off current position in the packet buffer. - * @param val10 the 10-bit integer. - * @return new position in the packet buffer. - */ -int pd_write_sym( int bit_off, uint32_t val10); - - -/** - * Ensure that we have an edge after EOP and we end up at level 0, - * also fill the last byte. - * - * @param port USB-C port number - * @param bit_off current position in the packet buffer. - * @return new position in the packet buffer. - */ -int pd_write_last_edge( int bit_off); - -/** - * Do 4B5B encoding on a 32-bit word. - * - * @param port USB-C port number - * @param off current offset in bits inside the message - * @param val32 32-bit word value to encode - * @return new offset in the message in bits. - */ -int encode_word( int off, uint32_t val32); - -/** - * Ensure that we have an edge after EOP and we end up at level 0, - * also fill the last byte. - * - * @param port USB-C port number - * @param header PD packet header - * @param cnt number of payload words - * @param data payload content - * @return length of the message in bits. - */ -int prepare_message( uint16_t header, uint8_t cnt, - const uint32_t *data); - -/** - * Dump the current PD packet on the console for debug. - * - * @param port USB-C port number - * @param msg context string. - */ -void pd_dump_packet( const char *msg); - -/** - * Change the TX data clock frequency. - * - * @param port USB-C port number - * @param freq frequency in hertz. - */ -void pd_set_clock( int freq); - -/* TX/RX callbacks */ - -/** - * Start sending over the wire the prepared packet. - * - * @param port USB-C port number - * @param polarity plug polarity (0=CC1, 1=CC2). - * @param bit_len size of the packet in bits. - * @return length transmitted or negative if error - */ -int pd_start_tx( int polarity, int bit_len); - -/** - * Set PD TX DMA to use circular mode. Call this before pd_start_tx() to - * continually loop over the transmit buffer given in pd_start_tx(). - * - * @param port USB-C port number - */ -void pd_tx_set_circular_mode(); - -/** - * Stop PD TX DMA circular mode transaction already in progress. - * - * @param port USB-C port number - */ -void pd_tx_clear_circular_mode(); - -/** - * Call when we are done sending a packet. - * - * @param port USB-C port number - * @param polarity plug polarity (0=CC1, 1=CC2). - */ -void pd_tx_done( int polarity); - -/** - * Check whether the PD reception is started. - * - * @param port USB-C port number - * @return true if the reception is on-going. - */ -int pd_rx_started(); - -/** - * Suspend the PD task. - * @param port USB-C port number - * @param enable pass 0 to resume, anything else to suspend - */ -void pd_set_suspend( int enable); - -/** - * Check if the port has been initialized and PD task has not been - * suspended. - * - * @param port USB-C port number - * @return true if the PD task is not suspended. - */ -int pd_is_port_enabled(); - -/* Callback when the hardware has detected an incoming packet */ -void pd_rx_event(); -/* Start sampling the CC line for reception */ -void pd_rx_start(); -/* Call when we are done reading a packet */ -void pd_rx_complete(); - -/* restart listening to the CC wire */ -void pd_rx_enable_monitoring(); -/* stop listening to the CC wire during transmissions */ -void pd_rx_disable_monitoring(); - -/* get time since last RX edge interrupt */ -uint64_t get_time_since_last_edge(); - -/** - * Deinitialize the hardware used for PD. - * - * @param port USB-C port number - */ -void pd_hw_release(); - -/** - * Initialize the hardware used for PD RX/TX. - * - * @param port USB-C port number - * @param role Role to initialize pins in - */ -void pd_hw_init( int role); - -/** - * Initialize the reception side of hardware used for PD. - * - * This is a subset of pd_hw_init() including only : - * the comparators + the RX edge delay timer + the RX DMA. - * - * @param port USB-C port number - */ -void pd_hw_init_rx(); - -/** - * Initialize the Power Delivery state machine - */ -void pd_init(); - -/** - * Run the state machine. This function must be called regularly - * to iterate through the state machine. It uses get_time() to - * determine what actions to take each call. - */ -void pd_run_state_machine(); - -/* --- Protocol layer functions --- */ - -/** - * Decode a raw packet in the RX buffer. - * - * @param port USB-C port number - * @param payload buffer to store the packet payload (must be 7x 32-bit) - * @return the packet header or <0 in case of error - */ -int pd_analyze_rx( uint32_t *payload); - -/** - * Check if PD communication is enabled - * - * @return true if it's enabled or false otherwise - */ -int pd_comm_is_enabled(); - -/** - * Get connected state - * - * @param port USB-C port number - * @return True if port is in connected state - */ -int pd_is_connected(); - -/** - * Execute a hard reset - * - * @param port USB-C port number - */ -void pd_execute_hard_reset(); - -/** - * Signal to protocol layer that PD transmit is complete - * - * @param port USB-C port number - * @param status status of the transmission - */ -void pd_transmit_complete( int status); - -/** - * Get port polarity. - * - * @param port USB-C port number - */ -int pd_get_polarity(); - -/** - * Get port partner data swap capable status - * - * @param port USB-C port number - */ -int pd_get_partner_data_swap_capable(); - -/** - * Request power swap command to be issued - * - * @param port USB-C port number - */ -void pd_request_power_swap(); - -/** - * Try to become the VCONN source, if we are not already the source and the - * other side is willing to accept a VCONN swap. - * - * @param port USB-C port number - */ -void pd_try_vconn_src(); - -/** - * Request data swap command to be issued - * - * @param port USB-C port number - */ -void pd_request_data_swap(); - -/** - * Set the PD communication enabled flag. When communication is disabled, - * the port can still detect connection and source power but will not - * send or respond to any PD communication. - * - * @param port USB-C port number - * @param enable Enable flag to set - */ -void pd_comm_enable( int enable); - -/** - * Set the PD pings enabled flag. When source has negotiated power over - * PD successfully, it can optionally send pings periodically based on - * this enable flag. - * - * @param port USB-C port number - * @param enable Enable flag to set - */ -void pd_ping_enable( int enable); - -/* Issue PD soft reset */ -void pd_soft_reset(void); - -/* Prepare PD communication for reset */ -void pd_prepare_reset(void); - -/** - * Signal power request to indicate a charger update that affects the port. - * - * @param port USB-C port number - */ -void pd_set_new_power_request(); - -/** - * Return true if partner port is a DTS or TS capable of entering debug - * mode (eg. is presenting Rp/Rp or Rd/Rd). - * - * @param port USB-C port number - */ -int pd_ts_dts_plugged(); - -/* ----- Logging ----- */ -#ifdef CONFIG_USB_PD_LOGGING -/** - * Record one event in the PD logging FIFO. - * - * @param type event type as defined by PD_EVENT_xx in ec_commands.h - * @param size_port payload size and port num (defined by PD_LOG_PORT_SIZE) - * @param data type-defined information - * @param payload pointer to the optional payload (0..16 bytes) - */ -void pd_log_event(uint8_t type, uint8_t size_port, - uint16_t data, void *payload); - -/** - * Retrieve one logged event and prepare a VDM with it. - * - * Used to answer the VDO_CMD_GET_LOG unstructured VDM. - * - * @param payload pointer to the payload data buffer (must be 7 words) - * @return number of 32-bit words in the VDM payload. - */ -int pd_vdm_get_log_entry(uint32_t *payload); -#else /* CONFIG_USB_PD_LOGGING */ -static inline void pd_log_event(uint8_t type, uint8_t size_port, - uint16_t data, void *payload) {} -static inline int pd_vdm_get_log_entry(uint32_t *payload) { return 0; } -#endif /* CONFIG_USB_PD_LOGGING */ - -#endif /* __CROS_EC_USB_PD_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.cpp b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.cpp deleted file mode 100644 index d70f7c3c..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_policy.cpp +++ /dev/null @@ -1,882 +0,0 @@ -/* Copyright (c) 2014 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 "USBC_TCPM/tcpm.h" -#include "usb_pd.h" -#include -#ifdef CONFIG_COMMON_RUNTIME -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#else -#define CPRINTS(format, args...) -#define CPRINTF(format, args...) -#endif - -static int rw_flash_changed = 1; - -int pd_check_requested_voltage(uint32_t rdo, const int port) { - //No source - return EC_ERROR_INVAL; -} - -#ifdef CONFIG_USB_PD_DUAL_ROLE -/* Last received source cap */ -static uint32_t pd_src_caps[PDO_MAX_OBJECTS]; -static uint8_t pd_src_cap_cnt; - -/* Cap on the max voltage requested as a sink (in millivolts) */ -static unsigned max_request_mv = PD_MAX_VOLTAGE_MV; /* no cap */ - -int pd_find_pdo_index(int max_mv, uint32_t *selected_pdo) { - int i, uw, mv, ma; - int ret = 0; - int __attribute__((unused)) cur_mv = 0; - int cur_uw = 0; - int prefer_cur; - const uint32_t *src_caps = pd_src_caps; - - /* max voltage is always limited by this boards max request */ - max_mv = MIN(max_mv, PD_MAX_VOLTAGE_MV); - - /* Get max power that is under our max voltage input */ - for (i = 0; i < pd_src_cap_cnt; i++) { - /* its an unsupported Augmented PDO (PD3.0) */ - if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) - continue; - - mv = ((src_caps[i] >> 10) & 0x3FF) * 50; - /* Skip invalid voltage */ - if (!mv) - continue; - /* Skip any voltage not supported by this board */ - if (!pd_is_valid_input_voltage(mv)) - continue; - - if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { - uw = 250000 * (src_caps[i] & 0x3FF); - } else { - ma = (src_caps[i] & 0x3FF) * 10; - ma = MIN(ma, PD_MAX_CURRENT_MA); - uw = ma * mv; - } - - if (mv > max_mv) - continue; - uw = MIN(uw, PD_MAX_POWER_MW * 1000); - prefer_cur = 0; - - /* Apply special rules in case of 'tie' */ -#ifdef PD_PREFER_LOW_VOLTAGE - if (uw == cur_uw && mv < cur_mv) - prefer_cur = 1; -#elif defined(PD_PREFER_HIGH_VOLTAGE) - if (uw == cur_uw && mv > cur_mv) - prefer_cur = 1; -#endif - /* Prefer higher power, except for tiebreaker */ - if (uw > cur_uw || prefer_cur) { - ret = i; - cur_uw = uw; - cur_mv = mv; - } - } - - if (selected_pdo) - *selected_pdo = src_caps[ret]; - - return ret; -} - -void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *mv) { - int max_ma, uw; - - *mv = ((pdo >> 10) & 0x3FF) * 50; - - if (*mv == 0) { - CPRINTF("ERR:PDO mv=0\n"); - *ma = 0; - return; - } - - if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { - uw = 250000 * (pdo & 0x3FF); - max_ma = 1000 * MIN(1000 * uw, PD_MAX_POWER_MW) / *mv; - } else { - max_ma = 10 * (pdo & 0x3FF); - max_ma = MIN(max_ma, PD_MAX_POWER_MW * 1000 / *mv); - } - - *ma = MIN(max_ma, PD_MAX_CURRENT_MA); -} - -int pd_build_request(uint32_t *rdo, uint32_t *ma, uint32_t *mv, - enum pd_request_type req_type) { - uint32_t pdo; - int pdo_index, flags = 0; - int uw; - int max_or_min_ma; - int max_or_min_mw; - - if (req_type == PD_REQUEST_VSAFE5V) { - /* src cap 0 should be vSafe5V */ - pdo_index = 0; - pdo = pd_src_caps[0]; - } else { - /* find pdo index for max voltage we can request */ - pdo_index = pd_find_pdo_index(max_request_mv, &pdo); - } - - pd_extract_pdo_power(pdo, ma, mv); - uw = *ma * *mv; - /* Mismatch bit set if less power offered than the operating power */ - if (uw < (1000 * PD_OPERATING_POWER_MW)) - flags |= RDO_CAP_MISMATCH; - -#ifdef CONFIG_USB_PD_GIVE_BACK - /* Tell source we are give back capable. */ - flags |= RDO_GIVE_BACK; - - /* - * BATTERY PDO: Inform the source that the sink will reduce - * power to this minimum level on receipt of a GotoMin Request. - */ - max_or_min_mw = PD_MIN_POWER_MW; - - /* - * FIXED or VARIABLE PDO: Inform the source that the sink will reduce - * current to this minimum level on receipt of a GotoMin Request. - */ - max_or_min_ma = PD_MIN_CURRENT_MA; -#else - /* - * Can't give back, so set maximum current and power to operating - * level. - */ - max_or_min_ma = *ma; - max_or_min_mw = uw / 1000; -#endif - - if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { - int mw = uw / 1000; - *rdo = RDO_BATT(pdo_index + 1, mw, max_or_min_mw, flags); - } else { - *rdo = RDO_FIXED(pdo_index + 1, *ma, max_or_min_ma, flags); - } - return EC_SUCCESS; -} - -void pd_process_source_cap(int cnt, uint32_t *src_caps) { -#ifdef CONFIG_CHARGE_MANAGER - uint32_t ma, mv, pdo; -#endif - int i; - - pd_src_cap_cnt = cnt; - for (i = 0; i < cnt; i++) - pd_src_caps[i] = *src_caps++; - -#ifdef CONFIG_CHARGE_MANAGER - /* Get max power info that we could request */ - pd_find_pdo_index( PD_MAX_VOLTAGE_MV, &pdo); - pd_extract_pdo_power(pdo, &ma, &mv); - - /* Set max. limit, but apply 500mA ceiling */ - //charge_manager_set_ceil( CEIL_REQUESTOR_PD, PD_MIN_MA); - pd_set_input_current_limit(ma, mv); -#endif -} - -#pragma weak pd_process_source_cap_callback -void pd_process_source_cap_callback(int cnt, uint32_t *src_caps) { -} - -void pd_set_max_voltage(unsigned mv) { - max_request_mv = mv; -} - -unsigned pd_get_max_voltage(void) { - return max_request_mv; -} - -int pd_charge_from_device(uint16_t vid, uint16_t pid) { - /* TODO: rewrite into table if we get more of these */ - /* - * White-list Apple charge-through accessory since it doesn't set - * externally powered bit, but we still need to charge from it when - * we are a sink. - */ - return (vid == USB_VID_APPLE && (pid == 0x1012 || pid == 0x1013)); -} -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - -#ifdef CONFIG_USB_PD_ALT_MODE - -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - -static struct pd_policy pe[CONFIG_USB_PD_PORT_COUNT]; - -void pd_dfp_pe_init(int port) -{ - memset(&pe, 0, sizeof(struct pd_policy)); -} - -static void dfp_consume_identity( int cnt, uint32_t *payload) -{ - int ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]); - size_t identity_size = MIN(sizeof(pe.identity), - (cnt - 1) * sizeof(uint32_t)); - pd_dfp_pe_init(port); - memcpy(&pe.identity, payload + 1, identity_size); - switch (ptype) { - case IDH_PTYPE_AMA: - /* TODO(tbroch) do I disable VBUS here if power contract - * requested it - */ - if (!PD_VDO_AMA_VBUS_REQ(payload[VDO_I(AMA)])) - pd_power_supply_reset(port); - -#if defined(CONFIG_USB_PD_DUAL_ROLE) && defined(CONFIG_USBC_VCONN_SWAP) - /* Adapter is requesting vconn, try to supply it */ - if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)])) - pd_try_vconn_src(port); -#endif - break; - default: - break; - } -} - -static int dfp_discover_svids( uint32_t *payload) -{ - payload[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID); - return 1; -} - -static void dfp_consume_svids( uint32_t *payload) -{ - int i; - uint32_t *ptr = payload + 1; - uint16_t svid0, svid1; - - for (i = pe.svid_cnt; i < pe.svid_cnt + 12; i += 2) { - if (i == SVID_DISCOVERY_MAX) { - CPRINTF("ERR:SVIDCNT\n"); - break; - } - - svid0 = PD_VDO_SVID_SVID0(*ptr); - if (!svid0) - break; - pe.svids[i].svid = svid0; - pe.svid_cnt++; - - svid1 = PD_VDO_SVID_SVID1(*ptr); - if (!svid1) - break; - pe.svids[i + 1].svid = svid1; - pe.svid_cnt++; - ptr++; - } - /* TODO(tbroch) need to re-issue discover svids if > 12 */ - if (i && ((i % 12) == 0)) - CPRINTF("ERR:SVID+12\n"); -} - -static int dfp_discover_modes( uint32_t *payload) -{ - uint16_t svid = pe.svids[pe.svid_idx].svid; - if (pe.svid_idx >= pe.svid_cnt) - return 0; - payload[0] = VDO(svid, 1, CMD_DISCOVER_MODES); - return 1; -} - -static void dfp_consume_modes( int cnt, uint32_t *payload) -{ - int idx = pe.svid_idx; - pe.svids[idx].mode_cnt = cnt - 1; - if (pe.svids[idx].mode_cnt < 0) { - CPRINTF("ERR:NOMODE\n"); - } else { - memcpy(pe.svids[pe.svid_idx].mode_vdo, &payload[1], - sizeof(uint32_t) * pe.svids[idx].mode_cnt); - } - - pe.svid_idx++; -} - -static int get_mode_idx( uint16_t svid) -{ - int i; - - for (i = 0; i < PD_AMODE_COUNT; i++) { - if (pe.amodes[i].fx->svid == svid) - return i; - } - return -1; -} - -static struct svdm_amode_data *get_modep( uint16_t svid) -{ - int idx = get_mode_idx( svid); - - return (idx == -1) ? NULL : &pe.amodes[idx]; -} - -int pd_alt_mode( uint16_t svid) -{ - struct svdm_amode_data *modep = get_modep( svid); - - return (modep) ? modep->opos : -1; -} - -int allocate_mode( uint16_t svid) -{ - int i, j; - struct svdm_amode_data *modep; - int mode_idx = get_mode_idx( svid); - - if (mode_idx != -1) - return mode_idx; - - /* There's no space to enter another mode */ - if (pe.amode_idx == PD_AMODE_COUNT) { - CPRINTF("ERR:NO AMODE SPACE\n"); - return -1; - } - - /* Allocate ... if SVID == 0 enter default supported policy */ - for (i = 0; i < supported_modes_cnt; i++) { - if (!&supported_modes[i]) - continue; - - for (j = 0; j < pe.svid_cnt; j++) { - struct svdm_svid_data *svidp = &pe.svids[j]; - if ((svidp->svid != supported_modes[i].svid) || - (svid && (svidp->svid != svid))) - continue; - - modep = &pe.amodes[pe.amode_idx]; - modep->fx = &supported_modes[i]; - modep->data = &pe.svids[j]; - pe.amode_idx++; - return pe.amode_idx - 1; - } - } - return -1; -} - -/* - * Enter default mode ( payload[0] == 0 ) or attempt to enter mode via svid & - * opos -*/ -uint32_t pd_dfp_enter_mode( uint16_t svid, int opos) -{ - int mode_idx = allocate_mode( svid); - struct svdm_amode_data *modep; - uint32_t mode_caps; - - if (mode_idx == -1) - return 0; - modep = &pe.amodes[mode_idx]; - - if (!opos) { - /* choose the lowest as default */ - modep->opos = 1; - } else if (opos <= modep->data->mode_cnt) { - modep->opos = opos; - } else { - CPRINTF("opos error\n"); - return 0; - } - - mode_caps = modep->data->mode_vdo[modep->opos - 1]; - if (modep->fx->enter( mode_caps) == -1) - return 0; - - /* SVDM to send to UFP for mode entry */ - return VDO(modep->fx->svid, 1, CMD_ENTER_MODE | VDO_OPOS(modep->opos)); -} - -static int validate_mode_request(struct svdm_amode_data *modep, - uint16_t svid, int opos) -{ - if (!modep->fx) - return 0; - - if (svid != modep->fx->svid) { - CPRINTF("ERR:svid r:0x%04x != c:0x%04x\n", - svid, modep->fx->svid); - return 0; - } - - if (opos != modep->opos) { - CPRINTF("ERR:opos r:%d != c:%d\n", - opos, modep->opos); - return 0; - } - - return 1; -} - -static void dfp_consume_attention( uint32_t *payload) -{ - uint16_t svid = PD_VDO_VID(payload[0]); - int opos = PD_VDO_OPOS(payload[0]); - struct svdm_amode_data *modep = get_modep( svid); - - if (!modep || !validate_mode_request(modep, svid, opos)) - return; - - if (modep->fx->attention) - modep->fx->attention( payload); -} - -/* - * This algorithm defaults to choosing higher pin config over lower ones in - * order to prefer multi-function if desired. - * - * NAME | SIGNALING | OUTPUT TYPE | MULTI-FUNCTION | PIN CONFIG - * ------------------------------------------------------------- - * A | USB G2 | ? | no | 00_0001 - * B | USB G2 | ? | yes | 00_0010 - * C | DP | CONVERTED | no | 00_0100 - * D | PD | CONVERTED | yes | 00_1000 - * E | DP | DP | no | 01_0000 - * F | PD | DP | yes | 10_0000 - * - * if UFP has NOT asserted multi-function preferred code masks away B/D/F - * leaving only A/C/E. For single-output dongles that should leave only one - * possible pin config depending on whether its a converter DP->(VGA|HDMI) or DP - * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C - * receptacle must always choose C/D in those cases. - */ -int pd_dfp_dp_get_pin_mode( uint32_t status) -{ - struct svdm_amode_data *modep = get_modep( USB_SID_DISPLAYPORT); - uint32_t mode_caps; - uint32_t pin_caps; - if (!modep) - return 0; - - mode_caps = modep->data->mode_vdo[modep->opos - 1]; - - /* TODO(crosbug.com/p/39656) revisit with DFP that can be a sink */ - pin_caps = PD_DP_PIN_CAPS(mode_caps); - - /* if don't want multi-function then ignore those pin configs */ - if (!PD_VDO_DPSTS_MF_PREF(status)) - pin_caps &= ~MODE_DP_PIN_MF_MASK; - - /* TODO(crosbug.com/p/39656) revisit if DFP drives USB Gen 2 signals */ - pin_caps &= ~MODE_DP_PIN_BR2_MASK; - - /* if C/D present they have precedence over E/F for USB-C->USB-C */ - if (pin_caps & (MODE_DP_PIN_C | MODE_DP_PIN_D)) - pin_caps &= ~(MODE_DP_PIN_E | MODE_DP_PIN_F); - - /* get_next_bit returns undefined for zero */ - if (!pin_caps) - return 0; - - return 1 << get_next_bit(&pin_caps); -} - -int pd_dfp_exit_mode( uint16_t svid, int opos) -{ - struct svdm_amode_data *modep; - int idx; - - /* - * Empty svid signals we should reset DFP VDM state by exiting all - * entered modes then clearing state. This occurs when we've - * disconnected or for hard reset. - */ - if (!svid) { - for (idx = 0; idx < PD_AMODE_COUNT; idx++) - if (pe.amodes[idx].fx) - pe.amodes[idx].fx->exit(port); - - pd_dfp_pe_init(port); - return 0; - } - - /* - * TODO(crosbug.com/p/33946) : below needs revisited to allow multiple - * mode exit. Additionally it should honor OPOS == 7 as DFP's request - * to exit all modes. We currently don't have any UFPs that support - * multiple modes on one SVID. - */ - modep = get_modep( svid); - if (!modep || !validate_mode_request(modep, svid, opos)) - return 0; - - /* call DFPs exit function */ - modep->fx->exit(port); - /* exit the mode */ - modep->opos = 0; - return 1; -} - -uint16_t pd_get_identity_vid(int port) -{ - return PD_IDH_VID(pe.identity[0]); -} - -uint16_t pd_get_identity_pid(int port) -{ - return PD_PRODUCT_PID(pe.identity[2]); -} - -#ifdef CONFIG_CMD_USB_PD_PE -static void dump_pe(int port) -{ - const char * const idh_ptype_names[] = { - "UNDEF", "Hub", "Periph", "PCable", "ACable", "AMA", - "RSV6", "RSV7"}; - - int i, j, idh_ptype; - struct svdm_amode_data *modep; - uint32_t mode_caps; - - if (pe.identity[0] == 0) { - ccprintf("No identity discovered yet.\n"); - return; - } - idh_ptype = PD_IDH_PTYPE(pe.identity[0]); - ccprintf("IDENT:\n"); - ccprintf("\t[ID Header] %08x :: %s, VID:%04x\n", pe.identity[0], - idh_ptype_names[idh_ptype], pd_get_identity_vid(port)); - ccprintf("\t[Cert Stat] %08x\n", pe.identity[1]); - for (i = 2; i < ARRAY_SIZE(pe.identity); i++) { - ccprintf("\t"); - if (pe.identity[i]) - ccprintf("[%d] %08x ", i, pe.identity[i]); - } - ccprintf("\n"); - - if (pe.svid_cnt < 1) { - ccprintf("No SVIDS discovered yet.\n"); - return; - } - - for (i = 0; i < pe.svid_cnt; i++) { - ccprintf("SVID[%d]: %04x MODES:", i, pe.svids[i].svid); - for (j = 0; j < pe.svids[j].mode_cnt; j++) - ccprintf(" [%d] %08x", j + 1, - pe.svids[i].mode_vdo[j]); - ccprintf("\n"); - modep = get_modep( pe.svids[i].svid); - if (modep) { - mode_caps = modep->data->mode_vdo[modep->opos - 1]; - ccprintf("MODE[%d]: svid:%04x caps:%08x\n", modep->opos, - modep->fx->svid, mode_caps); - } - } -} - -static int command_pe(int argc, char **argv) -{ - int port; - char *e; - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - /* command: pe */ - port = strtoi(argv[1], &e, 10); - if (*e || port >= CONFIG_USB_PD_PORT_COUNT) - return EC_ERROR_PARAM2; - if (!strncasecmp(argv[2], "dump", 4)) - dump_pe(port); - - return EC_SUCCESS; -} - -DECLARE_CONSOLE_COMMAND(pe, command_pe, - " dump", - "USB PE"); -#endif /* CONFIG_CMD_USB_PD_PE */ - -#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ - -int pd_svdm(int cnt, uint32_t *payload, uint32_t **rpayload) { - int cmd = PD_VDO_CMD(payload[0]); - int cmd_type = PD_VDO_CMDT(payload[0]); - int (*func)(uint32_t *payload) = NULL; - - int rsize = 1; /* VDM header at a minimum */ - - payload[0] &= ~VDO_CMDT_MASK; - *rpayload = payload; - - if (cmd_type == CMDT_INIT) { - switch (cmd) { - case CMD_DISCOVER_IDENT: - func = svdm_rsp.identity; - break; - case CMD_DISCOVER_SVID: - func = svdm_rsp.svids; - break; - case CMD_DISCOVER_MODES: - func = svdm_rsp.modes; - break; - case CMD_ENTER_MODE: - func = svdm_rsp.enter_mode; - break; - case CMD_DP_STATUS: - func = svdm_rsp.amode->status; - break; - case CMD_DP_CONFIG: - func = svdm_rsp.amode->config; - break; - case CMD_EXIT_MODE: - func = svdm_rsp.exit_mode; - break; -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - case CMD_ATTENTION: - /* - * attention is only SVDM with no response - * (just goodCRC) return zero here. - */ - dfp_consume_attention( payload); - return 0; -#endif - default: - CPRINTF("ERR:CMD:%d\n", cmd); - rsize = 0; - } - if (func) - rsize = func(payload); - else - /* not supported : NACK it */ - rsize = 0; - if (rsize >= 1) - payload[0] |= VDO_CMDT(CMDT_RSP_ACK); - else if (!rsize) { - payload[0] |= VDO_CMDT(CMDT_RSP_NAK); - rsize = 1; - } else { - payload[0] |= VDO_CMDT(CMDT_RSP_BUSY); - rsize = 1; - } - payload[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port)); - } else if (cmd_type == CMDT_RSP_ACK) { -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - struct svdm_amode_data *modep; - - modep = get_modep( PD_VDO_VID(payload[0])); -#endif - switch (cmd) { -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - case CMD_DISCOVER_IDENT: - dfp_consume_identity( cnt, payload); - rsize = dfp_discover_svids( payload); -#ifdef CONFIG_CHARGE_MANAGER - if (pd_charge_from_device(pd_get_identity_vid(port), - pd_get_identity_pid(port))) - charge_manager_update_dualrole( - CAP_DEDICATED); -#endif - break; - case CMD_DISCOVER_SVID: - dfp_consume_svids( payload); - rsize = dfp_discover_modes( payload); - break; - case CMD_DISCOVER_MODES: - dfp_consume_modes( cnt, payload); - rsize = dfp_discover_modes( payload); - /* enter the default mode for DFP */ - if (!rsize) { - payload[0] = pd_dfp_enter_mode( 0, 0); - if (payload[0]) - rsize = 1; - } - break; - case CMD_ENTER_MODE: - if (!modep) { - rsize = 0; - } else { - if (!modep->opos) - pd_dfp_enter_mode( 0, 0); - - if (modep->opos) { - rsize = modep->fx->status( - payload); - payload[0] |= PD_VDO_OPOS(modep->opos); - } - } - break; - case CMD_DP_STATUS: - /* DP status response & UFP's DP attention have same - payload */ - dfp_consume_attention( payload); - if (modep && modep->opos) - rsize = modep->fx->config( payload); - else - rsize = 0; - break; - case CMD_DP_CONFIG: - if (modep && modep->opos && modep->fx->post_config) - modep->fx->post_config(port); - /* no response after DFPs ack */ - rsize = 0; - break; - case CMD_EXIT_MODE: - /* no response after DFPs ack */ - rsize = 0; - break; -#endif - case CMD_ATTENTION: - /* no response after DFPs ack */ - rsize = 0; - break; - default: - CPRINTF("ERR:CMD:%d\n", cmd); - rsize = 0; - } - - payload[0] |= VDO_CMDT(CMDT_INIT); - payload[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port)); -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - } else if (cmd_type == CMDT_RSP_BUSY) { - switch (cmd) { - case CMD_DISCOVER_IDENT: - case CMD_DISCOVER_SVID: - case CMD_DISCOVER_MODES: - /* resend if its discovery */ - rsize = 1; - break; - case CMD_ENTER_MODE: - /* Error */ - CPRINTF("ERR:ENTBUSY\n"); - rsize = 0; - break; - case CMD_EXIT_MODE: - rsize = 0; - break; - default: - rsize = 0; - } - } else if (cmd_type == CMDT_RSP_NAK) { - /* nothing to do */ - rsize = 0; -#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ - } else { - CPRINTF("ERR:CMDT:%d\n", cmd); - /* do not answer */ - rsize = 0; - } - return rsize; -} - -#else - -int pd_svdm( int cnt, uint32_t *payload, uint32_t **rpayload) -{ - return 0; -} - -#endif /* CONFIG_USB_PD_ALT_MODE */ - -#ifndef CONFIG_USB_PD_CUSTOM_VDM -int pd_vdm(int cnt, uint32_t *payload, uint32_t **rpayload) { - return 0; -} -#endif /* !CONFIG_USB_PD_CUSTOM_VDM */ - -static void pd_usb_billboard_deferred(void) { -#if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP) \ - && !defined(CONFIG_USB_PD_SIMPLE_DFP) && defined(CONFIG_USB_BOS) - - /* - * TODO(tbroch) - * 1. Will we have multiple type-C port UFPs - * 2. Will there be other modes applicable to DFPs besides DP - */ - if (!pd_alt_mode(0, USB_SID_DISPLAYPORT)) - usb_connect(); - -#endif -} - -#ifdef CONFIG_USB_PD_ALT_MODE_DFP -static int hc_remote_pd_discovery(struct host_cmd_handler_args *args) -{ - const uint8_t *port = args->params; - struct ec_params_usb_pd_discovery_entry *r = args->response; - - if (*port >= CONFIG_USB_PD_PORT_COUNT) - return EC_RES_INVALID_PARAM; - - r->vid = pd_get_identity_vid(*port); - r->ptype = PD_IDH_PTYPE(pe[*port].identity[0]); - /* pid only included if vid is assigned */ - if (r->vid) - r->pid = PD_PRODUCT_PID(pe[*port].identity[2]); - - args->response_size = sizeof(*r); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DISCOVERY, - hc_remote_pd_discovery, - EC_VER_MASK(0)); - -static int hc_remote_pd_get_amode(struct host_cmd_handler_args *args) -{ - struct svdm_amode_data *modep; - const struct ec_params_usb_pd_get_mode_request *p = args->params; - struct ec_params_usb_pd_get_mode_response *r = args->response; - - if (p->port >= CONFIG_USB_PD_PORT_COUNT) - return EC_RES_INVALID_PARAM; - - /* no more to send */ - if (p->svid_idx >= pe[p->port].svid_cnt) { - r->svid = 0; - args->response_size = sizeof(r->svid); - return EC_RES_SUCCESS; - } - - r->svid = pe[p->port].svids[p->svid_idx].svid; - r->opos = 0; - memcpy(r->vdo, pe[p->port].svids[p->svid_idx].mode_vdo, 24); - modep = get_modep(p->port, r->svid); - - if (modep) - r->opos = pd_alt_mode(p->port, r->svid); - - args->response_size = sizeof(*r); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_GET_AMODE, - hc_remote_pd_get_amode, - EC_VER_MASK(0)); - -#endif - -#define FW_RW_END (CONFIG_EC_WRITABLE_STORAGE_OFF + \ - CONFIG_RW_STORAGE_OFF + CONFIG_RW_SIZE) - -#ifdef CONFIG_USB_PD_DISCHARGE -void pd_set_vbus_discharge( int enable) -{ - static struct mutex discharge_lock[CONFIG_USB_PD_PORT_COUNT]; - - mutex_lock(&discharge_lock); - enable &= !board_vbus_source_enabled(port); -#ifdef CONFIG_USB_PD_DISCHARGE_GPIO - if (!port) - gpio_set_level(GPIO_USB_C0_DISCHARGE, enable); -#if CONFIG_USB_PD_PORT_COUNT > 1 - else - gpio_set_level(GPIO_USB_C1_DISCHARGE, enable); -#endif /* CONFIG_USB_PD_PORT_COUNT */ -#elif defined(CONFIG_USB_PD_DISCHARGE_TCPC) - tcpc_discharge_vbus( enable); -#else -#error "PD discharge implementation not defined" -#endif - mutex_unlock(&discharge_lock); -} -#endif /* CONFIG_USB_PD_DISCHARGE */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.cpp b/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.cpp deleted file mode 100644 index 1ef96807..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/USBC_PD/usb_pd_protocol.cpp +++ /dev/null @@ -1,4029 +0,0 @@ -/* Copyright (c) 2014 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 "usb_pd.h" -#include "USBC_TCPM/usb_pd_tcpm.h" -#include "USBC_TCPM/tcpm.h" -#include "usb_pd_driver.h" -#include -#include -#ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -BUILD_ASSERT(CONFIG_USB_PD_PORT_COUNT <= EC_USB_PD_MAX_PORTS); - -/* - * Debug log level - higher number == more log - * Level 0: Log state transitions - * Level 1: Level 0, plus state name - * Level 2: Level 1, plus packet info - * Level 3: Level 2, plus ping packet and packet dump on error - * - * Note that higher log level causes timing changes and thus may affect - * performance. - * - * Can be limited to constant debug_level by CONFIG_USB_PD_DEBUG_LEVEL - */ -#ifdef CONFIG_USB_PD_DEBUG_LEVEL -static const int debug_level = CONFIG_USB_PD_DEBUG_LEVEL; -#else -static int debug_level; -#endif - -/* - * PD communication enabled flag. When false, PD state machine still - * detects source/sink connection and disconnection, and will still - * provide VBUS, but never sends any PD communication. - */ -static uint8_t pd_comm_enabled[CONFIG_USB_PD_PORT_COUNT]; -#else /* CONFIG_COMMON_RUNTIME */ -#define CPRINTF(format, args...) -#define CPRINTS(format, args...) -static const int debug_level = 0; -#endif - -#ifdef CONFIG_USB_PD_DUAL_ROLE -#define DUAL_ROLE_IF_ELSE( sink_clause, src_clause) \ - (pd.power_role == PD_ROLE_SINK ? (sink_clause) : (src_clause)) -#else -#define DUAL_ROLE_IF_ELSE( sink_clause, src_clause) (src_clause) -#endif - -#define READY_RETURN_STATE() DUAL_ROLE_IF_ELSE( PD_STATE_SNK_READY, \ - PD_STATE_SRC_READY) - -/* Type C supply voltage (mV) */ -#define TYPE_C_VOLTAGE 5000 /* mV */ - -/* PD counter definitions */ -#define PD_MESSAGE_ID_COUNT 7 -#define PD_HARD_RESET_COUNT 2 -#define PD_CAPS_COUNT 50 -#define PD_SNK_CAP_RETRIES 3 - -enum vdm_states { - VDM_STATE_ERR_BUSY = -3, - VDM_STATE_ERR_SEND = -2, - VDM_STATE_ERR_TMOUT = -1, - VDM_STATE_DONE = 0, - /* Anything >0 represents an active state */ - VDM_STATE_READY = 1, - VDM_STATE_BUSY = 2, - VDM_STATE_WAIT_RSP_BUSY = 3, -}; - -#ifdef CONFIG_USB_PD_DUAL_ROLE -/* Port dual-role state */ -enum pd_dual_role_states drp_state = CONFIG_USB_PD_INITIAL_DRP_STATE; - -/* Enable variable for Try.SRC states */ -static uint8_t pd_try_src_enable; -#endif - -#ifdef CONFIG_USB_PD_REV30 -/* - * The spec. revision is used to index into this array. - * Rev 0 (PD 1.0) - return PD_CTRL_REJECT - * Rev 1 (PD 2.0) - return PD_CTRL_REJECT - * Rev 2 (PD 3.0) - return PD_CTRL_NOT_SUPPORTED - */ -static const uint8_t refuse[] = { - PD_CTRL_REJECT, PD_CTRL_REJECT, PD_CTRL_NOT_SUPPORTED}; -#define REFUSE(r) refuse[r] -#else -#define REFUSE(r) PD_CTRL_REJECT -#endif - -#ifdef CONFIG_USB_PD_REV30 -/* - * The spec. revision is used to index into this array. - * Rev 0 (VDO 1.0) - return VDM_VER10 - * Rev 1 (VDO 1.0) - return VDM_VER10 - * Rev 2 (VDO 2.0) - return VDM_VER20 - */ -static const uint8_t vdo_ver[] = { - VDM_VER10, VDM_VER10, VDM_VER20}; -#define VDO_VER(v) vdo_ver[v] -#else -#define VDO_VER(v) VDM_VER10 -#endif - -// variables that used to be pd_task, but had to be promoted -// so both pd_init and pd_run_state_machine can see them -static int head; -static int port = TASK_ID_TO_PD_PORT(task_get_current()); -static uint32_t payload[7]; -static int timeout = 10 * MSEC; -static int cc1, cc2; -static int res, incoming_packet = 0; -static int hard_reset_count = 0; -#ifdef CONFIG_USB_PD_DUAL_ROLE -static uint64_t next_role_swap = PD_T_DRP_SNK; -#ifndef CONFIG_USB_PD_VBUS_DETECT_NONE -static int snk_hard_reset_vbus_off = 0; -#endif -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE -static const int auto_toggle_supported = tcpm_auto_toggle_supported(); -#endif -#if defined(CONFIG_CHARGE_MANAGER) -static typec_current_t typec_curr = 0, typec_curr_change = 0; -#endif /* CONFIG_CHARGE_MANAGER */ -#endif /* CONFIG_USB_PD_DUAL_ROLE */ -static enum pd_states this_state; -static enum pd_cc_states new_cc_state; -static timestamp_t now; -static int caps_count = 0, hard_reset_sent = 0; -static int snk_cap_count = 0; -static int evt; - -static struct pd_protocol { - /* current port power role (SOURCE or SINK) */ - uint8_t power_role; - /* current port data role (DFP or UFP) */ - uint8_t data_role; - /* 3-bit rolling message ID counter */ - uint8_t msg_id; - /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */ - uint8_t polarity; - /* PD state for port */ - enum pd_states task_state; - /* PD state when we run state handler the last time */ - enum pd_states last_state; - /* bool: request state change to SUSPENDED */ - uint8_t req_suspend_state; - /* The state to go to after timeout */ - enum pd_states timeout_state; - /* port flags, see PD_FLAGS_* */ - uint32_t flags; - /* Timeout for the current state. Set to 0 for no timeout. */ - uint64_t timeout; - /* Time for source recovery after hard reset */ - uint64_t src_recover; - /* Time for CC debounce end */ - uint64_t cc_debounce; - /* The cc state */ - enum pd_cc_states cc_state; - /* status of last transmit */ - uint8_t tx_status; - - /* last requested voltage PDO index */ - int requested_idx; -#ifdef CONFIG_USB_PD_DUAL_ROLE - /* Current limit / voltage based on the last request message */ - uint32_t curr_limit; - uint32_t supply_voltage; - /* Signal charging update that affects the port */ - int new_power_request; - /* Store previously requested voltage request */ - int prev_request_mv; - /* Time for Try.SRC states */ - uint64_t try_src_marker; -#endif - - /* PD state for Vendor Defined Messages */ - enum vdm_states vdm_state; - /* Timeout for the current vdm state. Set to 0 for no timeout. */ - timestamp_t vdm_timeout; - /* next Vendor Defined Message to send */ - uint32_t vdo_data[VDO_MAX_SIZE]; - uint8_t vdo_count; - /* VDO to retry if UFP responder replied busy. */ - uint32_t vdo_retry; - -#ifdef CONFIG_USB_PD_CHROMEOS - /* Attached ChromeOS device id, RW hash, and current RO / RW image */ - uint16_t dev_id; - uint32_t dev_rw_hash[PD_RW_HASH_SIZE/4]; - enum ec_current_image current_image; -#endif -#ifdef CONFIG_USB_PD_REV30 - /* PD Collision avoidance buffer */ - uint16_t ca_buffered; - uint16_t ca_header; - uint32_t ca_buffer[PDO_MAX_OBJECTS]; - enum tcpm_transmit_type ca_type; - /* protocol revision */ - uint8_t rev; -#endif -} pd; - -#ifdef CONFIG_COMMON_RUNTIME -static const char * const pd_state_names[] = { - "DISABLED", "SUSPENDED", -#ifdef CONFIG_USB_PD_DUAL_ROLE - "SNK_DISCONNECTED", "SNK_DISCONNECTED_DEBOUNCE", - "SNK_HARD_RESET_RECOVER", - "SNK_DISCOVERY", "SNK_REQUESTED", "SNK_TRANSITION", "SNK_READY", - "SNK_SWAP_INIT", "SNK_SWAP_SNK_DISABLE", - "SNK_SWAP_SRC_DISABLE", "SNK_SWAP_STANDBY", "SNK_SWAP_COMPLETE", -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - "SRC_DISCONNECTED", "SRC_DISCONNECTED_DEBOUNCE", - "SRC_HARD_RESET_RECOVER", "SRC_STARTUP", - "SRC_DISCOVERY", "SRC_NEGOCIATE", "SRC_ACCEPTED", "SRC_POWERED", - "SRC_TRANSITION", "SRC_READY", "SRC_GET_SNK_CAP", "DR_SWAP", -#ifdef CONFIG_USB_PD_DUAL_ROLE - "SRC_SWAP_INIT", "SRC_SWAP_SNK_DISABLE", "SRC_SWAP_SRC_DISABLE", - "SRC_SWAP_STANDBY", -#ifdef CONFIG_USBC_VCONN_SWAP - "VCONN_SWAP_SEND", "VCONN_SWAP_INIT", "VCONN_SWAP_READY", -#endif /* CONFIG_USBC_VCONN_SWAP */ -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - "SOFT_RESET", "HARD_RESET_SEND", "HARD_RESET_EXECUTE", "BIST_RX", - "BIST_TX", -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - "DRP_AUTO_TOGGLE", -#endif -}; -BUILD_ASSERT(ARRAY_SIZE(pd_state_names) == PD_STATE_COUNT); -#endif - -/* - * 4 entry rw_hash table of type-C devices that AP has firmware updates for. - */ -#ifdef CONFIG_COMMON_RUNTIME -#define RW_HASH_ENTRIES 4 -static struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES]; -#endif - -int pd_comm_is_enabled() { -#ifdef CONFIG_COMMON_RUNTIME - return pd_comm_enabled[port]; -#else - return 1; -#endif -} - -static inline void set_state_timeout(uint64_t timeout, - enum pd_states timeout_state) { - pd.timeout = timeout; - pd.timeout_state = timeout_state; -} - -#ifdef CONFIG_USB_PD_REV30 -int pd_get_rev() -{ - return pd.rev; -} - -int pd_get_vdo_ver() -{ - return vdo_ver[pd.rev]; -} -#endif - -/* Return flag for pd state is connected */ -int pd_is_connected() { - if (pd.task_state == PD_STATE_DISABLED) - return 0; - -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - if (pd.task_state == PD_STATE_DRP_AUTO_TOGGLE) - return 0; -#endif - - return DUAL_ROLE_IF_ELSE( - /* sink */ - pd.task_state != PD_STATE_SNK_DISCONNECTED && pd.task_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE, - /* source */ - pd.task_state != PD_STATE_SRC_DISCONNECTED && pd.task_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE); -} - -/* - * Return true if partner port is a DTS or TS capable of entering debug - * mode (eg. is presenting Rp/Rp or Rd/Rd). - */ -int pd_ts_dts_plugged() { - return pd.flags & PD_FLAGS_TS_DTS_PARTNER; -} - -#ifdef CONFIG_USB_PD_DUAL_ROLE -void pd_vbus_low() { - pd.flags &= ~PD_FLAGS_VBUS_NEVER_LOW; -} - -static inline int pd_is_vbus_present() { -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - return tcpm_get_vbus_level(); -#else - return pd_snk_is_vbus_provided(); -#endif -} -#endif - -static inline void set_state(enum pd_states next_state) { - enum pd_states last_state = pd.task_state; -#ifdef CONFIG_LOW_POWER_IDLE - int i; -#endif - - set_state_timeout(0, PD_STATE_DISABLED); - pd.task_state = next_state; - - if (last_state == next_state) - return; - -#ifdef CONFIG_USB_PD_DUAL_ROLE -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - /* Clear flag to allow DRP auto toggle when possible */ - if (last_state != PD_STATE_DRP_AUTO_TOGGLE) - pd.flags &= ~PD_FLAGS_TCPC_DRP_TOGGLE; -#endif - - /* Ignore dual-role toggling between sink and source */ - if ((last_state == PD_STATE_SNK_DISCONNECTED - && next_state == PD_STATE_SRC_DISCONNECTED) - || (last_state == PD_STATE_SRC_DISCONNECTED - && next_state == PD_STATE_SNK_DISCONNECTED)) - return; - - if (next_state == PD_STATE_SRC_DISCONNECTED - || next_state == PD_STATE_SNK_DISCONNECTED) { - /* Clear the input current limit */ - pd_set_input_current_limit(0, 0); -#ifdef CONFIG_CHARGE_MANAGER - //typec_set_input_current_limit( 0, 0); - //charge_manager_set_ceil( - // CEIL_REQUESTOR_PD, - // CHARGE_CEIL_NONE); -#endif -#ifdef CONFIG_USBC_VCONN - tcpm_set_vconn( 0); -#endif -#else /* CONFIG_USB_PD_DUAL_ROLE */ - if (next_state == PD_STATE_SRC_DISCONNECTED) { -#endif - -#ifdef CONFIG_USB_PD_REV30 - /* Adjust rev to highest level*/ - pd.rev = PD_REV30; -#endif -#ifdef CONFIG_USB_PD_CHROMEOS - pd.dev_id = 0; - pd.flags &= ~PD_FLAGS_RESET_ON_DISCONNECT_MASK; -#endif -#ifdef CONFIG_CHARGE_MANAGER - //charge_manager_update_dualrole( CAP_UNKNOWN); -#endif -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - pd_dfp_exit_mode( 0, 0); -#endif -#ifdef CONFIG_USBC_SS_MUX - usb_mux_set( TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, - pd.polarity); -#endif - /* Disable TCPC RX */ - tcpm_set_rx_enable(0); - } - -#ifdef CONFIG_LOW_POWER_IDLE - /* If a PD device is attached then disable deep sleep */ - for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) { - if (pd[i].flags & PD_FLAGS_PREVIOUS_PD_CONN) - break; - } - if (i == CONFIG_USB_PD_PORT_COUNT) - enable_sleep(SLEEP_MASK_USB_PD); - else - disable_sleep(SLEEP_MASK_USB_PD); -#endif - - if (debug_level >= 1) - CPRINTF("C%d st%d %s\n", port, next_state, - pd_state_names[next_state]); - else - CPRINTF("C%d st%d\n", port, next_state); -} - -/* increment message ID counter */ -static void inc_id() { - pd.msg_id = (pd.msg_id + 1) & PD_MESSAGE_ID_COUNT; -} - -#ifdef CONFIG_USB_PD_REV30 -static void sink_can_xmit( int rp) -{ - tcpm_select_rp_value( rp); - tcpm_set_cc( TYPEC_CC_RP); -} - -static inline void pd_ca_reset() -{ - pd.ca_buffered = 0; -} -#endif - -void pd_transmit_complete(int status) { - if (status == TCPC_TX_COMPLETE_SUCCESS) - inc_id(); - - pd.tx_status = status; - //task_set_event(PD_PORT_TO_TASK_ID(), PD_EVENT_TX, 0); - pd_task_set_event(PD_EVENT_TX, 0); -} - -static int pd_transmit(enum tcpm_transmit_type type, uint16_t header, - const uint32_t *data) { - int evt; - - /* If comms are disabled, do not transmit, return error */ - if (!pd_comm_is_enabled()) - return -1; -#ifdef CONFIG_USB_PD_REV30 - /* Source-coordinated collision avoidance */ - /* - * In order to avoid message collisions due to asynchronous Messaging - * sent from the Sink, the Source sets Rp to SinkTxOk to indicate to - * the Sink that it is ok to initiate an AMS. When the Source wishes - * to initiate an AMS it sets Rp to SinkTxNG. When the Sink detects - * that Rp is set to SinkTxOk it May initiate an AMS. When the Sink - * detects that Rp is set to SinkTxNG it Shall Not initiate an AMS - * and Shall only send Messages that are part of an AMS the Source has - * initiated. Note that this restriction applies to SOP* AMS’s i.e. - * for both Port to Port and Port to Cable Plug communications. - * - * This starts after an Explicit Contract is in place - * PD R3 V1.1 Section 2.5.2. - * - * Note: a Sink can still send Hard Reset signaling at any time. - */ - if ((pd.rev == PD_REV30) && - (pd.flags & PD_FLAGS_EXPLICIT_CONTRACT)) { - if (pd.power_role == PD_ROLE_SOURCE) { - /* - * Inform Sink that it can't transmit. If a sink - * transmition is in progress and a collsion occurs, - * a reset is generated. This should be rare because - * all extended messages are chunked. This effectively - * defaults to PD REV 2.0 collision avoidance. - */ - sink_can_xmit( SINK_TX_NG); - } else if (type != TCPC_TX_HARD_RESET) { - int cc1; - int cc2; - - tcpm_get_cc( &cc1, &cc2); - if (cc1 == TYPEC_CC_VOLT_SNK_1_5 || - cc2 == TYPEC_CC_VOLT_SNK_1_5) { - /* Sink can't transmit now. */ - /* Check if message is already buffered. */ - if (pd.ca_buffered) - return -1; - - /* Buffer message and send later. */ - pd.ca_type = type; - pd.ca_header = header; - memcpy(pd.ca_buffer, - data, sizeof(uint32_t) * - PD_HEADER_CNT(header)); - pd.ca_buffered = 1; - return 1; - } - } - } -#endif - tcpm_transmit(type, header, data); - - /* Wait until TX is complete */ - // Would wait, except that we're making tcpm_transmit blocking - //evt = task_wait_event_mask(PD_EVENT_TX, PD_T_TCPC_TX_TIMEOUT); -#ifdef CONFIG_USB_PD_REV30 - /* - * If the source just completed a transmit, tell - * the sink it can transmit if it wants to. - */ - if ((pd.rev == PD_REV30) && - (pd.power_role == PD_ROLE_SOURCE) && - (pd.flags & PD_FLAGS_EXPLICIT_CONTRACT)) { - sink_can_xmit( SINK_TX_OK); - } -#endif - - // removing task-based stuff from the library - //if (evt & TASK_EVENT_TIMER) - // return -1; - - /* TODO: give different error condition for failed vs discarded */ - return pd.tx_status == TCPC_TX_COMPLETE_SUCCESS ? 1 : -1; -} - -#ifdef CONFIG_USB_PD_REV30 -static void pd_ca_send_pending() -{ - int cc1; - int cc2; - - /* Check if a message has been buffered. */ - if (!pd.ca_buffered) - return; - - tcpm_get_cc( &cc1, &cc2); - if ((cc1 != TYPEC_CC_VOLT_SNK_1_5) && - (cc2 != TYPEC_CC_VOLT_SNK_1_5)) - if (pd_transmit( pd.ca_type, - pd.ca_header, - pd.ca_buffer) < 0) - return; - - /* Message was sent, so free up the buffer. */ - pd.ca_buffered = 0; -} -#endif - -static void pd_update_roles() { - /* Notify TCPC of role update */ - tcpm_set_msg_header(pd.power_role, pd.data_role); -} - -static int send_control(int type) { - int bit_len; - uint16_t header = PD_HEADER(type, pd.power_role, pd.data_role, pd.msg_id, 0, - pd_get_rev(), 0); - - bit_len = pd_transmit(TCPC_TX_SOP, header, NULL); - if (debug_level >= 2) - CPRINTF("CTRL[%d]>%d\n", type, bit_len); - - return bit_len; -} - -static int send_source_cap() { - int bit_len; -#if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ - defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) - const uint32_t *src_pdo; - const int src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port); -#else - const uint32_t *src_pdo = pd_src_pdo; - const int src_pdo_cnt = pd_src_pdo_cnt; -#endif - uint16_t header; - - if (src_pdo_cnt == 0) - /* No source capabilities defined, sink only */ - header = PD_HEADER(PD_CTRL_REJECT, pd.power_role, pd.data_role, - pd.msg_id, 0, pd_get_rev(), 0); - else - header = PD_HEADER(PD_DATA_SOURCE_CAP, pd.power_role, pd.data_role, - pd.msg_id, src_pdo_cnt, pd_get_rev(), 0); - - bit_len = pd_transmit(TCPC_TX_SOP, header, src_pdo); - if (debug_level >= 2) - CPRINTF("srcCAP>%d\n", bit_len); - - return bit_len; -} - -#ifdef CONFIG_USB_PD_REV30 -static int send_battery_cap( uint32_t *payload) -{ - int bit_len; - uint16_t msg[6] = {0, 0, 0, 0, 0, 0}; - uint16_t header = PD_HEADER(PD_EXT_BATTERY_CAP, - pd.power_role, - pd.data_role, - pd.msg_id, - 3, /* Number of Data Objects */ - pd.rev, - 1 /* This is an exteded message */ - ); - - /* Set extended header */ - msg[0] = PD_EXT_HEADER(0, /* Chunk Number */ - 0, /* Request Chunk */ - 9 /* Data Size in bytes */ - ); - /* Set VID */ - msg[1] = USB_VID_GOOGLE; - - /* Set PID */ - msg[2] = CONFIG_USB_PID; - - if (battery_is_present()) { - /* - * We only have one fixed battery, - * so make sure batt cap ref is 0. - */ - if (BATT_CAP_REF(payload[0]) != 0) { - /* Invalid battery reference */ - msg[5] = 1; - } else { - uint32_t v; - uint32_t c; - - /* - * The Battery Design Capacity field shall return the - * Battery’s design capacity in tenths of Wh. If the - * Battery is Hot Swappable and is not present, the - * Battery Design Capacity field shall be set to 0. If - * the Battery is unable to report its Design Capacity, - * it shall return 0xFFFF - */ - msg[3] = 0xffff; - - /* - * The Battery Last Full Charge Capacity field shall - * return the Battery’s last full charge capacity in - * tenths of Wh. If the Battery is Hot Swappable and - * is not present, the Battery Last Full Charge Capacity - * field shall be set to 0. If the Battery is unable to - * report its Design Capacity, the Battery Last Full - * Charge Capacity field shall be set to 0xFFFF. - */ - msg[4] = 0xffff; - - if (battery_design_voltage(&v) == 0) { - if (battery_design_capacity(&c) == 0) { - /* - * Wh = (c * v) / 1000000 - * 10th of a Wh = Wh * 10 - */ - msg[3] = DIV_ROUND_NEAREST((c * v), - 100000); - } - - if (battery_full_charge_capacity(&c) == 0) { - /* - * Wh = (c * v) / 1000000 - * 10th of a Wh = Wh * 10 - */ - msg[4] = DIV_ROUND_NEAREST((c * v), - 100000); - } - } - } - } - - bit_len = pd_transmit( TCPC_TX_SOP, header, (uint32_t *)msg); - if (debug_level >= 2) - CPRINTF("batCap>%d\n", bit_len); - return bit_len; -} - -static int send_battery_status( uint32_t *payload) -{ - int bit_len; - uint32_t msg = 0; - uint16_t header = PD_HEADER(PD_DATA_BATTERY_STATUS, - pd.power_role, - pd.data_role, - pd.msg_id, - 1, /* Number of Data Objects */ - pd.rev, - 0 /* This is NOT an extended message */ - ); - - if (battery_is_present()) { - /* - * We only have one fixed battery, - * so make sure batt cap ref is 0. - */ - if (BATT_CAP_REF(payload[0]) != 0) { - /* Invalid battery reference */ - msg |= BSDO_INVALID; - } else { - uint32_t v; - uint32_t c; - - if (battery_design_voltage(&v) != 0 || - battery_remaining_capacity(&c) != 0) { - msg |= BSDO_CAP(BSDO_CAP_UNKNOWN); - } else { - /* - * Wh = (c * v) / 1000000 - * 10th of a Wh = Wh * 10 - */ - msg |= BSDO_CAP(DIV_ROUND_NEAREST((c * v), - 100000)); - } - - /* Battery is present */ - msg |= BSDO_PRESENT; - - /* - * For drivers that are not smart battery compliant, - * battery_status() returns EC_ERROR_UNIMPLEMENTED and - * the battery is assumed to be idle. - */ - if (battery_status(&c) != 0) { - msg |= BSDO_IDLE; /* assume idle */ - } else { - if (c & STATUS_FULLY_CHARGED) - /* Fully charged */ - msg |= BSDO_IDLE; - else if (c & STATUS_DISCHARGING) - /* Discharging */ - msg |= BSDO_DISCHARGING; - /* else battery is charging.*/ - } - } - } else { - msg = BSDO_CAP(BSDO_CAP_UNKNOWN); - } - - bit_len = pd_transmit( TCPC_TX_SOP, header, &msg); - if (debug_level >= 2) - CPRINTF("batStat>%d\n", bit_len); - - return bit_len; -} -#endif - -#ifdef CONFIG_USB_PD_DUAL_ROLE -static void send_sink_cap() { - int bit_len; - uint16_t header = PD_HEADER(PD_DATA_SINK_CAP, pd.power_role, - pd.data_role, pd.msg_id, pd_snk_pdo_cnt, pd_get_rev(), - 0); - - bit_len = pd_transmit(TCPC_TX_SOP, header, pd_snk_pdo); - if (debug_level >= 2) - CPRINTF("snkCAP>%d\n", bit_len); -} - -static int send_request(uint32_t rdo) { - int bit_len; - uint16_t header = PD_HEADER(PD_DATA_REQUEST, pd.power_role, - pd.data_role, pd.msg_id, 1, pd_get_rev(), 0); - - bit_len = pd_transmit(TCPC_TX_SOP, header, &rdo); - if (debug_level >= 2) - CPRINTF("REQ%d>\n", bit_len); - - return bit_len; -} -#ifdef CONFIG_BBRAM -static int pd_get_saved_active() -{ - uint8_t val; - - if (system_get_bbram(port ? SYSTEM_BBRAM_IDX_PD1 : - SYSTEM_BBRAM_IDX_PD0, &val)) { - CPRINTS("PD NVRAM FAIL"); - return 0; - } - return !!val; -} - -static void pd_set_saved_active( int val) -{ - if (system_set_bbram(port ? SYSTEM_BBRAM_IDX_PD1 : - SYSTEM_BBRAM_IDX_PD0, val)) - CPRINTS("PD NVRAM FAIL"); -} -#endif // CONFIG_BBRAM -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - -#ifdef CONFIG_COMMON_RUNTIME -static int send_bist_cmd() -{ - /* currently only support sending bist carrier 2 */ - uint32_t bdo = BDO(BDO_MODE_CARRIER2, 0); - int bit_len; - uint16_t header = PD_HEADER(PD_DATA_BIST, pd.power_role, - pd.data_role, pd.msg_id, 1, - pd_get_rev(), 0); - - bit_len = pd_transmit( TCPC_TX_SOP, header, &bdo); - CPRINTF("BIST>%d\n", bit_len); - - return bit_len; -} -#endif - -static void queue_vdm(uint32_t *header, const uint32_t *data, int data_cnt) { - pd.vdo_count = data_cnt + 1; - pd.vdo_data[0] = header[0]; - memcpy(&pd.vdo_data[1], data, sizeof(uint32_t) * data_cnt); - /* Set ready, pd task will actually send */ - pd.vdm_state = VDM_STATE_READY; -} - -static void handle_vdm_request(int cnt, uint32_t *payload) { - int rlen = 0; - uint32_t *rdata; - - if (pd.vdm_state == VDM_STATE_BUSY) { - /* If UFP responded busy retry after timeout */ - if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_BUSY) { - pd.vdm_timeout.val = get_time().val + - PD_T_VDM_BUSY; - pd.vdm_state = VDM_STATE_WAIT_RSP_BUSY; - pd.vdo_retry = (payload[0] & ~VDO_CMDT_MASK) | - CMDT_INIT; - return; - } else { - pd.vdm_state = VDM_STATE_DONE; - } - } - - if (PD_VDO_SVDM(payload[0])) - rlen = pd_svdm(cnt, payload, &rdata); - - if (rlen > 0) { - queue_vdm(rdata, &rdata[1], rlen - 1); - return; - } - if (debug_level >= 2) - CPRINTF("Unhandled VDM VID %04x CMD %04x\n", - PD_VDO_VID(payload[0]), payload[0] & 0xFFFF); -} - -void pd_execute_hard_reset() { - if (pd.last_state == PD_STATE_HARD_RESET_SEND) - CPRINTF("C%d HARD RST TX\n", port); - else - CPRINTF("C%d HARD RST RX\n", port); - - pd.msg_id = 0; -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - pd_dfp_exit_mode( 0, 0); -#endif - -#ifdef CONFIG_USB_PD_REV30 - pd.rev = PD_REV30; - pd_ca_reset(); -#endif - /* - * Fake set last state to hard reset to make sure that the next - * state to run knows that we just did a hard reset. - */ - pd.last_state = PD_STATE_HARD_RESET_EXECUTE; - -#ifdef CONFIG_USB_PD_DUAL_ROLE - /* - * If we are swapping to a source and have changed to Rp, restore back - * to Rd and turn off vbus to match our power_role. - */ - if (pd.task_state == PD_STATE_SNK_SWAP_STANDBY - || pd.task_state == PD_STATE_SNK_SWAP_COMPLETE) { - tcpm_set_cc(TYPEC_CC_RD); - pd_power_supply_reset(); - } - - if (pd.power_role == PD_ROLE_SINK) { - /* Clear the input current limit */ - pd_set_input_current_limit(0, 0); -#ifdef CONFIG_CHARGE_MANAGER - //charge_manager_set_ceil( - // CEIL_REQUESTOR_PD, - // CHARGE_CEIL_NONE); -#endif /* CONFIG_CHARGE_MANAGER */ - - set_state (PD_STATE_SNK_HARD_RESET_RECOVER); - return; - } -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - - /* We are a source, cut power */ - pd_power_supply_reset(); - pd.src_recover = get_time().val + PD_T_SRC_RECOVER; - set_state(PD_STATE_SRC_HARD_RESET_RECOVER); -} - -static void execute_soft_reset() { - pd.msg_id = 0; - set_state( - DUAL_ROLE_IF_ELSE(PD_STATE_SNK_DISCOVERY, PD_STATE_SRC_DISCOVERY)); - CPRINTF("C%d Soft Rst\n", port); -} - -void pd_soft_reset(void) { - int i; - - if (pd_is_connected()) { - set_state(PD_STATE_SOFT_RESET); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID(i)); - } -} - -#ifdef CONFIG_USB_PD_DUAL_ROLE -/* - * Request desired charge voltage from source. - * Returns EC_SUCCESS on success or non-zero on failure. - */ -static int pd_send_request_msg(int always_send_request) { - uint32_t rdo, curr_limit, supply_voltage; - int res; - -#ifdef CONFIG_CHARGE_MANAGER - //int charging = (charge_manager_get_active_charge_port() == port); - const int charging = 1; -#else - const int charging = 1; -#endif - -#ifdef CONFIG_USB_PD_CHECK_MAX_REQUEST_ALLOWED - int max_request_allowed = pd_is_max_request_allowed(); -#else - const int max_request_allowed = 1; -#endif - - /* Clear new power request */ - pd.new_power_request = 0; - - /* Build and send request RDO */ - /* - * If this port is not actively charging or we are not allowed to - * request the max voltage, then select vSafe5V - */ - res = pd_build_request(&rdo, &curr_limit, &supply_voltage, - charging && max_request_allowed ? - PD_REQUEST_MAX : PD_REQUEST_VSAFE5V); - - if (res != EC_SUCCESS) - /* - * If fail to choose voltage, do nothing, let source re-send - * source cap - */ - return -1; - - if (!always_send_request) { - /* Don't re-request the same voltage */ - if (pd.prev_request_mv == supply_voltage) - return EC_SUCCESS; -#ifdef CONFIG_CHARGE_MANAGER - /* Limit current to PD_MIN_MA during transition */ - //else - // charge_manager_force_ceil( PD_MIN_MA); -#endif - } - - CPRINTF("Req C%d [%d] %dmV %dmA", port, RDO_POS(rdo), - supply_voltage, curr_limit); - if (rdo & RDO_CAP_MISMATCH) - CPRINTF(" Mismatch");CPRINTF("\n"); - - pd.curr_limit = curr_limit; - pd.supply_voltage = supply_voltage; - pd.prev_request_mv = supply_voltage; - res = send_request(rdo); - if (res < 0) - return res; - set_state (PD_STATE_SNK_REQUESTED); - return EC_SUCCESS; -} -#endif - -static void pd_update_pdo_flags(uint32_t pdo) { -#ifdef CONFIG_CHARGE_MANAGER -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - int charge_whitelisted = - (pd.power_role == PD_ROLE_SINK && - pd_charge_from_device(pd_get_identity_vid(), - pd_get_identity_pid())); -#else - const int charge_whitelisted = 0; -#endif -#endif - - /* can only parse PDO flags if type is fixed */ - if ((pdo & PDO_TYPE_MASK) != PDO_TYPE_FIXED) - return; - -#ifdef CONFIG_USB_PD_DUAL_ROLE - if (pdo & PDO_FIXED_DUAL_ROLE) - pd.flags |= PD_FLAGS_PARTNER_DR_POWER; - else - pd.flags &= ~PD_FLAGS_PARTNER_DR_POWER; - - if (pdo & PDO_FIXED_EXTERNAL) - pd.flags |= PD_FLAGS_PARTNER_EXTPOWER; - else - pd.flags &= ~PD_FLAGS_PARTNER_EXTPOWER; - - if (pdo & PDO_FIXED_COMM_CAP) - pd.flags |= PD_FLAGS_PARTNER_USB_COMM; - else - pd.flags &= ~PD_FLAGS_PARTNER_USB_COMM; -#endif - - if (pdo & PDO_FIXED_DATA_SWAP) - pd.flags |= PD_FLAGS_PARTNER_DR_DATA; - else - pd.flags &= ~PD_FLAGS_PARTNER_DR_DATA; - -#ifdef CONFIG_CHARGE_MANAGER - /* - * Treat device as a dedicated charger (meaning we should charge - * from it) if it does not support power swap, or if it is externally - * powered, or if we are a sink and the device identity matches a - * charging white-list. - */ - /* - if (!(pd.flags & PD_FLAGS_PARTNER_DR_POWER) || - (pd.flags & PD_FLAGS_PARTNER_EXTPOWER) || - charge_whitelisted) - charge_manager_update_dualrole( CAP_DEDICATED); - else - charge_manager_update_dualrole( CAP_DUALROLE); - */ -#endif -} - -static void handle_data_request(uint16_t head, uint32_t *payload) { - int type = PD_HEADER_TYPE(head); - int cnt = PD_HEADER_CNT(head); - - switch (type) { -#ifdef CONFIG_USB_PD_DUAL_ROLE - case PD_DATA_SOURCE_CAP: - if ((pd.task_state == PD_STATE_SNK_DISCOVERY) - || (pd.task_state == PD_STATE_SNK_TRANSITION) -#ifdef CONFIG_USB_PD_VBUS_DETECT_NONE - || (pd.task_state == - PD_STATE_SNK_HARD_RESET_RECOVER) -#endif - || (pd.task_state == PD_STATE_SNK_READY)) { -#ifdef CONFIG_USB_PD_REV30 - /* - * Only adjust sink rev if source rev is higher. - */ - if (PD_HEADER_REV(head) < pd.rev) - pd.rev = PD_HEADER_REV(head); -#endif - /* Port partner is now known to be PD capable */ - pd.flags |= PD_FLAGS_PREVIOUS_PD_CONN; - - /* src cap 0 should be fixed PDO */ - pd_update_pdo_flags(payload[0]); - - pd_process_source_cap(cnt, payload); - - /* Source will resend source cap on failure */ - pd_send_request_msg(1); - - // We call the callback after we send the request - // because the timing on Request seems to be sensitive - // User code can take the time until PS_RDY to do stuff - pd_process_source_cap_callback(cnt, payload); - } - break; -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - case PD_DATA_REQUEST: - - /* the message was incorrect or cannot be satisfied */ - send_control(PD_CTRL_REJECT); - /* keep last contract in place (whether implicit or explicit) */ - set_state(PD_STATE_SRC_READY); - break; - case PD_DATA_BIST: - /* If not in READY state, then don't start BIST */ - if (DUAL_ROLE_IF_ELSE(pd.task_state == PD_STATE_SNK_READY, - pd.task_state == PD_STATE_SRC_READY)) { - /* currently only support sending bist carrier mode 2 */ - if ((payload[0] >> 28) == 5) { - /* bist data object mode is 2 */ - pd_transmit(TCPC_TX_BIST_MODE_2, 0, - NULL); - /* Set to appropriate port disconnected state */ - set_state( - DUAL_ROLE_IF_ELSE(PD_STATE_SNK_DISCONNECTED, - PD_STATE_SRC_DISCONNECTED)); - } - } - break; - case PD_DATA_SINK_CAP: - pd.flags |= PD_FLAGS_SNK_CAP_RECVD; - /* snk cap 0 should be fixed PDO */ - pd_update_pdo_flags(payload[0]); - if (pd.task_state == PD_STATE_SRC_GET_SINK_CAP) - set_state(PD_STATE_SRC_READY); - break; -#ifdef CONFIG_USB_PD_REV30 - case PD_DATA_BATTERY_STATUS: - break; -#endif - case PD_DATA_VENDOR_DEF: - handle_vdm_request(cnt, payload); - break; - default: - CPRINTF("Unhandled data message type %d\n", type); - } -} - -#ifdef CONFIG_USB_PD_DUAL_ROLE -void pd_request_power_swap() { - if (pd.task_state == PD_STATE_SRC_READY) - set_state (PD_STATE_SRC_SWAP_INIT); - else if (pd.task_state == PD_STATE_SNK_READY) - set_state (PD_STATE_SNK_SWAP_INIT); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); -} - -#ifdef CONFIG_USBC_VCONN_SWAP -static void pd_request_vconn_swap() -{ - if (pd.task_state == PD_STATE_SRC_READY || - pd.task_state == PD_STATE_SNK_READY) - set_state( PD_STATE_VCONN_SWAP_SEND); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); -} - -void pd_try_vconn_src() -{ - /* - * If we don't currently provide vconn, and we can supply it, send - * a vconn swap request. - */ - if (!(pd.flags & PD_FLAGS_VCONN_ON)) { - if (pd_check_vconn_swap()) - pd_request_vconn_swap(); - } -} -#endif -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - -void pd_request_data_swap() { - if (DUAL_ROLE_IF_ELSE(pd.task_state == PD_STATE_SNK_READY, - pd.task_state == PD_STATE_SRC_READY)) - set_state(PD_STATE_DR_SWAP); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); -} - -static void pd_set_data_role(int role) { - pd.data_role = role; - pd_execute_data_swap(role); - -#ifdef CONFIG_USBC_SS_MUX -#ifdef CONFIG_USBC_SS_MUX_DFP_ONLY - /* - * Need to connect SS mux for if new data role is DFP. - * If new data role is UFP, then disconnect the SS mux. - */ - if (role == PD_ROLE_DFP) - usb_mux_set( TYPEC_MUX_USB, USB_SWITCH_CONNECT, - pd.polarity); - else - usb_mux_set( TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, - pd.polarity); -#else - usb_mux_set( TYPEC_MUX_USB, USB_SWITCH_CONNECT, - pd.polarity); -#endif -#endif - pd_update_roles(); -} - -static void pd_dr_swap() { - pd_set_data_role(!pd.data_role); - pd.flags |= PD_FLAGS_CHECK_IDENTITY; -} - -static void handle_ctrl_request(uint16_t head, uint32_t *payload) { - int type = PD_HEADER_TYPE(head); - int res; - - switch (type) { - case PD_CTRL_GOOD_CRC: - /* should not get it */ - break; - case PD_CTRL_PING: - /* Nothing else to do */ - break; - case PD_CTRL_GET_SOURCE_CAP: - res = send_source_cap(); - if ((res >= 0) && (pd.task_state == PD_STATE_SRC_DISCOVERY)) - set_state(PD_STATE_SRC_NEGOCIATE); - break; - case PD_CTRL_GET_SINK_CAP: -#ifdef CONFIG_USB_PD_DUAL_ROLE - send_sink_cap(); -#else - send_control(REFUSE(pd.rev)); -#endif - break; -#ifdef CONFIG_USB_PD_DUAL_ROLE - case PD_CTRL_GOTO_MIN: -#ifdef CONFIG_USB_PD_GIVE_BACK - if (pd.task_state == PD_STATE_SNK_READY) { - /* - * Reduce power consumption now! - * - * The source will restore power to this sink - * by sending a new source cap message at a - * later time. - */ - pd_snk_give_back( &pd.curr_limit, - &pd.supply_voltage); - set_state( PD_STATE_SNK_TRANSITION); - } -#endif - - break; - case PD_CTRL_PS_RDY: - if (pd.task_state == PD_STATE_SNK_SWAP_SRC_DISABLE) { - set_state (PD_STATE_SNK_SWAP_STANDBY); - } else if (pd.task_state == PD_STATE_SRC_SWAP_STANDBY) { - /* reset message ID and swap roles */ - pd.msg_id = 0; - pd.power_role = PD_ROLE_SINK; - pd_update_roles(); - set_state (PD_STATE_SNK_DISCOVERY); -#ifdef CONFIG_USBC_VCONN_SWAP - } else if (pd.task_state == PD_STATE_VCONN_SWAP_INIT) { - /* - * If VCONN is on, then this PS_RDY tells us it's - * ok to turn VCONN off - */ - if (pd.flags & PD_FLAGS_VCONN_ON) - set_state( PD_STATE_VCONN_SWAP_READY); -#endif - } else if (pd.task_state == PD_STATE_SNK_DISCOVERY) { - /* Don't know what power source is ready. Reset. */ - set_state(PD_STATE_HARD_RESET_SEND); - } else if (pd.task_state == PD_STATE_SNK_SWAP_STANDBY) { - /* Do nothing, assume this is a redundant PD_RDY */ - } else if (pd.power_role == PD_ROLE_SINK) { - set_state (PD_STATE_SNK_READY); - pd_set_input_current_limit(pd.curr_limit, - pd.supply_voltage); -#ifdef CONFIG_CHARGE_MANAGER - /* Set ceiling based on what's negotiated */ - //charge_manager_set_ceil( - // CEIL_REQUESTOR_PD, - // pd.curr_limit); -#endif - } - break; -#endif - case PD_CTRL_REJECT: - case PD_CTRL_WAIT: - if (pd.task_state == PD_STATE_DR_SWAP) - set_state(READY_RETURN_STATE()); -#ifdef CONFIG_USBC_VCONN_SWAP - else if (pd.task_state == PD_STATE_VCONN_SWAP_SEND) - set_state( READY_RETURN_STATE()); -#endif -#ifdef CONFIG_USB_PD_DUAL_ROLE - else if (pd.task_state == PD_STATE_SRC_SWAP_INIT) - set_state(PD_STATE_SRC_READY); - else if (pd.task_state == PD_STATE_SNK_SWAP_INIT) - set_state (PD_STATE_SNK_READY); - else if (pd.task_state == PD_STATE_SNK_REQUESTED) { - /* - * Explicit Contract in place - * - * On reception of a WAIT message, transition to - * PD_STATE_SNK_READY after PD_T_SINK_REQUEST ms to - * send another reqest. - * - * On reception of a REJECT messag, transition to - * PD_STATE_SNK_READY but don't resend the request. - * - * NO Explicit Contract in place - * - * On reception of a WAIT or REJECT message, - * transition to PD_STATE_SNK_DISCOVERY - */ - if (pd.flags & PD_FLAGS_EXPLICIT_CONTRACT) { - /* We have an explicit contract */ - if (type == PD_CTRL_WAIT) { - /* - * Trigger a new power request when - * we enter PD_STATE_SNK_READY - */ - pd.new_power_request = 1; - - /* - * After the request is triggered, - * make sure the request is sent. - */ - pd.prev_request_mv = 0; - - /* - * Transition to PD_STATE_SNK_READY - * after PD_T_SINK_REQUEST ms. - */ - set_state_timeout(get_time().val + - PD_T_SINK_REQUEST, PD_STATE_SNK_READY); - } else { - /* The request was rejected */ - set_state(PD_STATE_SNK_READY); - } - } else { - /* No explicit contract */ - set_state (PD_STATE_SNK_DISCOVERY); - } - } -#endif - break; - case PD_CTRL_ACCEPT: - if (pd.task_state == PD_STATE_SOFT_RESET) { - /* - * For the case that we sent soft reset in SNK_DISCOVERY - * on startup due to VBUS never low, clear the flag. - */ - pd.flags &= ~PD_FLAGS_VBUS_NEVER_LOW; - execute_soft_reset(); - } else if (pd.task_state == PD_STATE_DR_SWAP) { - /* switch data role */ - pd_dr_swap(); - set_state(READY_RETURN_STATE()); -#ifdef CONFIG_USB_PD_DUAL_ROLE -#ifdef CONFIG_USBC_VCONN_SWAP - } else if (pd.task_state == PD_STATE_VCONN_SWAP_SEND) { - /* switch vconn */ - set_state( PD_STATE_VCONN_SWAP_INIT); -#endif - } else if (pd.task_state == PD_STATE_SRC_SWAP_INIT) { - /* explicit contract goes away for power swap */ - pd.flags &= ~PD_FLAGS_EXPLICIT_CONTRACT; - set_state (PD_STATE_SRC_SWAP_SNK_DISABLE); - } else if (pd.task_state == PD_STATE_SNK_SWAP_INIT) { - /* explicit contract goes away for power swap */ - pd.flags &= ~PD_FLAGS_EXPLICIT_CONTRACT; - set_state (PD_STATE_SNK_SWAP_SNK_DISABLE); - } else if (pd.task_state == PD_STATE_SNK_REQUESTED) { - /* explicit contract is now in place */ - pd.flags |= PD_FLAGS_EXPLICIT_CONTRACT; -#ifdef CONFIG_BBRAM - pd_set_saved_active( 1); -#endif - set_state (PD_STATE_SNK_TRANSITION); -#endif - } - break; - case PD_CTRL_SOFT_RESET: - execute_soft_reset(); - /* We are done, acknowledge with an Accept packet */ - send_control(PD_CTRL_ACCEPT); - break; - case PD_CTRL_PR_SWAP: -#ifdef CONFIG_USB_PD_DUAL_ROLE - if (pd_check_power_swap()) { - send_control(PD_CTRL_ACCEPT); - /* - * Clear flag for checking power role to avoid - * immediately requesting another swap. - */ - pd.flags &= ~PD_FLAGS_CHECK_PR_ROLE; - set_state( - DUAL_ROLE_IF_ELSE(PD_STATE_SNK_SWAP_SNK_DISABLE, - PD_STATE_SRC_SWAP_SNK_DISABLE)); - } else { - send_control(REFUSE(pd.rev)); - } -#else - send_control(REFUSE(pd.rev)); -#endif - break; - case PD_CTRL_DR_SWAP: - if (pd_check_data_swap(pd.data_role)) { - /* - * Accept switch and perform data swap. Clear - * flag for checking data role to avoid - * immediately requesting another swap. - */ - pd.flags &= ~PD_FLAGS_CHECK_DR_ROLE; - if (send_control(PD_CTRL_ACCEPT) >= 0) - pd_dr_swap(); - } else { - send_control(REFUSE(pd.rev)); - - } - break; - case PD_CTRL_VCONN_SWAP: -#ifdef CONFIG_USBC_VCONN_SWAP - if (pd.task_state == PD_STATE_SRC_READY || - pd.task_state == PD_STATE_SNK_READY) { - if (pd_check_vconn_swap()) { - if (send_control( PD_CTRL_ACCEPT) > 0) - set_state( - PD_STATE_VCONN_SWAP_INIT); - } else { - send_control( REFUSE(pd.rev)); - } - } -#else - send_control(REFUSE(pd.rev)); -#endif - break; - default: -#ifdef CONFIG_USB_PD_REV30 - send_control( PD_CTRL_NOT_SUPPORTED); -#endif - CPRINTF("Unhandled ctrl message type %d\n", type); - } -} - -#ifdef CONFIG_USB_PD_REV30 -static void handle_ext_request( uint16_t head, uint32_t *payload) -{ - int type = PD_HEADER_TYPE(head); - - switch (type) { - case PD_EXT_GET_BATTERY_CAP: - send_battery_cap( payload); - break; - case PD_EXT_GET_BATTERY_STATUS: - send_battery_status( payload); - break; - case PD_EXT_BATTERY_CAP: - break; - default: - send_control( PD_CTRL_NOT_SUPPORTED); - } -} -#endif - -static void handle_request(uint16_t head, uint32_t *payload) { - int cnt = PD_HEADER_CNT(head); - int p; - - /* dump received packet content (only dump ping at debug level 3) */ - if ((debug_level == 2 && PD_HEADER_TYPE(head) != PD_CTRL_PING) - || debug_level >= 3) { - CPRINTF("RECV %04x/%d ", head, cnt); - for (p = 0; p < cnt; p++) - CPRINTF("[%d]%08x ", p, payload[p]);CPRINTF("\n"); - } - - /* - * If we are in disconnected state, we shouldn't get a request. - * Ignore it if we get one. - */ - if (!pd_is_connected()) - return; - -#ifdef CONFIG_USB_PD_REV30 - /* Check if this is an extended chunked data message. */ - if (pd.rev == PD_REV30 && PD_HEADER_EXT(head)) { - handle_ext_request( head, payload); - return; - } -#endif - if (cnt) - handle_data_request(head, payload); - else - handle_ctrl_request(head, payload); -} - -void pd_send_vdm(uint32_t vid, int cmd, const uint32_t *data, int count) { - if (count > VDO_MAX_SIZE - 1) { - CPRINTF("VDM over max size\n"); - return; - } - - /* set VDM header with VID & CMD */ - pd.vdo_data[0] = - VDO(vid, - ((vid & USB_SID_PD) == USB_SID_PD) ? 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), - cmd); -#ifdef CONFIG_USB_PD_REV30 - pd.vdo_data[0] |= VDO_SVDM_VERS(vdo_ver[pd.rev]); -#endif - queue_vdm(pd.vdo_data, data, count); - - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); -} - -static inline int pdo_busy() { - /* - * Note, main PDO state machine (pd_task) uses READY state exclusively - * to denote port partners have successfully negociated a contract. All - * other protocol actions force state transitions. - */ - int rv = (pd.task_state != PD_STATE_SRC_READY); -#ifdef CONFIG_USB_PD_DUAL_ROLE - rv &= (pd.task_state != PD_STATE_SNK_READY); -#endif - return rv; -} - -static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr) { - uint64_t timeout; - int cmd = PD_VDO_CMD(vdm_hdr); - - /* its not a structured VDM command */ - if (!PD_VDO_SVDM(vdm_hdr)) - return 500 * MSEC; - - switch (PD_VDO_CMDT(vdm_hdr)) { - case CMDT_INIT: - if ((cmd == CMD_ENTER_MODE) || (cmd == CMD_EXIT_MODE)) - timeout = PD_T_VDM_WAIT_MODE_E; - else - timeout = PD_T_VDM_SNDR_RSP; - break; - default: - if ((cmd == CMD_ENTER_MODE) || (cmd == CMD_EXIT_MODE)) - timeout = PD_T_VDM_E_MODE; - else - timeout = PD_T_VDM_RCVR_RSP; - break; - } - return timeout; -} - -static void pd_vdm_send_state_machine() { - int res; - uint16_t header; - - switch (pd.vdm_state) { - case VDM_STATE_READY: - /* Only transmit VDM if connected. */ - if (!pd_is_connected()) { - pd.vdm_state = VDM_STATE_ERR_BUSY; - break; - } - - /* - * if there's traffic or we're not in PDO ready state don't send - * a VDM. - */ - if (pdo_busy()) - break; - - /* Prepare and send VDM */ - header = PD_HEADER(PD_DATA_VENDOR_DEF, pd.power_role, pd.data_role, - pd.msg_id, (int )pd.vdo_count, pd_get_rev(), 0); - res = pd_transmit(TCPC_TX_SOP, header, pd.vdo_data); - if (res < 0) { - pd.vdm_state = VDM_STATE_ERR_SEND; - } else { - pd.vdm_state = VDM_STATE_BUSY; - pd.vdm_timeout.val = get_time().val - + vdm_get_ready_timeout(pd.vdo_data[0]); - } - break; - case VDM_STATE_WAIT_RSP_BUSY: - /* wait and then initiate request again */ - if (get_time().val > pd.vdm_timeout.val) { - pd.vdo_data[0] = pd.vdo_retry; - pd.vdo_count = 1; - pd.vdm_state = VDM_STATE_READY; - } - break; - case VDM_STATE_BUSY: - /* Wait for VDM response or timeout */ - if (pd.vdm_timeout.val && (get_time().val > pd.vdm_timeout.val)) { - pd.vdm_state = VDM_STATE_ERR_TMOUT; - } - break; - default: - break; - } -} - -#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO -static inline void pd_dev_dump_info(uint16_t dev_id, uint8_t *hash) -{ - int j; - ccprintf("DevId:%d.%d Hash:", HW_DEV_ID_MAJ(dev_id), - HW_DEV_ID_MIN(dev_id)); - for (j = 0; j < PD_RW_HASH_SIZE; j += 4) { - ccprintf(" 0x%02x%02x%02x%02x", hash[j + 3], hash[j + 2], - hash[j + 1], hash[j]); - } - ccprintf("\n"); -} -#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */ - -int pd_dev_store_rw_hash(uint16_t dev_id, uint32_t *rw_hash, - uint32_t current_image) { -#ifdef CONFIG_COMMON_RUNTIME - int i; -#endif - -#ifdef CONFIG_USB_PD_CHROMEOS - pd.dev_id = dev_id; - memcpy(pd.dev_rw_hash, rw_hash, PD_RW_HASH_SIZE); -#endif -#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO - if (debug_level >= 2) - pd_dev_dump_info(dev_id, (uint8_t *)rw_hash); -#endif -#ifdef CONFIG_USB_PD_CHROMEOS - pd.current_image = current_image; -#endif - -#ifdef CONFIG_COMMON_RUNTIME - /* Search table for matching device / hash */ - for (i = 0; i < RW_HASH_ENTRIES; i++) - if (dev_id == rw_hash_table[i].dev_id) - return !memcmp(rw_hash, - rw_hash_table[i].dev_rw_hash, - PD_RW_HASH_SIZE); -#endif - return 0; -} - -#ifdef CONFIG_USB_PD_DUAL_ROLE -enum pd_dual_role_states pd_get_dual_role(void) { - return drp_state; -} - -#ifdef CONFIG_USB_PD_TRY_SRC -static void pd_update_try_source(void) -{ - int i; - -#ifndef CONFIG_CHARGER - int batt_soc = board_get_battery_soc(); -#else - int batt_soc = charge_get_percent(); -#endif - - /* - * Enable try source when dual-role toggling AND battery is present - * and at some minimum percentage. - */ - pd_try_src_enable = drp_state == PD_DRP_TOGGLE_ON && - batt_soc >= CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC; -#if defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \ - defined(CONFIG_BATTERY_PRESENT_GPIO) - /* - * When battery is cutoff in ship mode it may not be reliable to - * check if battery is present with its state of charge. - * Also check if battery is initialized and ready to provide power. - */ - pd_try_src_enable &= (battery_is_present() == BP_YES); -#endif - - /* - * Clear this flag to cover case where a TrySrc - * mode went from enabled to disabled and trying_source - * was active at that time. - */ - for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) - pd[i].flags &= ~PD_FLAGS_TRY_SRC; - -} -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pd_update_try_source, HOOK_PRIO_DEFAULT); -#endif - -void pd_set_dual_role(enum pd_dual_role_states state) { - int i; - drp_state = state; - -#ifdef CONFIG_USB_PD_TRY_SRC - pd_update_try_source(); -#endif - - /* Inform PD tasks of dual role change. */ - for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) - // getting rid of task stuff - //task_set_event(PD_PORT_TO_TASK_ID(i), - // PD_EVENT_UPDATE_DUAL_ROLE, 0); - ; -} - -void pd_update_dual_role_config() { - /* - * Change to sink if port is currently a source AND (new DRP - * state is force sink OR new DRP state is either toggle off - * or debug accessory toggle only and we are in the source - * disconnected state). - */ - if (pd.power_role == PD_ROLE_SOURCE - && ((drp_state == PD_DRP_FORCE_SINK && !pd_ts_dts_plugged()) - || (drp_state == PD_DRP_TOGGLE_OFF - && pd.task_state == PD_STATE_SRC_DISCONNECTED))) { - pd.power_role = PD_ROLE_SINK; - set_state (PD_STATE_SNK_DISCONNECTED); - tcpm_set_cc(TYPEC_CC_RD); - /* Make sure we're not sourcing VBUS. */ - pd_power_supply_reset(); - } - - /* - * Change to source if port is currently a sink and the - * new DRP state is force source. - */ - if (pd.power_role == PD_ROLE_SINK - && drp_state == PD_DRP_FORCE_SOURCE) { - pd.power_role = PD_ROLE_SOURCE; - set_state(PD_STATE_SRC_DISCONNECTED); - tcpm_set_cc(TYPEC_CC_RP); - } - -#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \ - defined(CONFIG_USB_PD_TCPC_LOW_POWER) - /* When switching drp mode, make sure tcpc is out of standby mode */ - tcpm_set_drp_toggle( 0); -#endif -} - -int pd_get_role() { - return pd.power_role; -} - -static int pd_is_power_swapping() { - /* return true if in the act of swapping power roles */ - return pd.task_state == PD_STATE_SNK_SWAP_SNK_DISABLE - || pd.task_state == PD_STATE_SNK_SWAP_SRC_DISABLE - || pd.task_state == PD_STATE_SNK_SWAP_STANDBY - || pd.task_state == PD_STATE_SNK_SWAP_COMPLETE - || pd.task_state == PD_STATE_SRC_SWAP_SNK_DISABLE - || pd.task_state == PD_STATE_SRC_SWAP_SRC_DISABLE - || pd.task_state == PD_STATE_SRC_SWAP_STANDBY; -} - -/* - * Provide Rp to ensure the partner port is in a known state (eg. not - * PD negotiated, not sourcing 20V). - */ -static void pd_partner_port_reset() { - uint64_t timeout; - -#ifdef CONFIG_BBRAM - /* - * Check our battery-backed previous port state. If PD comms were - * active, and we didn't just lose power, make sure we - * don't boot into RO with a pre-existing power contract. - */ - if (!pd_get_saved_active() || - system_get_image_copy() != SYSTEM_IMAGE_RO || - system_get_reset_flags() & - (RESET_FLAG_BROWNOUT | RESET_FLAG_POWER_ON)) - return; -#endif // CONFIG_BBRAM - /* Provide Rp for 100 msec. or until we no longer have VBUS. */ - tcpm_set_cc(TYPEC_CC_RP); - timeout = get_time().val + 100 * MSEC; - - while (get_time().val < timeout && pd_is_vbus_present()) - msleep(10); -#ifdef CONFIG_BBRAM - pd_set_saved_active( 0); -#endif -} -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - -int pd_get_polarity() { - return pd.polarity; -} - -int pd_get_partner_data_swap_capable() { - /* return data swap capable status of port partner */ - return pd.flags & PD_FLAGS_PARTNER_DR_DATA; -} - -#ifdef CONFIG_COMMON_RUNTIME -void pd_comm_enable( int enable) -{ - /* We don't check port >= CONFIG_USB_PD_PORT_COUNT deliberately */ - pd_comm_enabled[port] = enable; - - /* If type-C connection, then update the TCPC RX enable */ - if (pd_is_connected()) - tcpm_set_rx_enable( enable); - -#ifdef CONFIG_USB_PD_DUAL_ROLE - /* - * If communications are enabled, start hard reset timer for - * any port in PD_SNK_DISCOVERY. - */ - if (enable && pd.task_state == PD_STATE_SNK_DISCOVERY) - set_state_timeout( - get_time().val + PD_T_SINK_WAIT_CAP, - PD_STATE_HARD_RESET_SEND); -#endif -} -#endif - -void pd_ping_enable(int enable) { - if (enable) - pd.flags |= PD_FLAGS_PING_ENABLED; - else - pd.flags &= ~PD_FLAGS_PING_ENABLED; -} - -/** - * 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_SNK_DEF) || (cc == TYPEC_CC_VOLT_SNK_1_5) - || (cc == TYPEC_CC_VOLT_SNK_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 int get_snk_polarity(int cc1, int cc2) { - /* the following assumes: - * TYPEC_CC_VOLT_SNK_3_0 > TYPEC_CC_VOLT_SNK_1_5 - * TYPEC_CC_VOLT_SNK_1_5 > TYPEC_CC_VOLT_SNK_DEF - * TYPEC_CC_VOLT_SNK_DEF > TYPEC_CC_VOLT_OPEN - */ - return (cc2 > cc1); -} - -#if defined(CONFIG_CHARGE_MANAGER) -/** - * Returns type C current limit (mA) based upon cc_voltage (mV). - */ -static typec_current_t get_typec_current_limit(int polarity, int cc1, int cc2) { - typec_current_t charge; - int cc = polarity ? cc2 : cc1; - int cc_alt = polarity ? cc1 : cc2; - - if (cc == TYPEC_CC_VOLT_SNK_3_0 && cc_alt != TYPEC_CC_VOLT_SNK_1_5) - charge = 3000; - else if (cc == TYPEC_CC_VOLT_SNK_1_5) - charge = 1500; - else - charge = 0; - - if (cc_is_rp(cc_alt)) - charge |= TYPEC_CURRENT_DTS_MASK; - - return charge; -} - -/** - * Signal power request to indicate a charger update that affects the port. - */ -void pd_set_new_power_request() { -// pd.new_power_request = 1; - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); -} -#endif /* CONFIG_CHARGE_MANAGER */ - -#if defined(CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP) && defined(CONFIG_USBC_SS_MUX) -/* - * Backwards compatible DFP does not support USB SS because it applies VBUS - * before debouncing CC and setting USB SS muxes, but SS detection will fail - * before we are done debouncing CC. - */ -#error "Backwards compatible DFP does not support USB" -#endif - -#ifdef CONFIG_COMMON_RUNTIME - -/* Initialize globals based on system state. */ -static void pd_init_tasks(void) -{ - static int initialized; - int enable = 1; - int i; - - /* Initialize globals once, for all PD tasks. */ - if (initialized) - return; - -#if defined(HAS_TASK_CHIPSET) && defined(CONFIG_USB_PD_DUAL_ROLE) - /* Set dual-role state based on chipset power state */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) - drp_state = PD_DRP_FORCE_SINK; - else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) - drp_state = PD_DRP_TOGGLE_OFF; - else /* CHIPSET_STATE_ON */ - drp_state = PD_DRP_TOGGLE_ON; -#endif - -#if defined(CONFIG_USB_PD_COMM_DISABLED) - enable = 0; -#elif defined(CONFIG_USB_PD_COMM_LOCKED) - /* Disable PD communication at init if we're in RO and locked. */ - if (!system_is_in_rw() && system_is_locked()) - enable = 0; -#endif - for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) - pd_comm_enabled[i] = enable; - CPRINTS("PD comm %sabled", enable ? "en" : "dis"); - - initialized = 1; -} -#endif /* CONFIG_COMMON_RUNTIME */ - -#ifndef CONFIG_USB_PD_TCPC -static int pd_restart_tcpc() { - if (board_set_tcpc_power_mode) { - /* force chip reset */ - board_set_tcpc_power_mode(0); - } - return tcpm_init(); -} -#endif - -void pd_init() { -#ifdef CONFIG_COMMON_RUNTIME - pd_init_tasks(); -#endif - - /* Ensure the power supply is in the default state */ - pd_power_supply_reset(); - -#ifdef CONFIG_USB_PD_TCPC_BOARD_INIT - /* Board specific TCPC init */ - board_tcpc_init(); -#endif - - /* Initialize TCPM driver and wait for TCPC to be ready */ - res = tcpm_init(); - -#ifdef CONFIG_USB_PD_DUAL_ROLE - //pd_partner_port_reset(); -#endif - - CPRINTS("TCPC p%d init %s", port, res ? "failed" : "ready"); - this_state = res ? PD_STATE_SUSPENDED : PD_DEFAULT_STATE(); -#ifndef CONFIG_USB_PD_TCPC - if (!res) { - struct ec_response_pd_chip_info *info; - tcpm_get_chip_info(0, &info); - CPRINTS("TCPC p%d VID:0x%x PID:0x%x DID:0x%x FWV:0x%lx", - port, info->vendor_id, info->product_id, - info->device_id, info->fw_version_number); - } -#endif - -#ifdef CONFIG_USB_PD_REV30 - /* Set Revision to highest */ - pd.rev = PD_REV30; - pd_ca_reset(); -#endif - -#ifdef CONFIG_USB_PD_DUAL_ROLE - /* - * If VBUS is high, then initialize flag for VBUS has always been - * present. This flag is used to maintain a PD connection after a - * reset by sending a soft reset. - */ - //pd.flags = pd_is_vbus_present() ? PD_FLAGS_VBUS_NEVER_LOW : 0; - pd.flags = 0; -#endif - - /* Disable TCPC RX until connection is established */ - tcpm_set_rx_enable(0); - -#ifdef CONFIG_USBC_SS_MUX - /* Initialize USB mux to its default state */ - usb_mux_init(); -#endif - - /* Initialize PD protocol state variables for each port. */ - pd.power_role = PD_ROLE_DEFAULT(); - pd.vdm_state = VDM_STATE_DONE; - set_state(this_state); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - ASSERT(PD_ROLE_DEFAULT() == PD_ROLE_SINK); - tcpm_select_rp_value( CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT); -#else - tcpm_select_rp_value( CONFIG_USB_PD_PULLUP); -#endif - tcpm_set_cc( - PD_ROLE_DEFAULT() == PD_ROLE_SOURCE ? TYPEC_CC_RP : TYPEC_CC_RD); - -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - /* Initialize PD Policy engine */ - pd_dfp_pe_init(); -#endif - -#ifdef CONFIG_CHARGE_MANAGER - /* Initialize PD and type-C supplier current limits to 0 */ - pd_set_input_current_limit(0, 0); - //typec_set_input_current_limit( 0, 0); - //charge_manager_update_dualrole( CAP_UNKNOWN); -#endif -} - -void pd_run_state_machine() { -#ifdef CONFIG_USB_PD_REV30 - /* send any pending messages */ - pd_ca_send_pending(); -#endif - /* process VDM messages last */ - pd_vdm_send_state_machine(); - - /* Verify board specific health status : current, voltages... */ - res = pd_board_checks(); - if (res != EC_SUCCESS) { - /* cut the power */ - pd_execute_hard_reset(); - /* notify the other side of the issue */ - pd_transmit(TCPC_TX_HARD_RESET, 0, NULL); - } - - /* wait for next event/packet or timeout expiration */ - // getting rid of task stuff - //evt = task_wait_event(timeout); -#ifdef CONFIG_USB_PD_DUAL_ROLE - if (evt & PD_EVENT_UPDATE_DUAL_ROLE) - pd_update_dual_role_config(); -#endif - -#ifdef CONFIG_USB_PD_TCPC - /* - * run port controller task to check CC and/or read incoming - * messages - */ - tcpc_run( evt); -#else - /* if TCPC has reset, then need to initialize it again */ - if (evt & PD_EVENT_TCPC_RESET) { - CPRINTS("TCPC p%d reset!", port); - if (tcpm_init() != EC_SUCCESS) - CPRINTS("TCPC p%d init failed", port); -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - } - - if ((evt & PD_EVENT_TCPC_RESET) && - (pd.task_state != PD_STATE_DRP_AUTO_TOGGLE)) { -#endif - /* Ensure CC termination is default */ - tcpm_set_cc( PD_ROLE_DEFAULT() == - PD_ROLE_SOURCE ? TYPEC_CC_RP : TYPEC_CC_RD); - - /* - * If we have a stable contract in the default role, - * then simply update TCPC with some missing info - * so that we can continue without resetting PD comms. - * Otherwise, go to the default disconnected state - * and force renegotiation. - */ - if (pd.vdm_state == VDM_STATE_DONE - && ( -#ifdef CONFIG_USB_PD_DUAL_ROLE - (PD_ROLE_DEFAULT() == PD_ROLE_SINK - && pd.task_state == PD_STATE_SNK_READY) - || -#endif - (PD_ROLE_DEFAULT() == PD_ROLE_SOURCE - && pd.task_state == PD_STATE_SRC_READY))) { - tcpm_set_polarity(pd.polarity); - tcpm_set_msg_header(pd.power_role, pd.data_role); - tcpm_set_rx_enable(1); - } else { - /* Ensure state variables are at default */ - pd.power_role = PD_ROLE_DEFAULT(); - pd.vdm_state = VDM_STATE_DONE; - set_state(PD_DEFAULT_STATE()); - } - } -#endif - - /* process any potential incoming message */ - incoming_packet = evt & PD_EVENT_RX; - //if (incoming_packet) { - if (!tcpm_get_message(payload, &head)) - handle_request(head, payload); - //} - - if (pd.req_suspend_state) - set_state(PD_STATE_SUSPENDED); - - /* if nothing to do, verify the state of the world in 500ms */ - this_state = pd.task_state; - timeout = 500 * MSEC; - switch (this_state) { - case PD_STATE_DISABLED: - /* Nothing to do */ - break; - case PD_STATE_SRC_DISCONNECTED: - timeout = 10 * MSEC; - tcpm_get_cc(&cc1, &cc2); -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - /* - * Attempt TCPC auto DRP toggle if it is - * not already auto toggling and not try.src - */ - if (auto_toggle_supported && - !(pd.flags & PD_FLAGS_TCPC_DRP_TOGGLE) && - !(pd.flags & PD_FLAGS_TRY_SRC) && - (cc1 == TYPEC_CC_VOLT_OPEN && - cc2 == TYPEC_CC_VOLT_OPEN)) { - set_state( PD_STATE_DRP_AUTO_TOGGLE); - timeout = 2*MSEC; - break; - } -#endif - - /* Vnc monitoring */ - if ((cc1 == TYPEC_CC_VOLT_RD || cc2 == TYPEC_CC_VOLT_RD) - || (cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_RA)) { -#ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP - /* Enable VBUS */ - if (pd_set_power_supply_ready()) - break; -#endif - pd.cc_state = PD_CC_NONE; - set_state(PD_STATE_SRC_DISCONNECTED_DEBOUNCE); - } -#if defined(CONFIG_USB_PD_DUAL_ROLE) - /* - * Try.SRC state is embedded here. Wait for SNK - * detect, or if timer expires, transition to - * SNK_DISCONNETED. - * - * If Try.SRC state is not active, then this block - * handles the normal DRP toggle from SRC->SNK - */ - else if ((pd.flags & PD_FLAGS_TRY_SRC - && get_time().val >= pd.try_src_marker) - || (!(pd.flags & PD_FLAGS_TRY_SRC) - && drp_state != PD_DRP_FORCE_SOURCE - && drp_state != PD_DRP_FREEZE - && get_time().val >= next_role_swap)) { - pd.power_role = PD_ROLE_SINK; - set_state (PD_STATE_SNK_DISCONNECTED); - tcpm_set_cc(TYPEC_CC_RD); - next_role_swap = get_time().val + PD_T_DRP_SNK; - pd.try_src_marker = get_time().val + PD_T_TRY_WAIT; - - /* Swap states quickly */ - timeout = 2 * MSEC; - } -#endif - break; - case PD_STATE_SRC_DISCONNECTED_DEBOUNCE: - timeout = 20 * MSEC; - tcpm_get_cc(&cc1, &cc2); - - if (cc1 == TYPEC_CC_VOLT_RD && cc2 == TYPEC_CC_VOLT_RD) { - /* Debug accessory */ - new_cc_state = PD_CC_DEBUG_ACC; - } else if (cc1 == TYPEC_CC_VOLT_RD || cc2 == TYPEC_CC_VOLT_RD) { - /* UFP attached */ - new_cc_state = PD_CC_UFP_ATTACHED; - } else if (cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_RA) { - /* Audio accessory */ - new_cc_state = PD_CC_AUDIO_ACC; - } else { - /* No UFP */ - set_state(PD_STATE_SRC_DISCONNECTED); - timeout = 5 * MSEC; - break; - } - /* If in Try.SRC state, then don't need to debounce */ - if (!(pd.flags & PD_FLAGS_TRY_SRC)) { - /* Debounce the cc state */ - if (new_cc_state != pd.cc_state) { - pd.cc_debounce = get_time().val + - PD_T_CC_DEBOUNCE; - pd.cc_state = new_cc_state; - break; - } else if (get_time().val < pd.cc_debounce) { - break; - } - } - - /* Debounce complete */ - /* UFP is attached */ - if (new_cc_state == PD_CC_UFP_ATTACHED - || new_cc_state == PD_CC_DEBUG_ACC) { - pd.polarity = (cc1 != TYPEC_CC_VOLT_RD); - tcpm_set_polarity(pd.polarity); - - /* initial data role for source is DFP */ - pd_set_data_role( PD_ROLE_DFP); - - if (new_cc_state == PD_CC_DEBUG_ACC) - pd.flags |= - PD_FLAGS_TS_DTS_PARTNER; - -#ifndef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP - /* Enable VBUS */ - if (pd_set_power_supply_ready()) { -#ifdef CONFIG_USBC_SS_MUX - usb_mux_set( TYPEC_MUX_NONE, - USB_SWITCH_DISCONNECT, - pd.polarity); -#endif - break; - } -#endif - /* If PD comm is enabled, enable TCPC RX */ - if (pd_comm_is_enabled()) - tcpm_set_rx_enable(1); - -#ifdef CONFIG_USBC_VCONN - tcpm_set_vconn( 1); - pd.flags |= PD_FLAGS_VCONN_ON; -#endif - - pd.flags |= PD_FLAGS_CHECK_PR_ROLE | - PD_FLAGS_CHECK_DR_ROLE; - hard_reset_count = 0; - timeout = 5 * MSEC; - set_state(PD_STATE_SRC_STARTUP); - } - /* - * AUDIO_ACC will remain in this state indefinitely - * until disconnect. - */ - break; - case PD_STATE_SRC_HARD_RESET_RECOVER: - /* Do not continue until hard reset recovery time */ - if (get_time().val < pd.src_recover) { - timeout = 50 * MSEC; - break; - } - - /* Enable VBUS */ - timeout = 10 * MSEC; - if (pd_set_power_supply_ready()) { - set_state(PD_STATE_SRC_DISCONNECTED); - break; - } -#ifdef CONFIG_USB_PD_TCPM_TCPCI - /* - * After transmitting hard reset, TCPM writes - * to RECEIVE_DETECT register to enable - * PD message passing. - */ - if (pd_comm_is_enabled()) - tcpm_set_rx_enable( 1); -#endif /* CONFIG_USB_PD_TCPM_TCPCI */ - - set_state(PD_STATE_SRC_STARTUP); - break; - case PD_STATE_SRC_STARTUP: - /* Wait for power source to enable */ - if (pd.last_state != pd.task_state) { - pd.flags |= PD_FLAGS_CHECK_IDENTITY; - /* reset various counters */ - caps_count = 0; - pd.msg_id = 0; - snk_cap_count = 0; - set_state_timeout( -#ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP - /* - * delay for power supply to start up. - * subtract out debounce time if coming - * from debounce state since vbus is - * on during debounce. - */ - get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY - - (pd.last_state == - PD_STATE_SRC_DISCONNECTED_DEBOUNCE - ? PD_T_CC_DEBOUNCE : 0), -#else - get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY, -#endif - PD_STATE_SRC_DISCOVERY); - } - break; - case PD_STATE_SRC_DISCOVERY: - if (pd.last_state != pd.task_state) { - /* - * If we have had PD connection with this port - * partner, then start NoResponseTimer. - */ - if (pd.flags & PD_FLAGS_PREVIOUS_PD_CONN) - set_state_timeout(get_time().val + - PD_T_NO_RESPONSE, - hard_reset_count < - PD_HARD_RESET_COUNT ? - PD_STATE_HARD_RESET_SEND : - PD_STATE_SRC_DISCONNECTED); - } - - /* Send source cap some minimum number of times */ - if (caps_count < PD_CAPS_COUNT) { - /* Query capabilities of the other side */ - res = send_source_cap(); - /* packet was acked => PD capable device) */ - if (res >= 0) { - set_state(PD_STATE_SRC_NEGOCIATE); - timeout = 10 * MSEC; - hard_reset_count = 0; - caps_count = 0; - /* Port partner is PD capable */ - pd.flags |= - PD_FLAGS_PREVIOUS_PD_CONN; - } else { /* failed, retry later */ - timeout = PD_T_SEND_SOURCE_CAP; - caps_count++; - } - } - break; - case PD_STATE_SRC_NEGOCIATE: - /* wait for a "Request" message */ - if (pd.last_state != pd.task_state) - set_state_timeout(get_time().val + - PD_T_SENDER_RESPONSE, PD_STATE_HARD_RESET_SEND); - break; - case PD_STATE_SRC_ACCEPTED: - /* Accept sent, wait for enabling the new voltage */ - if (pd.last_state != pd.task_state) - set_state_timeout(get_time().val + - PD_T_SINK_TRANSITION, PD_STATE_SRC_POWERED); - break; - case PD_STATE_SRC_POWERED: - /* Switch to the new requested voltage */ - if (pd.last_state != pd.task_state) { - pd_transition_voltage(pd.requested_idx); - set_state_timeout(get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY, PD_STATE_SRC_TRANSITION); - } - break; - case PD_STATE_SRC_TRANSITION: - /* the voltage output is good, notify the source */ - res = send_control(PD_CTRL_PS_RDY); - if (res >= 0) { - timeout = 10 * MSEC; - /* it'a time to ping regularly the sink */ - set_state(PD_STATE_SRC_READY); - } else { - /* The sink did not ack, cut the power... */ - set_state(PD_STATE_SRC_DISCONNECTED); - } - break; - case PD_STATE_SRC_READY: - timeout = PD_T_SOURCE_ACTIVITY; - - /* - * Don't send any PD traffic if we woke up due to - * incoming packet or if VDO response pending to avoid - * collisions. - */ - if (incoming_packet || (pd.vdm_state == VDM_STATE_BUSY)) - break; - - /* Send updated source capabilities to our partner */ - if (pd.flags & PD_FLAGS_UPDATE_SRC_CAPS) { - res = send_source_cap(); - if (res >= 0) { - set_state(PD_STATE_SRC_NEGOCIATE); - pd.flags &= ~PD_FLAGS_UPDATE_SRC_CAPS; - } - break; - } - - /* Send get sink cap if haven't received it yet */ - if (!(pd.flags & PD_FLAGS_SNK_CAP_RECVD)) { - if (++snk_cap_count <= PD_SNK_CAP_RETRIES) { - /* Get sink cap to know if dual-role device */ - send_control(PD_CTRL_GET_SINK_CAP); - set_state(PD_STATE_SRC_GET_SINK_CAP); - break; - } else if (debug_level >= 2 - && snk_cap_count == PD_SNK_CAP_RETRIES + 1) { - CPRINTF("ERR SNK_CAP\n"); - } - } - - /* Check power role policy, which may trigger a swap */ - if (pd.flags & PD_FLAGS_CHECK_PR_ROLE) { - pd_check_pr_role( PD_ROLE_SOURCE, pd.flags); - pd.flags &= ~PD_FLAGS_CHECK_PR_ROLE; - break; - } - - /* Check data role policy, which may trigger a swap */ - if (pd.flags & PD_FLAGS_CHECK_DR_ROLE) { - pd_check_dr_role(pd.data_role, pd.flags); - pd.flags &= ~PD_FLAGS_CHECK_DR_ROLE; - break; - } - - /* Send discovery SVDMs last */ - if (pd.data_role == PD_ROLE_DFP - && (pd.flags & PD_FLAGS_CHECK_IDENTITY)) { -#ifndef CONFIG_USB_PD_SIMPLE_DFP - pd_send_vdm( USB_SID_PD, - CMD_DISCOVER_IDENT, NULL, 0); -#endif - pd.flags &= ~PD_FLAGS_CHECK_IDENTITY; - break; - } - - if (!(pd.flags & PD_FLAGS_PING_ENABLED)) - break; - - /* Verify that the sink is alive */ - res = send_control(PD_CTRL_PING); - if (res >= 0) - break; - - /* Ping dropped. Try soft reset. */ - set_state(PD_STATE_SOFT_RESET); - timeout = 10 * MSEC; - break; - case PD_STATE_SRC_GET_SINK_CAP: - if (pd.last_state != pd.task_state) - set_state_timeout(get_time().val + - PD_T_SENDER_RESPONSE, PD_STATE_SRC_READY); - break; - case PD_STATE_DR_SWAP: - if (pd.last_state != pd.task_state) { - res = send_control(PD_CTRL_DR_SWAP); - if (res < 0) { - timeout = 10 * MSEC; - /* - * If failed to get goodCRC, send - * soft reset, otherwise ignore - * failure. - */ - set_state( - res == -1 ? PD_STATE_SOFT_RESET : READY_RETURN_STATE()); - break; - } - /* Wait for accept or reject */ - set_state_timeout(get_time().val + - PD_T_SENDER_RESPONSE, READY_RETURN_STATE()); - } - break; -#ifdef CONFIG_USB_PD_DUAL_ROLE - case PD_STATE_SRC_SWAP_INIT: - if (pd.last_state != pd.task_state) { - res = send_control(PD_CTRL_PR_SWAP); - if (res < 0) { - timeout = 10 * MSEC; - /* - * If failed to get goodCRC, send - * soft reset, otherwise ignore - * failure. - */ - set_state(res == -1 ? PD_STATE_SOFT_RESET : PD_STATE_SRC_READY); - break; - } - /* Wait for accept or reject */ - set_state_timeout(get_time().val + - PD_T_SENDER_RESPONSE, PD_STATE_SRC_READY); - } - break; - case PD_STATE_SRC_SWAP_SNK_DISABLE: - /* Give time for sink to stop drawing current */ - if (pd.last_state != pd.task_state) - set_state_timeout(get_time().val + - PD_T_SINK_TRANSITION, PD_STATE_SRC_SWAP_SRC_DISABLE); - break; - case PD_STATE_SRC_SWAP_SRC_DISABLE: - /* Turn power off */ - if (pd.last_state != pd.task_state) { - pd_power_supply_reset(); - set_state_timeout(get_time().val + - PD_POWER_SUPPLY_TURN_OFF_DELAY, PD_STATE_SRC_SWAP_STANDBY); - } - break; - case PD_STATE_SRC_SWAP_STANDBY: - /* Send PS_RDY to let sink know our power is off */ - if (pd.last_state != pd.task_state) { - /* Send PS_RDY */ - res = send_control(PD_CTRL_PS_RDY); - if (res < 0) { - timeout = 10 * MSEC; - set_state(PD_STATE_SRC_DISCONNECTED); - break; - } - /* Switch to Rd and swap roles to sink */ - tcpm_set_cc(TYPEC_CC_RD); - pd.power_role = PD_ROLE_SINK; - /* Wait for PS_RDY from new source */ - set_state_timeout(get_time().val + - PD_T_PS_SOURCE_ON, PD_STATE_SNK_DISCONNECTED); - } - break; - case PD_STATE_SUSPENDED: { -#ifndef CONFIG_USB_PD_TCPC - int rstatus; -#endif - CPRINTS("TCPC p%d suspended!", port); - pd.req_suspend_state = 0; -#ifdef CONFIG_USB_PD_TCPC - pd_rx_disable_monitoring(); - pd_hw_release(); - pd_power_supply_reset(); -#else - rstatus = tcpm_release(); - if (rstatus != 0 && rstatus != EC_ERROR_UNIMPLEMENTED) - CPRINTS("TCPC p%d release failed!", port); -#endif - /* Wait for resume */ - // getting rid of task stuff - //while (pd.task_state == PD_STATE_SUSPENDED) - // task_wait_event(-1); -#ifdef CONFIG_USB_PD_TCPC - pd_hw_init( PD_ROLE_DEFAULT()); - CPRINTS("TCPC p%d resumed!", port); -#else - if (rstatus != EC_ERROR_UNIMPLEMENTED && pd_restart_tcpc() != 0) { - /* stay in PD_STATE_SUSPENDED */ - CPRINTS("TCPC p%d restart failed!", port); - break; - } - set_state(PD_DEFAULT_STATE()); - CPRINTS("TCPC p%d resumed!", port); -#endif - break; - } - case PD_STATE_SNK_DISCONNECTED: -#ifdef CONFIG_USB_PD_LOW_POWER - timeout = drp_state != PD_DRP_TOGGLE_ON ? SECOND - : 10*MSEC; -#else - timeout = 10 * MSEC; -#endif - tcpm_get_cc(&cc1, &cc2); - -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - /* - * Attempt TCPC auto DRP toggle if it is - * not already auto toggling and not try.src - */ - if (auto_toggle_supported && - !(pd.flags & PD_FLAGS_TCPC_DRP_TOGGLE) && - !(pd.flags & PD_FLAGS_TRY_SRC) && - (cc1 == TYPEC_CC_VOLT_OPEN && - cc2 == TYPEC_CC_VOLT_OPEN)) { - set_state( PD_STATE_DRP_AUTO_TOGGLE); - timeout = 2*MSEC; - break; - } -#endif - - /* Source connection monitoring */ - if (cc1 != TYPEC_CC_VOLT_OPEN || cc2 != TYPEC_CC_VOLT_OPEN) { - pd.cc_state = PD_CC_NONE; - hard_reset_count = 0; - new_cc_state = PD_CC_NONE; - pd.cc_debounce = get_time().val + - PD_T_CC_DEBOUNCE; - set_state (PD_STATE_SNK_DISCONNECTED_DEBOUNCE); - timeout = 10 * MSEC; - break; - } - - /* - * If Try.SRC is active and failed to detect a SNK, - * then it transitions to TryWait.SNK. Need to prevent - * normal dual role toggle until tDRPTryWait timer - * expires. - */ - if (pd.flags & PD_FLAGS_TRY_SRC) { - if (get_time().val > pd.try_src_marker) - pd.flags &= ~PD_FLAGS_TRY_SRC; - break; - } - - /* If no source detected, check for role toggle. */ - if (drp_state == PD_DRP_TOGGLE_ON && get_time().val >= next_role_swap) { - /* Swap roles to source */ - pd.power_role = PD_ROLE_SOURCE; - set_state(PD_STATE_SRC_DISCONNECTED); - tcpm_set_cc(TYPEC_CC_RP); - next_role_swap = get_time().val + PD_T_DRP_SRC; - - /* Swap states quickly */ - timeout = 2 * MSEC; - } - break; - case PD_STATE_SNK_DISCONNECTED_DEBOUNCE: - tcpm_get_cc(&cc1, &cc2); - - if (cc_is_rp(cc1) && cc_is_rp(cc2)) { - /* Debug accessory */ - new_cc_state = PD_CC_DEBUG_ACC; - } else if (cc_is_rp(cc1) || cc_is_rp(cc2)) { - new_cc_state = PD_CC_DFP_ATTACHED; - } else { - /* No connection any more */ - set_state (PD_STATE_SNK_DISCONNECTED); - timeout = 5 * MSEC; - break; - } - - timeout = 20 * MSEC; - - /* Debounce the cc state */ - if (new_cc_state != pd.cc_state) { - pd.cc_debounce = get_time().val + - PD_T_CC_DEBOUNCE; - pd.cc_state = new_cc_state; - break; - } - /* Wait for CC debounce and VBUS present */ - if (get_time().val < pd.cc_debounce || !pd_is_vbus_present()) - break; - - if (pd_try_src_enable && !(pd.flags & PD_FLAGS_TRY_SRC)) { - /* - * If TRY_SRC is enabled, but not active, - * then force attempt to connect as source. - */ - pd.try_src_marker = get_time().val + PD_T_TRY_SRC; - /* Swap roles to source */ - pd.power_role = PD_ROLE_SOURCE; - tcpm_set_cc(TYPEC_CC_RP); - timeout = 2 * MSEC; - set_state(PD_STATE_SRC_DISCONNECTED); - /* Set flag after the state change */ - pd.flags |= PD_FLAGS_TRY_SRC; - break; - } - - /* We are attached */ - pd.polarity = get_snk_polarity(cc1, cc2); - tcpm_set_polarity(pd.polarity); - /* reset message ID on connection */ - pd.msg_id = 0; - /* initial data role for sink is UFP */ - pd_set_data_role( PD_ROLE_UFP); -#if defined(CONFIG_CHARGE_MANAGER) - typec_curr = get_typec_current_limit(pd.polarity, cc1, cc2); - //typec_set_input_current_limit( - // port, typec_curr, TYPE_C_VOLTAGE); -#endif - /* If PD comm is enabled, enable TCPC RX */ - if (pd_comm_is_enabled()) - tcpm_set_rx_enable(1); - - /* DFP is attached */ - if (new_cc_state == PD_CC_DFP_ATTACHED - || new_cc_state == PD_CC_DEBUG_ACC) { - pd.flags |= PD_FLAGS_CHECK_PR_ROLE | - PD_FLAGS_CHECK_DR_ROLE | - PD_FLAGS_CHECK_IDENTITY; - if (new_cc_state == PD_CC_DEBUG_ACC) - pd.flags |= - PD_FLAGS_TS_DTS_PARTNER; - send_control(PD_CTRL_GET_SOURCE_CAP); - set_state (PD_STATE_SNK_DISCOVERY); - timeout = 10 * MSEC; - //hook_call_deferred( - // &pd_usb_billboard_deferred_data, - // PD_T_AME); - } - break; - case PD_STATE_SNK_HARD_RESET_RECOVER: - if (pd.last_state != pd.task_state) - pd.flags |= PD_FLAGS_CHECK_IDENTITY; -#ifdef CONFIG_USB_PD_VBUS_DETECT_NONE - /* - * Can't measure vbus state so this is the maximum - * recovery time for the source. - */ - if (pd.last_state != pd.task_state) - set_state_timeout( get_time().val + - PD_T_SAFE_0V + - PD_T_SRC_RECOVER_MAX + - PD_T_SRC_TURN_ON, - PD_STATE_SNK_DISCONNECTED); -#else - /* Wait for VBUS to go low and then high*/ - if (pd.last_state != pd.task_state) { - snk_hard_reset_vbus_off = 0; - set_state_timeout(get_time().val + - PD_T_SAFE_0V, - hard_reset_count < - PD_HARD_RESET_COUNT ? - PD_STATE_HARD_RESET_SEND : PD_STATE_SNK_DISCOVERY); - } - - if (!pd_is_vbus_present() && !snk_hard_reset_vbus_off) { - /* VBUS has gone low, reset timeout */ - snk_hard_reset_vbus_off = 1; - set_state_timeout(get_time().val + - PD_T_SRC_RECOVER_MAX + - PD_T_SRC_TURN_ON, PD_STATE_SNK_DISCONNECTED); - } - if (pd_is_vbus_present() && snk_hard_reset_vbus_off) { -#ifdef CONFIG_USB_PD_TCPM_TCPCI - /* - * After transmitting hard reset, TCPM writes - * to RECEIVE_MESSAGE register to enable - * PD message passing. - */ - if (pd_comm_is_enabled()) - tcpm_set_rx_enable( 1); -#endif /* CONFIG_USB_PD_TCPM_TCPCI */ - - /* VBUS went high again */ - set_state (PD_STATE_SNK_DISCOVERY); - timeout = 10 * MSEC; - } - - /* - * Don't need to set timeout because VBUS changing - * will trigger an interrupt and wake us up. - */ -#endif - break; - case PD_STATE_SNK_DISCOVERY: - /* Wait for source cap expired only if we are enabled */ - if ((pd.last_state != pd.task_state) - && pd_comm_is_enabled()) { - /* - * If VBUS has never been low, and we timeout - * waiting for source cap, try a soft reset - * first, in case we were already in a stable - * contract before this boot. - */ - if (pd.flags & PD_FLAGS_VBUS_NEVER_LOW) - set_state_timeout(get_time().val + - PD_T_SINK_WAIT_CAP, PD_STATE_SOFT_RESET); - /* - * If we haven't passed hard reset counter, - * start SinkWaitCapTimer, otherwise start - * NoResponseTimer. - */ - else if (hard_reset_count < PD_HARD_RESET_COUNT) - set_state_timeout(get_time().val + - PD_T_SINK_WAIT_CAP, PD_STATE_HARD_RESET_SEND); - else if (pd.flags & - PD_FLAGS_PREVIOUS_PD_CONN) - /* ErrorRecovery */ - set_state_timeout(get_time().val + - PD_T_NO_RESPONSE, PD_STATE_SNK_DISCONNECTED); -#if defined(CONFIG_CHARGE_MANAGER) - /* - * If we didn't come from disconnected, must - * have come from some path that did not set - * typec current limit. So, set to 0 so that - * we guarantee this is revised below. - */ - if (pd.last_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE) - typec_curr = 0; -#endif - } - -#if defined(CONFIG_CHARGE_MANAGER) - timeout = PD_T_SINK_ADJ - PD_T_DEBOUNCE; - - /* Check if CC pull-up has changed */ - tcpm_get_cc(&cc1, &cc2); - if (typec_curr - != get_typec_current_limit(pd.polarity, cc1, cc2)) { - /* debounce signal by requiring two reads */ - if (typec_curr_change) { - /* set new input current limit */ - typec_curr = get_typec_current_limit(pd.polarity, cc1, - cc2); - //typec_set_input_current_limit( - // port, typec_curr, TYPE_C_VOLTAGE); - } else { - /* delay for debounce */ - timeout = PD_T_DEBOUNCE; - } - typec_curr_change = !typec_curr_change; - } else { - typec_curr_change = 0; - } -#endif - break; - case PD_STATE_SNK_REQUESTED: - /* Wait for ACCEPT or REJECT */ - if (pd.last_state != pd.task_state) { - hard_reset_count = 0; - set_state_timeout(get_time().val + - PD_T_SENDER_RESPONSE, PD_STATE_HARD_RESET_SEND); - } - break; - case PD_STATE_SNK_TRANSITION: - /* Wait for PS_RDY */ - if (pd.last_state != pd.task_state) - set_state_timeout(get_time().val + - PD_T_PS_TRANSITION, PD_STATE_HARD_RESET_SEND); - break; - case PD_STATE_SNK_READY: - timeout = 20 * MSEC; - - /* - * Don't send any PD traffic if we woke up due to - * incoming packet or if VDO response pending to avoid - * collisions. - */ - if (incoming_packet || (pd.vdm_state == VDM_STATE_BUSY)) - break; - - /* Check for new power to request */ - if (pd.new_power_request) { - if (pd_send_request_msg(0) != EC_SUCCESS) - set_state(PD_STATE_SOFT_RESET); - break; - } - - /* Check power role policy, which may trigger a swap */ - if (pd.flags & PD_FLAGS_CHECK_PR_ROLE) { - pd_check_pr_role( PD_ROLE_SINK, pd.flags); - pd.flags &= ~PD_FLAGS_CHECK_PR_ROLE; - break; - } - - /* Check data role policy, which may trigger a swap */ - if (pd.flags & PD_FLAGS_CHECK_DR_ROLE) { - pd_check_dr_role(pd.data_role, pd.flags); - pd.flags &= ~PD_FLAGS_CHECK_DR_ROLE; - break; - } - - /* If DFP, send discovery SVDMs */ - if (pd.data_role == PD_ROLE_DFP - && (pd.flags & PD_FLAGS_CHECK_IDENTITY)) { - pd_send_vdm( USB_SID_PD, - CMD_DISCOVER_IDENT, NULL, 0); - pd.flags &= ~PD_FLAGS_CHECK_IDENTITY; - break; - } - - /* Sent all messages, don't need to wake very often */ - timeout = 200 * MSEC; - break; - case PD_STATE_SNK_SWAP_INIT: - if (pd.last_state != pd.task_state) { - res = send_control(PD_CTRL_PR_SWAP); - if (res < 0) { - timeout = 10 * MSEC; - /* - * If failed to get goodCRC, send - * soft reset, otherwise ignore - * failure. - */ - set_state(res == -1 ? PD_STATE_SOFT_RESET : PD_STATE_SNK_READY); - break; - } - /* Wait for accept or reject */ - set_state_timeout(get_time().val + - PD_T_SENDER_RESPONSE, PD_STATE_SNK_READY); - } - break; - case PD_STATE_SNK_SWAP_SNK_DISABLE: - /* Stop drawing power */ - pd_set_input_current_limit(0, 0); -#ifdef CONFIG_CHARGE_MANAGER - //typec_set_input_current_limit( 0, 0); - //charge_manager_set_ceil( - // CEIL_REQUESTOR_PD, - // CHARGE_CEIL_NONE); -#endif - set_state (PD_STATE_SNK_SWAP_SRC_DISABLE); - timeout = 10 * MSEC; - break; - case PD_STATE_SNK_SWAP_SRC_DISABLE: - /* Wait for PS_RDY */ - if (pd.last_state != pd.task_state) - set_state_timeout(get_time().val + - PD_T_PS_SOURCE_OFF, PD_STATE_HARD_RESET_SEND); - break; - case PD_STATE_SNK_SWAP_STANDBY: - if (pd.last_state != pd.task_state) { - /* Switch to Rp and enable power supply */ - tcpm_set_cc(TYPEC_CC_RP); - if (pd_set_power_supply_ready()) { - /* Restore Rd */ - tcpm_set_cc(TYPEC_CC_RD); - timeout = 10 * MSEC; - set_state (PD_STATE_SNK_DISCONNECTED); - break; - } - /* Wait for power supply to turn on */ - set_state_timeout(get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY, PD_STATE_SNK_SWAP_COMPLETE); - } - break; - case PD_STATE_SNK_SWAP_COMPLETE: - /* Send PS_RDY and change to source role */ - res = send_control(PD_CTRL_PS_RDY); - if (res < 0) { - /* Restore Rd */ - tcpm_set_cc(TYPEC_CC_RD); - pd_power_supply_reset(); - timeout = 10 * MSEC; - set_state (PD_STATE_SNK_DISCONNECTED); - break; - } - - /* Don't send GET_SINK_CAP on swap */ - snk_cap_count = PD_SNK_CAP_RETRIES + 1; - caps_count = 0; - pd.msg_id = 0; - pd.power_role = PD_ROLE_SOURCE; - pd_update_roles(); - set_state(PD_STATE_SRC_DISCOVERY); - timeout = 10 * MSEC; - break; -#ifdef CONFIG_USBC_VCONN_SWAP - case PD_STATE_VCONN_SWAP_SEND: - if (pd.last_state != pd.task_state) { - res = send_control( PD_CTRL_VCONN_SWAP); - if (res < 0) { - timeout = 10*MSEC; - /* - * If failed to get goodCRC, send - * soft reset, otherwise ignore - * failure. - */ - set_state( res == -1 ? - PD_STATE_SOFT_RESET : - READY_RETURN_STATE()); - break; - } - /* Wait for accept or reject */ - set_state_timeout( - get_time().val + - PD_T_SENDER_RESPONSE, - READY_RETURN_STATE()); - } - break; - case PD_STATE_VCONN_SWAP_INIT: - if (pd.last_state != pd.task_state) { - if (!(pd.flags & PD_FLAGS_VCONN_ON)) { - /* Turn VCONN on and wait for it */ - tcpm_set_vconn( 1); - set_state_timeout( - get_time().val + PD_VCONN_SWAP_DELAY, - PD_STATE_VCONN_SWAP_READY); - } else { - set_state_timeout( - get_time().val + PD_T_VCONN_SOURCE_ON, - READY_RETURN_STATE()); - } - } - break; - case PD_STATE_VCONN_SWAP_READY: - if (pd.last_state != pd.task_state) { - if (!(pd.flags & PD_FLAGS_VCONN_ON)) { - /* VCONN is now on, send PS_RDY */ - pd.flags |= PD_FLAGS_VCONN_ON; - res = send_control( - PD_CTRL_PS_RDY); - if (res == -1) { - timeout = 10*MSEC; - /* - * If failed to get goodCRC, - * send soft reset - */ - set_state( - PD_STATE_SOFT_RESET); - break; - } - set_state( - READY_RETURN_STATE()); - } else { - /* Turn VCONN off and wait for it */ - tcpm_set_vconn( 0); - pd.flags &= ~PD_FLAGS_VCONN_ON; - set_state_timeout( - get_time().val + PD_VCONN_SWAP_DELAY, - READY_RETURN_STATE()); - } - } - break; -#endif /* CONFIG_USBC_VCONN_SWAP */ -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - case PD_STATE_SOFT_RESET: - if (pd.last_state != pd.task_state) { - /* Message ID of soft reset is always 0 */ - pd.msg_id = 0; - res = send_control(PD_CTRL_SOFT_RESET); - - /* if soft reset failed, try hard reset. */ - if (res < 0) { - set_state(PD_STATE_HARD_RESET_SEND); - timeout = 5 * MSEC; - break; - } - - set_state_timeout(get_time().val + PD_T_SENDER_RESPONSE, - PD_STATE_HARD_RESET_SEND); - } - break; - case PD_STATE_HARD_RESET_SEND: - hard_reset_count++; - if (pd.last_state != pd.task_state) - hard_reset_sent = 0; -#ifdef CONFIG_CHARGE_MANAGER -// if (pd.last_state == PD_STATE_SNK_DISCOVERY -// || (pd.last_state == PD_STATE_SOFT_RESET -// && (pd.flags & PD_FLAGS_VBUS_NEVER_LOW))) { -// pd.flags &= ~PD_FLAGS_VBUS_NEVER_LOW; -// /* -// * If discovery timed out, assume that we -// * have a dedicated charger attached. This -// * may not be a correct assumption according -// * to the specification, but it generally -// * works in practice and the harmful -// * effects of a wrong assumption here -// * are minimal. -// */ -// //charge_manager_update_dualrole( -// // CAP_DEDICATED); -// } -#endif - - /* try sending hard reset until it succeeds */ - if (!hard_reset_sent) { - if (pd_transmit(TCPC_TX_HARD_RESET, 0, NULL) < 0) { - timeout = 10 * MSEC; - break; - } - - /* successfully sent hard reset */ - hard_reset_sent = 1; - /* - * If we are source, delay before cutting power - * to allow sink time to get hard reset. - */ - - set_state(PD_STATE_HARD_RESET_EXECUTE); - timeout = 10 * MSEC; - - } - break; - case PD_STATE_HARD_RESET_EXECUTE: -#ifdef CONFIG_USB_PD_DUAL_ROLE - /* - * If hard reset while in the last stages of power - * swap, then we need to restore our CC resistor. - */ - if (pd.last_state == PD_STATE_SNK_SWAP_STANDBY) - tcpm_set_cc(TYPEC_CC_RD); -#endif - - /* reset our own state machine */ - pd_execute_hard_reset(); - timeout = 10 * MSEC; - break; -#ifdef CONFIG_COMMON_RUNTIME - case PD_STATE_BIST_RX: - send_bist_cmd(); - /* Delay at least enough for partner to finish BIST */ - timeout = PD_T_BIST_RECEIVE + 20*MSEC; - /* Set to appropriate port disconnected state */ - set_state( DUAL_ROLE_IF_ELSE( - PD_STATE_SNK_DISCONNECTED, - PD_STATE_SRC_DISCONNECTED)); - break; - case PD_STATE_BIST_TX: - pd_transmit( TCPC_TX_BIST_MODE_2, 0, NULL); - /* Delay at least enough to finish sending BIST */ - timeout = PD_T_BIST_TRANSMIT + 20*MSEC; - /* Set to appropriate port disconnected state */ - set_state( DUAL_ROLE_IF_ELSE( - PD_STATE_SNK_DISCONNECTED, - PD_STATE_SRC_DISCONNECTED)); - break; -#endif -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - case PD_STATE_DRP_AUTO_TOGGLE: - { - enum pd_states next_state; - - assert(auto_toggle_supported); - - /* Check for connection */ - tcpm_get_cc( &cc1, &cc2); - - /* Set to appropriate port state */ - if (cc1 == TYPEC_CC_VOLT_OPEN && - cc2 == TYPEC_CC_VOLT_OPEN) - /* nothing connected, keep toggling*/ - next_state = PD_STATE_DRP_AUTO_TOGGLE; - else if ((cc_is_rp(cc1) || cc_is_rp(cc2)) && - drp_state != PD_DRP_FORCE_SOURCE) - /* SNK allowed unless ForceSRC */ - next_state = PD_STATE_SNK_DISCONNECTED; - else if (((cc1 == TYPEC_CC_VOLT_RD || - cc2 == TYPEC_CC_VOLT_RD) || - (cc1 == TYPEC_CC_VOLT_RA && - cc2 == TYPEC_CC_VOLT_RA)) && - (drp_state != PD_DRP_TOGGLE_OFF && - drp_state != PD_DRP_FORCE_SINK)) - /* SRC allowed unless ForceSNK or Toggle Off */ - next_state = PD_STATE_SRC_DISCONNECTED; - else - /* Anything else, keep toggling */ - next_state = PD_STATE_DRP_AUTO_TOGGLE; - - if (next_state != PD_STATE_DRP_AUTO_TOGGLE) { - tcpm_set_drp_toggle( 0); -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER - CPRINTS("TCPC p%d Exit Low Power Mode", port); -#endif - } - - if (next_state == PD_STATE_SNK_DISCONNECTED) { - tcpm_set_cc( TYPEC_CC_RD); - pd.power_role = PD_ROLE_SINK; - timeout = 2*MSEC; - } else if (next_state == PD_STATE_SRC_DISCONNECTED) { - tcpm_set_cc( TYPEC_CC_RP); - pd.power_role = PD_ROLE_SOURCE; - timeout = 2*MSEC; - } else { - tcpm_set_drp_toggle( 1); - pd.flags |= PD_FLAGS_TCPC_DRP_TOGGLE; - timeout = -1; -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER - CPRINTS("TCPC p%d Low Power Mode", port); -#endif - } - set_state( next_state); - - break; - } -#endif - default: - break; - } - - pd.last_state = this_state; - - /* - * Check for state timeout, and if not check if need to adjust - * timeout value to wake up on the next state timeout. - */ - now = get_time(); - if (pd.timeout) { - if (now.val >= pd.timeout) { - set_state(pd.timeout_state); - /* On a state timeout, run next state soon */ - timeout = timeout < 10 * MSEC ? timeout : 10 * MSEC; - } else if (pd.timeout - now.val < timeout) { - timeout = pd.timeout - now.val; - } - } - - /* Check for disconnection if we're connected */ - if (!pd_is_connected()) - return; -#ifdef CONFIG_USB_PD_DUAL_ROLE - if (pd_is_power_swapping()) - return; -#endif - -#ifdef CONFIG_USB_PD_DUAL_ROLE - /* - * Sink disconnect if VBUS is low and we are not recovering - * a hard reset. - */ - if (pd.power_role == PD_ROLE_SINK && !pd_is_vbus_present() - && pd.task_state != PD_STATE_SNK_HARD_RESET_RECOVER - && pd.task_state != PD_STATE_HARD_RESET_EXECUTE) { - /* Sink: detect disconnect by monitoring VBUS */ - set_state (PD_STATE_SNK_DISCONNECTED); - /* set timeout small to reconnect fast */ - timeout = 5 * MSEC; - } -#endif /* CONFIG_USB_PD_DUAL_ROLE */ -} - -#ifdef CONFIG_USB_PD_DUAL_ROLE -//extern "C" { -//static void dual_role_on(void) { -// int i; -// -// for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) { -//#ifdef CONFIG_CHARGE_MANAGER -// //if (charge_manager_get_active_charge_port() != i) -//#endif -// pd[i].flags |= PD_FLAGS_CHECK_PR_ROLE | -// PD_FLAGS_CHECK_DR_ROLE; -// -// pd[i].flags |= PD_FLAGS_CHECK_IDENTITY; -// } -// -// pd_set_dual_role(PD_DRP_TOGGLE_ON); -// CPRINTS("chipset -> S0"); -//} -//} -//DECLARE_HOOK(HOOK_CHIPSET_RESUME, dual_role_on, HOOK_PRIO_DEFAULT); -// -//static void dual_role_off(void) { -// pd_set_dual_role(PD_DRP_TOGGLE_OFF); -// CPRINTS("chipset -> S3"); -//} -//DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, dual_role_off, HOOK_PRIO_DEFAULT); -//DECLARE_HOOK(HOOK_CHIPSET_STARTUP, dual_role_off, HOOK_PRIO_DEFAULT); -// -//static void dual_role_force_sink(void) { -// pd_set_dual_role(PD_DRP_FORCE_SINK); -// CPRINTS("chipset -> S5"); -//} -//DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, dual_role_force_sink, HOOK_PRIO_DEFAULT); - -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - -#ifdef CONFIG_COMMON_RUNTIME - -/* - * (enable=1) request pd_task transition to the suspended state. hang - * around for a while until we observe the state change. this can - * take a while (like 300ms) on startup when pd_task is sleeping in - * tcpci_tcpm_init. - * - * (enable=0) force pd_task out of the suspended state and into the - * port's default state. - */ - -void pd_set_suspend( int enable) -{ - int tries = 300; - - if (enable) { - pd.req_suspend_state = 1; - do { - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); - if (pd.task_state == PD_STATE_SUSPENDED) - break; - msleep(1); - } while (--tries != 0); - if (!tries) - CPRINTS("TCPC p%d set_suspend failed!", port); - } else { - if (pd.task_state != PD_STATE_SUSPENDED) - CPRINTS("TCPC p%d suspend disable request " - "while not suspended!", port); - set_state( PD_DEFAULT_STATE()); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); - } -} - -int pd_is_port_enabled() -{ - switch (pd.task_state) { - case PD_STATE_DISABLED: - case PD_STATE_SUSPENDED: - return 0; - default: - return 1; - } -} - -#if defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) -static int hex8tou32(char *str, uint32_t *val) -{ - char *ptr = str; - uint32_t tmp = 0; - - while (*ptr) { - char c = *ptr++; - if (c >= '0' && c <= '9') - tmp = (tmp << 4) + (c - '0'); - else if (c >= 'A' && c <= 'F') - tmp = (tmp << 4) + (c - 'A' + 10); - else if (c >= 'a' && c <= 'f') - tmp = (tmp << 4) + (c - 'a' + 10); - else - return EC_ERROR_INVAL; - } - if (ptr != str + 8) - return EC_ERROR_INVAL; - *val = tmp; - return EC_SUCCESS; -} - -static int remote_flashing(int argc, char **argv) -{ - int port, cnt, cmd; - uint32_t data[VDO_MAX_SIZE-1]; - char *e; - static int flash_offset[CONFIG_USB_PD_PORT_COUNT]; - - if (argc < 4 || argc > (VDO_MAX_SIZE + 4 - 1)) - return EC_ERROR_PARAM_COUNT; - - port = strtoi(argv[1], &e, 10); - if (*e || port >= CONFIG_USB_PD_PORT_COUNT) - return EC_ERROR_PARAM2; - - cnt = 0; - if (!strcasecmp(argv[3], "erase")) { - cmd = VDO_CMD_FLASH_ERASE; - flash_offset[port] = 0; - ccprintf("ERASE ..."); - } else if (!strcasecmp(argv[3], "reboot")) { - cmd = VDO_CMD_REBOOT; - ccprintf("REBOOT ..."); - } else if (!strcasecmp(argv[3], "signature")) { - cmd = VDO_CMD_ERASE_SIG; - ccprintf("ERASE SIG ..."); - } else if (!strcasecmp(argv[3], "info")) { - cmd = VDO_CMD_READ_INFO; - ccprintf("INFO..."); - } else if (!strcasecmp(argv[3], "version")) { - cmd = VDO_CMD_VERSION; - ccprintf("VERSION..."); - } else { - int i; - argc -= 3; - for (i = 0; i < argc; i++) - if (hex8tou32(argv[i+3], data + i)) - return EC_ERROR_INVAL; - cmd = VDO_CMD_FLASH_WRITE; - cnt = argc; - ccprintf("WRITE %d @%04x ...", argc * 4, - flash_offset[port]); - flash_offset[port] += argc * 4; - } - - pd_send_vdm( USB_VID_GOOGLE, cmd, data, cnt); - - /* Wait until VDM is done */ - while (pd.vdm_state > 0) - task_wait_event(100*MSEC); - - ccprintf("DONE %d\n", pd.vdm_state); - return EC_SUCCESS; -} -#endif /* defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) */ - -#if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP) -void pd_send_hpd( enum hpd_event hpd) -{ - uint32_t data[1]; - int opos = pd_alt_mode( USB_SID_DISPLAYPORT); - if (!opos) - return; - - data[0] = VDO_DP_STATUS((hpd == hpd_irq), /* IRQ_HPD */ - (hpd != hpd_low), /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - 0, /* MF pref */ - 1, /* enabled */ - 0, /* power low */ - 0x2); - pd_send_vdm( USB_SID_DISPLAYPORT, - VDO_OPOS(opos) | CMD_ATTENTION, data, 1); - /* Wait until VDM is done. */ - while (pd[0].vdm_state > 0) - task_wait_event(USB_PD_RX_TMOUT_US * (PD_RETRY_COUNT + 1)); -} -#endif - -int pd_fetch_acc_log_entry() -{ - timestamp_t timeout; - - /* Cannot send a VDM now, the host should retry */ - if (pd.vdm_state > 0) - return pd.vdm_state == VDM_STATE_BUSY ? - EC_RES_BUSY : EC_RES_UNAVAILABLE; - - pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_GET_LOG, NULL, 0); - timeout.val = get_time().val + 75*MSEC; - - /* Wait until VDM is done */ - while ((pd.vdm_state > 0) && - (get_time().val < timeout.val)) - task_wait_event(10*MSEC); - - if (pd.vdm_state > 0) - return EC_RES_TIMEOUT; - else if (pd.vdm_state < 0) - return EC_RES_ERROR; - - return EC_RES_SUCCESS; -} - -#ifdef CONFIG_USB_PD_DUAL_ROLE -void pd_request_source_voltage( int mv) -{ - pd_set_max_voltage(mv); - - if (pd.task_state == PD_STATE_SNK_READY || - pd.task_state == PD_STATE_SNK_TRANSITION) { - /* Set flag to send new power request in pd_task */ - pd.new_power_request = 1; - } else { - pd.power_role = PD_ROLE_SINK; - tcpm_set_cc( TYPEC_CC_RD); - set_state( PD_STATE_SNK_DISCONNECTED); - } - - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); -} - -void pd_set_external_voltage_limit( int mv) -{ - pd_set_max_voltage(mv); - - if (pd.task_state == PD_STATE_SNK_READY || - pd.task_state == PD_STATE_SNK_TRANSITION) { - /* Set flag to send new power request in pd_task */ - pd.new_power_request = 1; - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); - } -} - -void pd_update_contract() -{ - if ((pd.task_state >= PD_STATE_SRC_NEGOCIATE) && - (pd.task_state <= PD_STATE_SRC_GET_SINK_CAP)) { - pd.flags |= PD_FLAGS_UPDATE_SRC_CAPS; - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); - } -} - -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - -static int command_pd(int argc, char **argv) -{ - int port; - char *e; - - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - -#if defined(CONFIG_CMD_PD) && defined(CONFIG_USB_PD_DUAL_ROLE) - /* command: pd */ - if (!strcasecmp(argv[1], "dualrole")) { - if (argc < 3) { - ccprintf("dual-role toggling: "); - switch (drp_state) { - case PD_DRP_TOGGLE_ON: - ccprintf("on\n"); - break; - case PD_DRP_TOGGLE_OFF: - ccprintf("off\n"); - break; - case PD_DRP_FREEZE: - ccprintf("freeze\n"); - break; - case PD_DRP_FORCE_SINK: - ccprintf("force sink\n"); - break; - case PD_DRP_FORCE_SOURCE: - ccprintf("force source\n"); - break; - } - } else { - if (!strcasecmp(argv[2], "on")) - pd_set_dual_role(PD_DRP_TOGGLE_ON); - else if (!strcasecmp(argv[2], "off")) - pd_set_dual_role(PD_DRP_TOGGLE_OFF); - else if (!strcasecmp(argv[2], "freeze")) - pd_set_dual_role(PD_DRP_FREEZE); - else if (!strcasecmp(argv[2], "sink")) - pd_set_dual_role(PD_DRP_FORCE_SINK); - else if (!strcasecmp(argv[2], "source")) - pd_set_dual_role(PD_DRP_FORCE_SOURCE); - else - return EC_ERROR_PARAM3; - } - return EC_SUCCESS; - } else -#endif - if (!strcasecmp(argv[1], "dump")) { -#ifndef CONFIG_USB_PD_DEBUG_LEVEL - int level; - - if (argc >= 3) { - level = strtoi(argv[2], &e, 10); - if (*e) - return EC_ERROR_PARAM2; - debug_level = level; - } else -#endif - ccprintf("dump level: %d\n", debug_level); - - return EC_SUCCESS; - } -#ifdef CONFIG_CMD_PD -#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO - else if (!strncasecmp(argv[1], "rwhashtable", 3)) { - int i; - struct ec_params_usb_pd_rw_hash_entry *p; - for (i = 0; i < RW_HASH_ENTRIES; i++) { - p = &rw_hash_table[i]; - pd_dev_dump_info(p->dev_id, p->dev_rw_hash); - } - return EC_SUCCESS; - } -#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */ -#ifdef CONFIG_USB_PD_TRY_SRC - else if (!strncasecmp(argv[1], "trysrc", 6)) { - int enable; - - if (argc < 2) { - return EC_ERROR_PARAM_COUNT; - } else if (argc >= 3) { - enable = strtoi(argv[2], &e, 10); - if (*e) - return EC_ERROR_PARAM3; - pd_try_src_enable = enable ? 1 : 0; - } - - ccprintf("Try.SRC %s\n", pd_try_src_enable ? "on" : "off"); - return EC_SUCCESS; - } -#endif -#endif - /* command: pd [args] */ - port = strtoi(argv[1], &e, 10); - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - if (*e || port >= CONFIG_USB_PD_PORT_COUNT) - return EC_ERROR_PARAM2; -#if defined(CONFIG_CMD_PD) && defined(CONFIG_USB_PD_DUAL_ROLE) - - if (!strcasecmp(argv[2], "tx")) { - set_state( PD_STATE_SNK_DISCOVERY); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); - } else if (!strcasecmp(argv[2], "bist_rx")) { - set_state( PD_STATE_BIST_RX); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); - } else if (!strcasecmp(argv[2], "bist_tx")) { - if (*e) - return EC_ERROR_PARAM3; - set_state( PD_STATE_BIST_TX); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); - } else if (!strcasecmp(argv[2], "charger")) { - pd.power_role = PD_ROLE_SOURCE; - tcpm_set_cc( TYPEC_CC_RP); - set_state( PD_STATE_SRC_DISCONNECTED); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); - } else if (!strncasecmp(argv[2], "dev", 3)) { - int max_volt; - if (argc >= 4) - max_volt = strtoi(argv[3], &e, 10) * 1000; - else - max_volt = pd_get_max_voltage(); - - pd_request_source_voltage( max_volt); - ccprintf("max req: %dmV\n", max_volt); - } else if (!strcasecmp(argv[2], "disable")) { - pd_comm_enable( 0); - ccprintf("Port C%d disable\n", port); - return EC_SUCCESS; - } else if (!strcasecmp(argv[2], "enable")) { - pd_comm_enable( 1); - ccprintf("Port C%d enabled\n", port); - return EC_SUCCESS; - } else if (!strncasecmp(argv[2], "hard", 4)) { - set_state( PD_STATE_HARD_RESET_SEND); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); - } else if (!strncasecmp(argv[2], "info", 4)) { - int i; - ccprintf("Hash "); - for (i = 0; i < PD_RW_HASH_SIZE / 4; i++) - ccprintf("%08x ", pd.dev_rw_hash[i]); - ccprintf("\nImage %s\n", system_image_copy_t_to_string( - pd.current_image)); - } else if (!strncasecmp(argv[2], "soft", 4)) { - set_state( PD_STATE_SOFT_RESET); - // getting rid of task stuff - //task_wake(PD_PORT_TO_TASK_ID()); - } else if (!strncasecmp(argv[2], "swap", 4)) { - if (argc < 4) - return EC_ERROR_PARAM_COUNT; - - if (!strncasecmp(argv[3], "power", 5)) - pd_request_power_swap(); - else if (!strncasecmp(argv[3], "data", 4)) - pd_request_data_swap(); -#ifdef CONFIG_USBC_VCONN_SWAP - else if (!strncasecmp(argv[3], "vconn", 5)) - pd_request_vconn_swap(); -#endif - else - return EC_ERROR_PARAM3; - } else if (!strncasecmp(argv[2], "ping", 4)) { - int enable; - - if (argc > 3) { - enable = strtoi(argv[3], &e, 10); - if (*e) - return EC_ERROR_PARAM3; - pd_ping_enable( enable); - } - - ccprintf("Pings %s\n", - (pd.flags & PD_FLAGS_PING_ENABLED) ? - "on" : "off"); - } else if (!strncasecmp(argv[2], "vdm", 3)) { - if (argc < 4) - return EC_ERROR_PARAM_COUNT; - - if (!strncasecmp(argv[3], "ping", 4)) { - uint32_t enable; - if (argc < 5) - return EC_ERROR_PARAM_COUNT; - enable = strtoi(argv[4], &e, 10); - if (*e) - return EC_ERROR_PARAM4; - pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_PING_ENABLE, - &enable, 1); - } else if (!strncasecmp(argv[3], "curr", 4)) { - pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_CURRENT, - NULL, 0); - } else if (!strncasecmp(argv[3], "vers", 4)) { - pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_VERSION, - NULL, 0); - } else { - return EC_ERROR_PARAM_COUNT; - } -#if defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) - } else if (!strncasecmp(argv[2], "flash", 4)) { - return remote_flashing(argc, argv); -#endif - } else -#endif - if (!strncasecmp(argv[2], "state", 5)) { - ccprintf("Port C%d CC%d, %s - Role: %s-%s%s " - "State: %s, Flags: 0x%04x\n", - port, pd.polarity + 1, - pd_comm_is_enabled() ? "Ena" : "Dis", - pd.power_role == PD_ROLE_SOURCE ? "SRC" : "SNK", - pd.data_role == PD_ROLE_DFP ? "DFP" : "UFP", - (pd.flags & PD_FLAGS_VCONN_ON) ? "-VC" : "", - pd_state_names[pd.task_state], - pd.flags); - } else { - return EC_ERROR_PARAM1; - } - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(pd, command_pd, - "dualrole|dump|rwhashtable" - "|trysrc [0|1]\n\t " - "[tx|bist_rx|bist_tx|charger|clock|dev|disable|enable" - "|soft|hash|hard|ping|state|swap [power|data]|" - "vdm [ping | curr | vers]]", - "USB PD"); - -#ifdef HAS_TASK_HOSTCMD - -static int hc_pd_ports(struct host_cmd_handler_args *args) -{ - struct ec_response_usb_pd_ports *r = args->response; - r->num_ports = CONFIG_USB_PD_PORT_COUNT; - - args->response_size = sizeof(*r); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_PORTS, - hc_pd_ports, - EC_VER_MASK(0)); - -static const enum pd_dual_role_states dual_role_map[USB_PD_CTRL_ROLE_COUNT] = { - [USB_PD_CTRL_ROLE_TOGGLE_ON] = PD_DRP_TOGGLE_ON, - [USB_PD_CTRL_ROLE_TOGGLE_OFF] = PD_DRP_TOGGLE_OFF, - [USB_PD_CTRL_ROLE_FORCE_SINK] = PD_DRP_FORCE_SINK, - [USB_PD_CTRL_ROLE_FORCE_SOURCE] = PD_DRP_FORCE_SOURCE, - [USB_PD_CTRL_ROLE_FREEZE] = PD_DRP_FREEZE, -}; - -#ifdef CONFIG_USBC_SS_MUX -static const enum typec_mux typec_mux_map[USB_PD_CTRL_MUX_COUNT] = { - [USB_PD_CTRL_MUX_NONE] = TYPEC_MUX_NONE, - [USB_PD_CTRL_MUX_USB] = TYPEC_MUX_USB, - [USB_PD_CTRL_MUX_AUTO] = TYPEC_MUX_DP, - [USB_PD_CTRL_MUX_DP] = TYPEC_MUX_DP, - [USB_PD_CTRL_MUX_DOCK] = TYPEC_MUX_DOCK, -}; -#endif - -static int hc_usb_pd_control(struct host_cmd_handler_args *args) -{ - const struct ec_params_usb_pd_control *p = args->params; - struct ec_response_usb_pd_control_v1 *r_v1 = args->response; - struct ec_response_usb_pd_control *r = args->response; - - if (p->port >= CONFIG_USB_PD_PORT_COUNT) - return EC_RES_INVALID_PARAM; - - if (p->role >= USB_PD_CTRL_ROLE_COUNT || - p->mux >= USB_PD_CTRL_MUX_COUNT) - return EC_RES_INVALID_PARAM; - - if (p->role != USB_PD_CTRL_ROLE_NO_CHANGE) - pd_set_dual_role(dual_role_map[p->role]); - -#ifdef CONFIG_USBC_SS_MUX - if (p->mux != USB_PD_CTRL_MUX_NO_CHANGE) - usb_mux_set(p->port, typec_mux_map[p->mux], - typec_mux_map[p->mux] == TYPEC_MUX_NONE ? - USB_SWITCH_DISCONNECT : - USB_SWITCH_CONNECT, - pd_get_polarity(p->port)); -#endif /* CONFIG_USBC_SS_MUX */ - - if (p->swap == USB_PD_CTRL_SWAP_DATA) - pd_request_data_swap(p->port); -#ifdef CONFIG_USB_PD_DUAL_ROLE - else if (p->swap == USB_PD_CTRL_SWAP_POWER) - pd_request_power_swap(p->port); -#ifdef CONFIG_USBC_VCONN_SWAP - else if (p->swap == USB_PD_CTRL_SWAP_VCONN) - pd_request_vconn_swap(p->port); -#endif -#endif - - if (args->version == 0) { - r->enabled = pd_comm_is_enabled(p->port); - r->role = pd[p->port].power_role; - r->polarity = pd[p->port].polarity; - r->state = pd[p->port].task_state; - args->response_size = sizeof(*r); - } else { - r_v1->enabled = - (pd_comm_is_enabled(p->port) ? - PD_CTRL_RESP_ENABLED_COMMS : 0) | - (pd_is_connected(p->port) ? - PD_CTRL_RESP_ENABLED_CONNECTED : 0) | - ((pd[p->port].flags & PD_FLAGS_PREVIOUS_PD_CONN) ? - PD_CTRL_RESP_ENABLED_PD_CAPABLE : 0); - r_v1->role = - (pd[p->port].power_role ? PD_CTRL_RESP_ROLE_POWER : 0) | - (pd[p->port].data_role ? PD_CTRL_RESP_ROLE_DATA : 0) | - ((pd[p->port].flags & PD_FLAGS_VCONN_ON) ? - PD_CTRL_RESP_ROLE_VCONN : 0) | - ((pd[p->port].flags & PD_FLAGS_PARTNER_DR_POWER) ? - PD_CTRL_RESP_ROLE_DR_POWER : 0) | - ((pd[p->port].flags & PD_FLAGS_PARTNER_DR_DATA) ? - PD_CTRL_RESP_ROLE_DR_DATA : 0) | - ((pd[p->port].flags & PD_FLAGS_PARTNER_USB_COMM) ? - PD_CTRL_RESP_ROLE_USB_COMM : 0) | - ((pd[p->port].flags & PD_FLAGS_PARTNER_EXTPOWER) ? - PD_CTRL_RESP_ROLE_EXT_POWERED : 0); - r_v1->polarity = pd[p->port].polarity; - strzcpy(r_v1->state, - pd_state_names[pd[p->port].task_state], - sizeof(r_v1->state)); - args->response_size = sizeof(*r_v1); - } - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_CONTROL, - hc_usb_pd_control, - EC_VER_MASK(0) | EC_VER_MASK(1)); - -static int hc_remote_flash(struct host_cmd_handler_args *args) -{ - const struct ec_params_usb_pd_fw_update *p = args->params; - int port = p->port; - const uint32_t *data = &(p->size) + 1; - int i, size, rv = EC_RES_SUCCESS; - timestamp_t timeout; - - if (port >= CONFIG_USB_PD_PORT_COUNT) - return EC_RES_INVALID_PARAM; - - if (p->size + sizeof(*p) > args->params_size) - return EC_RES_INVALID_PARAM; - -#if defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \ - defined(CONFIG_BATTERY_PRESENT_GPIO) - /* - * Do not allow PD firmware update if no battery and this port - * is sinking power, because we will lose power. - */ - if (battery_is_present() != BP_YES && - charge_manager_get_active_charge_port() == port) - return EC_RES_UNAVAILABLE; -#endif - - /* - * Busy still with a VDM that host likely generated. 1 deep VDM queue - * so just return for retry logic on host side to deal with. - */ - if (pd.vdm_state > 0) - return EC_RES_BUSY; - - switch (p->cmd) { - case USB_PD_FW_REBOOT: - pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0); - - /* - * Return immediately to free pending i2c bus. Host needs to - * manage this delay. - */ - return EC_RES_SUCCESS; - - case USB_PD_FW_FLASH_ERASE: - pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_FLASH_ERASE, NULL, 0); - - /* - * Return immediately. Host needs to manage delays here which - * can be as long as 1.2 seconds on 64KB RW flash. - */ - return EC_RES_SUCCESS; - - case USB_PD_FW_ERASE_SIG: - pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0); - timeout.val = get_time().val + 500*MSEC; - break; - - case USB_PD_FW_FLASH_WRITE: - /* Data size must be a multiple of 4 */ - if (!p->size || p->size % 4) - return EC_RES_INVALID_PARAM; - - size = p->size / 4; - for (i = 0; i < size; i += VDO_MAX_SIZE - 1) { - pd_send_vdm( USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE, - data + i, MIN(size - i, VDO_MAX_SIZE - 1)); - timeout.val = get_time().val + 500*MSEC; - - /* Wait until VDM is done */ - while ((pd.vdm_state > 0) && - (get_time().val < timeout.val)) - task_wait_event(10*MSEC); - - if (pd.vdm_state > 0) - return EC_RES_TIMEOUT; - } - return EC_RES_SUCCESS; - - default: - return EC_RES_INVALID_PARAM; - break; - } - - /* Wait until VDM is done or timeout */ - while ((pd.vdm_state > 0) && (get_time().val < timeout.val)) - task_wait_event(50*MSEC); - - if ((pd.vdm_state > 0) || - (pd.vdm_state == VDM_STATE_ERR_TMOUT)) - rv = EC_RES_TIMEOUT; - else if (pd.vdm_state < 0) - rv = EC_RES_ERROR; - - return rv; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_FW_UPDATE, - hc_remote_flash, - EC_VER_MASK(0)); - -static int hc_remote_rw_hash_entry(struct host_cmd_handler_args *args) -{ - int i, idx = 0, found = 0; - const struct ec_params_usb_pd_rw_hash_entry *p = args->params; - static int rw_hash_next_idx; - - if (!p->dev_id) - return EC_RES_INVALID_PARAM; - - for (i = 0; i < RW_HASH_ENTRIES; i++) { - if (p->dev_id == rw_hash_table[i].dev_id) { - idx = i; - found = 1; - break; - } - } - if (!found) { - idx = rw_hash_next_idx; - rw_hash_next_idx = rw_hash_next_idx + 1; - if (rw_hash_next_idx == RW_HASH_ENTRIES) - rw_hash_next_idx = 0; - } - memcpy(&rw_hash_table[idx], p, sizeof(*p)); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_RW_HASH_ENTRY, - hc_remote_rw_hash_entry, - EC_VER_MASK(0)); - -static int hc_remote_pd_dev_info(struct host_cmd_handler_args *args) -{ - const uint8_t *port = args->params; - struct ec_params_usb_pd_rw_hash_entry *r = args->response; - - if (*port >= CONFIG_USB_PD_PORT_COUNT) - return EC_RES_INVALID_PARAM; - - r->dev_id = pd[*port].dev_id; - - if (r->dev_id) { - memcpy(r->dev_rw_hash, pd[*port].dev_rw_hash, - PD_RW_HASH_SIZE); - } - - r->current_image = pd[*port].current_image; - - args->response_size = sizeof(*r); - return EC_RES_SUCCESS; -} - -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DEV_INFO, - hc_remote_pd_dev_info, - EC_VER_MASK(0)); - -#ifndef CONFIG_USB_PD_TCPC -#ifdef CONFIG_EC_CMD_PD_CHIP_INFO -static int hc_remote_pd_chip_info(struct host_cmd_handler_args *args) -{ - const struct ec_params_pd_chip_info *p = args->params; - struct ec_response_pd_chip_info *r = args->response, *info; - - if (p->port >= CONFIG_USB_PD_PORT_COUNT) - return EC_RES_INVALID_PARAM; - - if (tcpm_get_chip_info(p->port, p->renew, &info)) - return EC_RES_ERROR; - - memcpy(r, info, sizeof(*r)); - args->response_size = sizeof(*r); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_PD_CHIP_INFO, - hc_remote_pd_chip_info, - EC_VER_MASK(0)); -#endif -#endif - -#ifdef CONFIG_USB_PD_ALT_MODE_DFP -static int hc_remote_pd_set_amode(struct host_cmd_handler_args *args) -{ - const struct ec_params_usb_pd_set_mode_request *p = args->params; - - if ((p->port >= CONFIG_USB_PD_PORT_COUNT) || (!p->svid) || (!p->opos)) - return EC_RES_INVALID_PARAM; - - switch (p->cmd) { - case PD_EXIT_MODE: - if (pd_dfp_exit_mode(p->port, p->svid, p->opos)) - pd_send_vdm(p->port, p->svid, - CMD_EXIT_MODE | VDO_OPOS(p->opos), NULL, 0); - else { - CPRINTF("Failed exit mode\n"); - return EC_RES_ERROR; - } - break; - case PD_ENTER_MODE: - if (pd_dfp_enter_mode(p->port, p->svid, p->opos)) - pd_send_vdm(p->port, p->svid, CMD_ENTER_MODE | - VDO_OPOS(p->opos), NULL, 0); - break; - default: - return EC_RES_INVALID_PARAM; - } - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_SET_AMODE, - hc_remote_pd_set_amode, - EC_VER_MASK(0)); -#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ - -#endif /* HAS_TASK_HOSTCMD */ - -#ifdef CONFIG_CMD_PD_CONTROL - -static int pd_control(struct host_cmd_handler_args *args) -{ - static int pd_control_disabled[CONFIG_USB_PD_PORT_COUNT]; - const struct ec_params_pd_control *cmd = args->params; - int enable = 0; - - if (cmd->chip >= CONFIG_USB_PD_PORT_COUNT) - return EC_RES_INVALID_PARAM; - - /* Always allow disable command */ - if (cmd->subcmd == PD_CONTROL_DISABLE) { - pd_control_disabled[cmd->chip] = 1; - return EC_RES_SUCCESS; - } - - if (pd_control_disabled[cmd->chip]) - return EC_RES_ACCESS_DENIED; - - if (cmd->subcmd == PD_SUSPEND) { - enable = 0; - } else if (cmd->subcmd == PD_RESUME) { - enable = 1; - } else if (cmd->subcmd == PD_RESET) { -#ifdef HAS_TASK_PDCMD - board_reset_pd_mcu(); -#else - return EC_RES_INVALID_COMMAND; -#endif - } else if (cmd->subcmd == PD_CHIP_ON && board_set_tcpc_power_mode) { - board_set_tcpc_power_mode(cmd->chip, 1); - return EC_RES_SUCCESS; - } else { - return EC_RES_INVALID_COMMAND; - } - - pd_comm_enable(cmd->chip, enable); - pd_set_suspend(cmd->chip, !enable); - - return EC_RES_SUCCESS; -} - -DECLARE_HOST_COMMAND(EC_CMD_PD_CONTROL, pd_control, EC_VER_MASK(0)); -#endif /* CONFIG_CMD_PD_CONTROL */ - -#endif /* CONFIG_COMMON_RUNTIME */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h b/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h deleted file mode 100644 index e44504fb..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/tcpm.h +++ /dev/null @@ -1,258 +0,0 @@ -/* Copyright 2015 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 Power delivery port management - common header for TCPM drivers */ - -#ifndef __CROS_EC_USB_PD_TCPM_TCPM_H -#define __CROS_EC_USB_PD_TCPM_TCPM_H - -#include "tcpm_driver.h" -#include "usb_pd_tcpm.h" - -#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \ - !defined(CONFIG_USB_PD_DUAL_ROLE) -#error "DRP auto toggle requires board to have DRP support" -#error "Please upgrade your board configuration" -#endif - -#ifndef CONFIG_USB_PD_TCPC -extern const struct tcpc_config_t tcpc_config; - -/* I2C wrapper functions - get I2C port / slave addr from config struct. */ -int tcpc_write(int reg, int val); -int tcpc_write16(int reg, int val); -int tcpc_read(int reg, int *val); -int tcpc_read16(int reg, int *val); -int tcpc_xfer(const uint8_t *out, int out_size, uint8_t *in, int in_size, - int flags); - -/* TCPM driver wrapper function */ -static inline int tcpm_init() { - int rv; - - rv = tcpc_config.drv->init(); - if (rv) - return rv; - - /* Board specific post TCPC init */ - if (board_tcpc_post_init) - rv = board_tcpc_post_init(); - - return rv; -} - -static inline int tcpm_release() { - return tcpc_config.drv->release(); -} - -static inline int tcpm_get_cc(int *cc1, int *cc2) { - return tcpc_config.drv->get_cc(cc1, cc2); -} - -static inline int tcpm_get_vbus_level() { - return tcpc_config.drv->get_vbus_level(); -} - -static inline int tcpm_select_rp_value(int rp) { - return tcpc_config.drv->select_rp_value(rp); -} - -static inline int tcpm_set_cc(int pull) { - return tcpc_config.drv->set_cc(pull); -} - -static inline int tcpm_set_polarity(int polarity) { - return tcpc_config.drv->set_polarity(polarity); -} - -static inline int tcpm_set_vconn(int enable) { - return tcpc_config.drv->set_vconn(enable); -} - -static inline int tcpm_set_msg_header(int power_role, int data_role) { - return tcpc_config.drv->set_msg_header(power_role, data_role); -} - -static inline int tcpm_set_rx_enable(int enable) { - return tcpc_config.drv->set_rx_enable(enable); -} - -static inline int tcpm_get_message(uint32_t *payload, int *head) { - return tcpc_config.drv->get_message(payload, head); -} - -static inline int tcpm_transmit(enum tcpm_transmit_type type, uint16_t header, - const uint32_t *data) { - return tcpc_config.drv->transmit(type, header, data); -} - -static inline void tcpc_alert() { - tcpc_config.drv->tcpc_alert(); -} - -static inline void tcpc_discharge_vbus(int enable) { - tcpc_config.drv->tcpc_discharge_vbus(enable); -} - -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE -static inline int tcpm_auto_toggle_supported() -{ - return !!tcpc_config.drv->drp_toggle; -} - -static inline int tcpm_set_drp_toggle( int enable) -{ - return tcpc_config.drv->drp_toggle( enable); -} -#endif - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC -static inline int tcpc_i2c_read(const int port, const int addr, - const int reg, int *data) -{ - return tcpc_read( reg, data); -} - -static inline int tcpc_i2c_write(const int port, const int addr, - const int reg, int data) -{ - return tcpc_write( reg, data); -} -#endif - -static inline int tcpm_get_chip_info(int renew, - struct ec_response_pd_chip_info **info) { - if (tcpc_config.drv->get_chip_info) - return tcpc_config.drv->get_chip_info(renew, info); - return EC_ERROR_UNIMPLEMENTED; -} - -#else - -/** - * Initialize TCPM driver and wait for TCPC readiness. - * - * @param port Type-C port number - * - * @return EC_SUCCESS or error - */ -int tcpm_init(); - -/** - * Read the CC line status. - * - * @param port Type-C port number - * @param cc1 pointer to CC status for CC1 - * @param cc2 pointer to CC status for CC2 - * - * @return EC_SUCCESS or error - */ -int tcpm_get_cc( int *cc1, int *cc2); - -/** - * Read VBUS - * - * @param port Type-C port number - * - * @return 0 => VBUS not detected, 1 => VBUS detected - */ -int tcpm_get_vbus_level(); - -/** - * Set the value of the CC pull-up used when we are a source. - * - * @param port Type-C port number - * @param rp One of enum tcpc_rp_value - * - * @return EC_SUCCESS or error - */ -int tcpm_select_rp_value( int rp); - -/** - * Set the CC pull resistor. This sets our role as either source or sink. - * - * @param port Type-C port number - * @param pull One of enum tcpc_cc_pull - * - * @return EC_SUCCESS or error - */ -int tcpm_set_cc( int pull); - -/** - * Set polarity - * - * @param port Type-C port number - * @param polarity 0=> transmit on CC1, 1=> transmit on CC2 - * - * @return EC_SUCCESS or error - */ -int tcpm_set_polarity( int polarity); - -/** - * Set Vconn. - * - * @param port Type-C port number - * @param polarity Polarity of the CC line to read - * - * @return EC_SUCCESS or error - */ -int tcpm_set_vconn( int enable); - -/** - * Set PD message header to use for goodCRC - * - * @param port Type-C port number - * @param power_role Power role to use in header - * @param data_role Data role to use in header - * - * @return EC_SUCCESS or error - */ -int tcpm_set_msg_header( int power_role, int data_role); - -/** - * Set RX enable flag - * - * @param port Type-C port number - * @enable true for enable, false for disable - * - * @return EC_SUCCESS or error - */ -int tcpm_set_rx_enable( int enable); - -/** - * Read last received PD message. - * - * @param port Type-C port number - * @param payload Pointer to location to copy payload of message - * @param header of message - * - * @return EC_SUCCESS or error - */ -int tcpm_get_message( uint32_t *payload, int *head); - -/** - * Transmit PD message - * - * @param port Type-C port number - * @param type Transmit type - * @param header Packet header - * @param cnt Number of bytes in payload - * @param data Payload - * - * @return EC_SUCCESS or error - */ -int tcpm_transmit( enum tcpm_transmit_type type, uint16_t header, - const uint32_t *data); - -/** - * TCPC is asserting alert - * - * @param port Type-C port number - */ -void tcpc_alert(); - -#endif - -#endif diff --git a/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h b/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h deleted file mode 100644 index 86a4fbb3..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/USBC_TCPM/usb_pd_tcpm.h +++ /dev/null @@ -1,344 +0,0 @@ -/* Copyright 2015 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 Power delivery port management */ - -#ifndef __CROS_EC_USB_PD_TCPM_H -#define __CROS_EC_USB_PD_TCPM_H - -/* List of common error codes that can be returned */ -enum ec_error_list { - /* Success - no error */ - EC_SUCCESS = 0, - /* Unknown error */ - EC_ERROR_UNKNOWN = 1, - /* Function not implemented yet */ - EC_ERROR_UNIMPLEMENTED = 2, - /* Overflow error; too much input provided. */ - EC_ERROR_OVERFLOW = 3, - /* Timeout */ - EC_ERROR_TIMEOUT = 4, - /* Invalid argument */ - EC_ERROR_INVAL = 5, - /* Already in use, or not ready yet */ - EC_ERROR_BUSY = 6, - /* Access denied */ - EC_ERROR_ACCESS_DENIED = 7, - /* Failed because component does not have power */ - EC_ERROR_NOT_POWERED = 8, - /* Failed because component is not calibrated */ - EC_ERROR_NOT_CALIBRATED = 9, - /* Failed because CRC error */ - EC_ERROR_CRC = 10, - /* Invalid console command param (PARAMn means parameter n is bad) */ - EC_ERROR_PARAM1 = 11, - EC_ERROR_PARAM2 = 12, - EC_ERROR_PARAM3 = 13, - EC_ERROR_PARAM4 = 14, - EC_ERROR_PARAM5 = 15, - EC_ERROR_PARAM6 = 16, - EC_ERROR_PARAM7 = 17, - EC_ERROR_PARAM8 = 18, - EC_ERROR_PARAM9 = 19, - /* Wrong number of params */ - EC_ERROR_PARAM_COUNT = 20, - /* Interrupt event not handled */ - EC_ERROR_NOT_HANDLED = 21, - /* Data has not changed */ - EC_ERROR_UNCHANGED = 22, - /* Memory allocation */ - EC_ERROR_MEMORY_ALLOCATION = 23, - - /* Verified boot errors */ - EC_ERROR_VBOOT_SIGNATURE = 0x1000, /* 4096 */ - EC_ERROR_VBOOT_SIG_MAGIC = 0x1001, - EC_ERROR_VBOOT_SIG_SIZE = 0x1002, - EC_ERROR_VBOOT_SIG_ALGORITHM = 0x1003, - EC_ERROR_VBOOT_HASH_ALGORITHM = 0x1004, - EC_ERROR_VBOOT_SIG_OFFSET = 0x1005, - EC_ERROR_VBOOT_DATA_SIZE = 0x1006, - - /* Verified boot key errors */ - EC_ERROR_VBOOT_KEY = 0x1100, - EC_ERROR_VBOOT_KEY_MAGIC = 0x1101, - EC_ERROR_VBOOT_KEY_SIZE = 0x1102, - - /* Verified boot data errors */ - EC_ERROR_VBOOT_DATA = 0x1200, - EC_ERROR_VBOOT_DATA_VERIFY = 0x1201, - - /* Module-internal error codes may use this range. */ - EC_ERROR_INTERNAL_FIRST = 0x10000, - EC_ERROR_INTERNAL_LAST = 0x1FFFF -}; - -/* Flags for i2c_xfer() */ -#define I2C_XFER_START (1 << 0) /* Start smbus session from idle state */ -#define I2C_XFER_STOP (1 << 1) /* Terminate smbus session with stop bit */ -#define I2C_XFER_SINGLE (I2C_XFER_START | I2C_XFER_STOP) /* One transaction */ - -/* Default retry count for transmitting */ -#define PD_RETRY_COUNT 3 - -/* Time to wait for TCPC to complete transmit */ -#define PD_T_TCPC_TX_TIMEOUT (100*MSEC) - -enum tcpc_cc_voltage_status { - TYPEC_CC_VOLT_OPEN = 0, - TYPEC_CC_VOLT_RA = 1, - TYPEC_CC_VOLT_RD = 2, - TYPEC_CC_VOLT_SNK_DEF = 5, - TYPEC_CC_VOLT_SNK_1_5 = 6, - TYPEC_CC_VOLT_SNK_3_0 = 7, -}; - -enum tcpc_cc_pull { - TYPEC_CC_RA = 0, TYPEC_CC_RP = 1, TYPEC_CC_RD = 2, TYPEC_CC_OPEN = 3, -}; - -enum tcpc_rp_value { - TYPEC_RP_USB = 0, TYPEC_RP_1A5 = 1, TYPEC_RP_3A0 = 2, TYPEC_RP_RESERVED = 3, -}; - -enum tcpm_transmit_type { - TCPC_TX_SOP = 0, - TCPC_TX_SOP_PRIME = 1, - TCPC_TX_SOP_PRIME_PRIME = 2, - TCPC_TX_SOP_DEBUG_PRIME = 3, - TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4, - TCPC_TX_HARD_RESET = 5, - TCPC_TX_CABLE_RESET = 6, - TCPC_TX_BIST_MODE_2 = 7 -}; - -enum tcpc_transmit_complete { - TCPC_TX_COMPLETE_SUCCESS = 0, - TCPC_TX_COMPLETE_DISCARDED = 1, - TCPC_TX_COMPLETE_FAILED = 2, -}; - -struct tcpm_drv { - /** - * Initialize TCPM driver and wait for TCPC readiness. - * - * @param port Type-C port number - * - * @return EC_SUCCESS or error - */ - int (*init)(); - - /** - * Release the TCPM hardware and disconnect the driver. - * Only .init() can be called after .release(). - * - * @param port Type-C port number - * - * @return EC_SUCCESS or error - */ - int (*release)(); - - /** - * Read the CC line status. - * - * @param port Type-C port number - * @param cc1 pointer to CC status for CC1 - * @param cc2 pointer to CC status for CC2 - * - * @return EC_SUCCESS or error - */ - int (*get_cc)(int *cc1, int *cc2); - - /** - * Read VBUS - * - * @param port Type-C port number - * - * @return 0 => VBUS not detected, 1 => VBUS detected - */ - int (*get_vbus_level)(); - - /** - * Set the value of the CC pull-up used when we are a source. - * - * @param port Type-C port number - * @param rp One of enum tcpc_rp_value - * - * @return EC_SUCCESS or error - */ - int (*select_rp_value)(int rp); - - /** - * Set the CC pull resistor. This sets our role as either source or sink. - * - * @param port Type-C port number - * @param pull One of enum tcpc_cc_pull - * - * @return EC_SUCCESS or error - */ - int (*set_cc)(int pull); - - /** - * Set polarity - * - * @param port Type-C port number - * @param polarity 0=> transmit on CC1, 1=> transmit on CC2 - * - * @return EC_SUCCESS or error - */ - int (*set_polarity)(int polarity); - - /** - * Set Vconn. - * - * @param port Type-C port number - * @param polarity Polarity of the CC line to read - * - * @return EC_SUCCESS or error - */ - int (*set_vconn)(int enable); - - /** - * Set PD message header to use for goodCRC - * - * @param port Type-C port number - * @param power_role Power role to use in header - * @param data_role Data role to use in header - * - * @return EC_SUCCESS or error - */ - int (*set_msg_header)(int power_role, int data_role); - - /** - * Set RX enable flag - * - * @param port Type-C port number - * @enable true for enable, false for disable - * - * @return EC_SUCCESS or error - */ - int (*set_rx_enable)(int enable); - - /** - * Read last received PD message. - * - * @param port Type-C port number - * @param payload Pointer to location to copy payload of message - * @param header of message - * - * @return EC_SUCCESS or error - */ - int (*get_message)(uint32_t *payload, int *head); - - /** - * Transmit PD message - * - * @param port Type-C port number - * @param type Transmit type - * @param header Packet header - * @param cnt Number of bytes in payload - * @param data Payload - * - * @return EC_SUCCESS or error - */ - int (*transmit)(enum tcpm_transmit_type type, uint16_t header, - const uint32_t *data); - - /** - * TCPC is asserting alert - * - * @param port Type-C port number - */ - void (*tcpc_alert)(); - - /** - * Discharge PD VBUS on src/sink disconnect & power role swap - * - * @param port Type-C port number - * @param enable Discharge enable or disable - */ - void (*tcpc_discharge_vbus)(int enable); - -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - /** - * Enable TCPC auto DRP toggling. - * - * @param port Type-C port number - * @param enable 1: Enable 0: Disable - * - * @return EC_SUCCESS or error - */ - int (*drp_toggle)( int enable); -#endif - - /** - * Get firmware version. - * - * @param port Type-C port number - * @param renew Force renewal - * @param info Pointer to pointer to PD chip info - * - * @return EC_SUCCESS or error - */ - int (*get_chip_info)(int renew, struct ec_response_pd_chip_info **info); -}; - -enum tcpc_alert_polarity { - TCPC_ALERT_ACTIVE_LOW, TCPC_ALERT_ACTIVE_HIGH, -}; - -struct tcpc_config_t { - int i2c_slave_addr; - const struct tcpm_drv *drv; -}; - -/** - * Returns the PD_STATUS_TCPC_ALERT_* mask corresponding to the TCPC ports - * that are currently asserting ALERT. - * - * @return PD_STATUS_TCPC_ALERT_* mask. - */ -uint16_t tcpc_get_alert_status(void); - -/** - * Optional, set the TCPC power mode. - * - * @param port Type-C port number - * @param mode 0: off/sleep, 1: on/awake - */ -void board_set_tcpc_power_mode(int mode) __attribute__((weak)); - -/** - * Initialize TCPC. - * - * @param port Type-C port number - */ -void tcpc_init(); - -/** - * TCPC is asserting alert - * - * @param port Type-C port number - */ -void tcpc_alert_clear(); - -/** - * Run TCPC task once. This checks for incoming messages, processes - * any outgoing messages, and reads CC lines. - * - * @param port Type-C port number - * @param evt Event type that woke up this task - */ -int tcpc_run(int evt); - -/** - * Initialize board specific TCPC functions post TCPC initialization. - * - * @param port Type-C port number - * - * @return EC_SUCCESS or error - */ -int board_tcpc_post_init() __attribute__((weak)); - -#endif /* __CROS_EC_USB_PD_TCPM_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp new file mode 100644 index 00000000..46956178 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp @@ -0,0 +1,204 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fusb302b.h" +#include "I2CBB.hpp" +#include + +/* + * Read a single byte from the FUSB302B + * + * cfg: The FUSB302B to communicate with + * addr: The memory address from which to read + * + * Returns the value read from addr. + */ +static uint8_t fusb_read_byte(uint8_t addr) { + uint8_t data[1]; + I2CBB::Mem_Read(FUSB302B_ADDR, addr, (uint8_t*) data, 1); + return data[0]; +} + +/* + * Read multiple bytes from the FUSB302B + * + * cfg: The FUSB302B to communicate with + * addr: The memory address from which to read + * size: The number of bytes to read + * buf: The buffer into which data will be read + */ +static void fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) { + I2CBB::Mem_Read(FUSB302B_ADDR, addr, (uint8_t*) buf, size); + +} + +/* + * Write a single byte to the FUSB302B + * + * cfg: The FUSB302B to communicate with + * addr: The memory address to which we will write + * byte: The value to write + */ +static void fusb_write_byte(uint8_t addr, uint8_t byte) { + I2CBB::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &byte, 1); + +} + +/* + * Write multiple bytes to the FUSB302B + * + * cfg: The FUSB302B to communicate with + * addr: The memory address to which we will write + * size: The number of bytes to write + * buf: The buffer to write + */ +static void fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) { + I2CBB::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &buf, size); + +} + +void fusb_send_message(const union pd_msg *msg) { + /* Token sequences for the FUSB302B */ + static uint8_t sop_seq[5] = { + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP2, + FUSB_FIFO_TX_PACKSYM }; + static const uint8_t eop_seq[4] = { + FUSB_FIFO_TX_JAM_CRC, + FUSB_FIFO_TX_EOP, + FUSB_FIFO_TX_TXOFF, + FUSB_FIFO_TX_TXON }; + + /* Take the I2C2 mutex now so there can't be a race condition on sop_seq */ + /* Get the length of the message: a two-octet header plus NUMOBJ four-octet + * data objects */ + uint8_t msg_len = 2 + 4 * PD_NUMOBJ_GET(msg); + + /* Set the number of bytes to be transmitted in the packet */ + sop_seq[4] = FUSB_FIFO_TX_PACKSYM | msg_len; + + /* Write all three parts of the message to the TX FIFO */ + fusb_write_buf( FUSB_FIFOS, 5, sop_seq); + fusb_write_buf( FUSB_FIFOS, msg_len, msg->bytes); + fusb_write_buf( FUSB_FIFOS, 4, eop_seq); + +} + +uint8_t fusb_read_message(union pd_msg *msg) { + uint8_t garbage[4]; + uint8_t numobj; + + /* If this isn't an SOP message, return error. + * Because of our configuration, we should be able to assume this means the + * buffer is empty, and not try to read past a non-SOP message. */ + if ((fusb_read_byte( FUSB_FIFOS) & FUSB_FIFO_RX_TOKEN_BITS) + != FUSB_FIFO_RX_SOP) { + return 1; + } + /* Read the message header into msg */ + fusb_read_buf( FUSB_FIFOS, 2, msg->bytes); + /* Get the number of data objects */ + numobj = PD_NUMOBJ_GET(msg); + /* If there is at least one data object, read the data objects */ + if (numobj > 0) { + fusb_read_buf( FUSB_FIFOS, numobj * 4, msg->bytes + 2); + } + /* Throw the CRC32 in the garbage, since the PHY already checked it. */ + fusb_read_buf( FUSB_FIFOS, 4, garbage); + + return 0; +} + +void fusb_send_hardrst() { + + /* Send a hard reset */ + fusb_write_byte( FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET); + +} + +void fusb_setup() { + + /* Fully reset the FUSB302B */ + fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES); + + /* Turn on all power */ + fusb_write_byte( FUSB_POWER, 0x0F); + + /* Set interrupt masks */ + fusb_write_byte( FUSB_MASK1, 0x00); + fusb_write_byte( FUSB_MASKA, 0x00); + fusb_write_byte( FUSB_MASKB, 0x00); + fusb_write_byte( FUSB_CONTROL0, 0x04); + + /* Enable automatic retransmission */ + fusb_write_byte( FUSB_CONTROL3, 0x07); + + /* Flush the RX buffer */ + fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); + + /* Measure CC1 */ + fusb_write_byte( FUSB_SWITCHES0, 0x07); + osDelay(1); + uint8_t cc1 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; + + /* Measure CC2 */ + fusb_write_byte( FUSB_SWITCHES0, 0x0B); + osDelay(1); + uint8_t cc2 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; + + /* Select the correct CC line for BMC signaling; also enable AUTO_CRC */ + if (cc1 > cc2) { + fusb_write_byte( FUSB_SWITCHES1, 0x25); + fusb_write_byte( FUSB_SWITCHES0, 0x07); + } else { + fusb_write_byte( FUSB_SWITCHES1, 0x26); + fusb_write_byte( FUSB_SWITCHES0, 0x0B); + } + + /* Reset the PD logic */ + fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); + +} + +void fusb_get_status(union fusb_status *status) { + + /* Read the interrupt and status flags into status */ + fusb_read_buf( FUSB_STATUS0A, 7, status->bytes); + +} + +enum fusb_typec_current fusb_get_typec_current() { + + /* Read the BC_LVL into a variable */ + enum fusb_typec_current bc_lvl = (enum fusb_typec_current) (fusb_read_byte( + FUSB_STATUS0) & FUSB_STATUS0_BC_LVL); + + return bc_lvl; +} + +void fusb_reset() { + + /* Flush the TX buffer */ + fusb_write_byte( FUSB_CONTROL0, 0x44); + /* Flush the RX buffer */ + fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); + /* Reset the PD logic */ + fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); + +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h new file mode 100644 index 00000000..7bb4ed2c --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h @@ -0,0 +1,303 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PDB_FUSB302B_H +#define PDB_FUSB302B_H + +#include + +#include "pd.h" +#include + +/* I2C addresses of the FUSB302B chips */ +#define FUSB302B_ADDR 0x22 +#define FUSB302B01_ADDR 0x23 +#define FUSB302B10_ADDR 0x24 +#define FUSB302B11_ADDR 0x25 + +/* Device ID register */ +#define FUSB_DEVICE_ID 0x01 +#define FUSB_DEVICE_ID_VERSION_ID_SHIFT 4 +#define FUSB_DEVICE_ID_VERSION_ID (0xF << FUSB_DEVICE_ID_VERSION_ID_SHIFT) +#define FUSB_DEVICE_ID_PRODUCT_ID_SHIFT 2 +#define FUSB_DEVICE_ID_PRODUCT_ID (0x3 << FUSB_DEVICE_ID_PRODUCT_ID_SHIFT) +#define FUSB_DEVICE_ID_REVISION_ID_SHIFT 0 +#define FUSB_DEVICE_ID_REVISION_ID (0x3 << FUSB_DEVICE_ID_REVISION_ID_SHIFT) + +/* Switches0 register */ +#define FUSB_SWITCHES0 0x02 +#define FUSB_SWITCHES0_PU_EN2 (1 << 7) +#define FUSB_SWITCHES0_PU_EN1 (1 << 6) +#define FUSB_SWITCHES0_VCONN_CC2 (1 << 5) +#define FUSB_SWITCHES0_VCONN_CC1 (1 << 4) +#define FUSB_SWITCHES0_MEAS_CC2 (1 << 3) +#define FUSB_SWITCHES0_MEAS_CC1 (1 << 2) +#define FUSB_SWITCHES0_PDWN_2 (1 << 1) +#define FUSB_SWITCHES0_PDWN_1 1 + +/* Switches1 register */ +#define FUSB_SWITCHES1 0x03 +#define FUSB_SWITCHES1_POWERROLE (1 << 7) +#define FUSB_SWITCHES1_SPECREV_SHIFT 5 +#define FUSB_SWITCHES1_SPECREV (0x3 << FUSB_SWITCHES1_SPECREV_SHIFT) +#define FUSB_SWITCHES1_DATAROLE (1 << 4) +#define FUSB_SWITCHES1_AUTO_CRC (1 << 2) +#define FUSB_SWITCHES1_TXCC2 (1 << 1) +#define FUSB_SWITCHES1_TXCC1 1 + +/* Measure register */ +#define FUSB_MEASURE 0x04 +#define FUSB_MEASURE_MEAS_VBUS (1 << 6) +#define FUSB_MEASURE_MDAC_SHIFT 0 +#define FUSB_MEASURE_MDAC (0x3F << FUSB_MEASURE_MDAC_SHIFT) + +/* Slice register */ +#define FUSB_SLICE 0x05 +#define FUSB_SLICE_SDAC_HYS_SHIFT 6 +#define FUSB_SLICE_SDAC_HYS (0x3 << FUSB_SLICE_SDAC_HYS_SHIFT) +#define FUSB_SLICE_SDAC_SHIFT 0 +#define FUSB_SLICE_SDAC (0x3F << FUSB_SLICE_SDAC_SHIFT) + +/* Control0 register */ +#define FUSB_CONTROL0 0x06 +#define FUSB_CONTROL0_TX_FLUSH (1 << 6) +#define FUSB_CONTROL0_INT_MASK (1 << 5) +#define FUSB_CONTROL0_HOST_CUR_SHIFT 2 +#define FUSB_CONTROL0_HOST_CUR (0x3 << FUSB_CONTROL0_HOST_CUR_SHIFT) +#define FUSB_CONTROL0_AUTO_PRE (1 << 1) +#define FUSB_CONTROL0_TX_START 1 + +/* Control1 register */ +#define FUSB_CONTROL1 0x07 +#define FUSB_CONTROL1_ENSOP2DB (1 << 6) +#define FUSB_CONTROL1_ENSOP1DB (1 << 5) +#define FUSB_CONTROL1_BIST_MODE2 (1 << 4) +#define FUSB_CONTROL1_RX_FLUSH (1 << 2) +#define FUSB_CONTROL1_ENSOP2 (1 << 1) +#define FUSB_CONTROL1_ENSOP1 1 + +/* Control2 register */ +#define FUSB_CONTROL2 0x08 +#define FUSB_CONTROL2_TOG_SAVE_PWR_SHIFT 6 +#define FUSB_CONTROL2_TOG_SAVE_PWR (0x3 << FUSB_CONTROL2_TOG_SAVE_PWR) +#define FUSB_CONTROL2_TOG_RD_ONLY (1 << 5) +#define FUSB_CONTROL2_WAKE_EN (1 << 3) +#define FUSB_CONTROL2_MODE_SHIFT 1 +#define FUSB_CONTROL2_MODE (0x3 << FUSB_CONTROL2_MODE_SHIFT) +#define FUSB_CONTROL2_TOGGLE 1 + +/* Control3 register */ +#define FUSB_CONTROL3 0x09 +#define FUSB_CONTROL3_SEND_HARD_RESET (1 << 6) +#define FUSB_CONTROL3_BIST_TMODE (1 << 5) +#define FUSB_CONTROL3_AUTO_HARDRESET (1 << 4) +#define FUSB_CONTROL3_AUTO_SOFTRESET (1 << 3) +#define FUSB_CONTROL3_N_RETRIES_SHIFT 1 +#define FUSB_CONTROL3_N_RETRIES (0x3 << FUSB_CONTROL3_N_RETRIES_SHIFT) +#define FUSB_CONTROL3_AUTO_RETRY 1 + +/* Mask1 register */ +#define FUSB_MASK1 0x0A +#define FUSB_MASK1_M_VBUSOK (1 << 7) +#define FUSB_MASK1_M_ACTIVITY (1 << 6) +#define FUSB_MASK1_M_COMP_CHNG (1 << 5) +#define FUSB_MASK1_M_CRC_CHK (1 << 4) +#define FUSB_MASK1_M_ALERT (1 << 3) +#define FUSB_MASK1_M_WAKE (1 << 2) +#define FUSB_MASK1_M_COLLISION (1 << 1) +#define FUSB_MASK1_M_BC_LVL (1 << 0) + +/* Power register */ +#define FUSB_POWER 0x0B +#define FUSB_POWER_PWR3 (1 << 3) +#define FUSB_POWER_PWR2 (1 << 2) +#define FUSB_POWER_PWR1 (1 << 1) +#define FUSB_POWER_PWR0 1 + +/* Reset register */ +#define FUSB_RESET 0x0C +#define FUSB_RESET_PD_RESET (1 << 1) +#define FUSB_RESET_SW_RES 1 + +/* OCPreg register */ +#define FUSB_OCPREG 0x0D +#define FUSB_OCPREG_OCP_RANGE (1 << 3) +#define FUSB_OCPREG_OCP_CUR_SHIFT 0 +#define FUSB_OCPREG_OCP_CUR (0x7 << FUSB_OCPREG_OCP_CUR_SHIFT) + +/* Maska register */ +#define FUSB_MASKA 0x0E +#define FUSB_MASKA_M_OCP_TEMP (1 << 7) +#define FUSB_MASKA_M_TOGDONE (1 << 6) +#define FUSB_MASKA_M_SOFTFAIL (1 << 5) +#define FUSB_MASKA_M_RETRYFAIL (1 << 4) +#define FUSB_MASKA_M_HARDSENT (1 << 3) +#define FUSB_MASKA_M_TXSENT (1 << 2) +#define FUSB_MASKA_M_SOFTRST (1 << 1) +#define FUSB_MASKA_M_HARDRST 1 + +/* Maskb register */ +#define FUSB_MASKB 0x0F +#define FUSB_MASKB_M_GCRCSENT 1 + +/* Control4 register */ +#define FUSB_CONTROL4 0x10 +#define FUSB_CONTROL4_TOG_EXIT_AUD 1 + +/* Status0a register */ +#define FUSB_STATUS0A 0x3C +#define FUSB_STATUS0A_SOFTFAIL (1 << 5) +#define FUSB_STATUS0A_RETRYFAIL (1 << 4) +#define FUSB_STATUS0A_POWER3 (1 << 3) +#define FUSB_STATUS0A_POWER2 (1 << 2) +#define FUSB_STATUS0A_SOFTRST (1 << 1) +#define FUSB_STATUS0A_HARDRST 1 + +/* Status1a register */ +#define FUSB_STATUS1A 0x3D +#define FUSB_STATUS1A_TOGSS_SHIFT 3 +#define FUSB_STATUS1A_TOGSS (0x7 << FUSB_STATUS1A_TOGSS_SHIFT) +#define FUSB_STATUS1A_RXSOP2DB (1 << 2) +#define FUSB_STATUS1A_RXSOP1DB (1 << 1) +#define FUSB_STATUS1A_RXSOP 1 + +/* Interrupta register */ +#define FUSB_INTERRUPTA 0x3E +#define FUSB_INTERRUPTA_I_OCP_TEMP (1 << 7) +#define FUSB_INTERRUPTA_I_TOGDONE (1 << 6) +#define FUSB_INTERRUPTA_I_SOFTFAIL (1 << 5) +#define FUSB_INTERRUPTA_I_RETRYFAIL (1 << 4) +#define FUSB_INTERRUPTA_I_HARDSENT (1 << 3) +#define FUSB_INTERRUPTA_I_TXSENT (1 << 2) +#define FUSB_INTERRUPTA_I_SOFTRST (1 << 1) +#define FUSB_INTERRUPTA_I_HARDRST 1 + +/* Interruptb register */ +#define FUSB_INTERRUPTB 0x3F +#define FUSB_INTERRUPTB_I_GCRCSENT 1 + +/* Status0 register */ +#define FUSB_STATUS0 0x40 +#define FUSB_STATUS0_VBUSOK (1 << 7) +#define FUSB_STATUS0_ACTIVITY (1 << 6) +#define FUSB_STATUS0_COMP (1 << 5) +#define FUSB_STATUS0_CRC_CHK (1 << 4) +#define FUSB_STATUS0_ALERT (1 << 3) +#define FUSB_STATUS0_WAKE (1 << 2) +#define FUSB_STATUS0_BC_LVL_SHIFT 0 +#define FUSB_STATUS0_BC_LVL (0x3 << FUSB_STATUS0_BC_LVL_SHIFT) + +/* Status1 register */ +#define FUSB_STATUS1 0x41 +#define FUSB_STATUS1_RXSOP2 (1 << 7) +#define FUSB_STATUS1_RXSOP1 (1 << 6) +#define FUSB_STATUS1_RX_EMPTY (1 << 5) +#define FUSB_STATUS1_RX_FULL (1 << 4) +#define FUSB_STATUS1_TX_EMPTY (1 << 3) +#define FUSB_STATUS1_TX_FULL (1 << 2) +#define FUSB_STATUS1_OVRTEMP (1 << 1) +#define FUSB_STATUS1_OCP 1 + +/* Interrupt register */ +#define FUSB_INTERRUPT 0x42 +#define FUSB_INTERRUPT_I_VBUSOK (1 << 7) +#define FUSB_INTERRUPT_I_ACTIVITY (1 << 6) +#define FUSB_INTERRUPT_I_COMP_CHNG (1 << 5) +#define FUSB_INTERRUPT_I_CRC_CHK (1 << 4) +#define FUSB_INTERRUPT_I_ALERT (1 << 3) +#define FUSB_INTERRUPT_I_WAKE (1 << 2) +#define FUSB_INTERRUPT_I_COLLISION (1 << 1) +#define FUSB_INTERRUPT_I_BC_LVL 1 + +/* FIFOs register */ +#define FUSB_FIFOS 0x43 + +#define FUSB_FIFO_TX_TXON 0xA1 +#define FUSB_FIFO_TX_SOP1 0x12 +#define FUSB_FIFO_TX_SOP2 0x13 +#define FUSB_FIFO_TX_SOP3 0x1B +#define FUSB_FIFO_TX_RESET1 0x15 +#define FUSB_FIFO_TX_RESET2 0x16 +#define FUSB_FIFO_TX_PACKSYM 0x80 +#define FUSB_FIFO_TX_JAM_CRC 0xFF +#define FUSB_FIFO_TX_EOP 0x14 +#define FUSB_FIFO_TX_TXOFF 0xFE + +#define FUSB_FIFO_RX_TOKEN_BITS 0xE0 +#define FUSB_FIFO_RX_SOP 0xE0 +#define FUSB_FIFO_RX_SOP1 0xC0 +#define FUSB_FIFO_RX_SOP2 0xA0 +#define FUSB_FIFO_RX_SOP1DB 0x80 +#define FUSB_FIFO_RX_SOP2DB 0x60 + +/* + * FUSB status union + * + * Provides a nicer structure than just an array of uint8_t for working with + * the FUSB302B status and interrupt flags. + */ +union fusb_status { + uint8_t bytes[7]; + struct { + uint8_t status0a; + uint8_t status1a; + uint8_t interrupta; + uint8_t interruptb; + uint8_t status0; + uint8_t status1; + uint8_t interrupt; + }; +}; + +/* FUSB functions */ + +/* + * Send a USB Power Delivery message to the FUSB302B + */ +void fusb_send_message(const union pd_msg *msg); + +/* + * Read a USB Power Delivery message from the FUSB302B + */ +uint8_t fusb_read_message(union pd_msg *msg); + +/* + * Tell the FUSB302B to send a hard reset signal + */ +void fusb_send_hardrst(); + +/* + * Read the FUSB302B status and interrupt flags into *status + */ +void fusb_get_status(union fusb_status *status); + +/* + * Read the FUSB302B BC_LVL as an enum fusb_typec_current + */ +enum fusb_typec_current fusb_get_typec_current(); + +/* + * Initialization routine for the FUSB302B + */ +void fusb_setup(); + +/* + * Reset the FUSB302B + */ +void fusb_reset(); + +#endif /* PDB_FUSB302B_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp new file mode 100644 index 00000000..00b84e96 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -0,0 +1,38 @@ +/* + * fusbpd.cpp + * + * Created on: 13 Jun 2020 + * Author: Ralim + */ + +#include +#include +#include "I2CBB.hpp" +#include "fusb302b.h" +#include "policy_engine.h" +#include "protocol_rx.h" +#include "protocol_tx.h" +#include "int_n.h" +#include "hard_reset.h" + +uint8_t fusb302_detect() { + //Probe the I2C bus for its address + return I2CBB::probe(FUSB302B_ADDR); +} + +void fusb302_start_processing() { + + /* Initialize the FUSB302B */ + fusb_setup(); + + /* Create the policy engine thread. */ + PolicyEngine::init(); + + /* Create the protocol layer threads. */ + ProtocolReceive::init(); + ProtocolTransmit::init(); + ResetHandler::init(); + + /* Create the INT_N thread. */ + InterruptHandler::init(); +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.h b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.h new file mode 100644 index 00000000..b48dfc4e --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.h @@ -0,0 +1,18 @@ +/* + * fusbpd.h + * + * Created on: 13 Jun 2020 + * Author: Ralim + */ + +#ifndef DRIVERS_FUSB302_FUSBPD_H_ +#define DRIVERS_FUSB302_FUSBPD_H_ +//Wrapper for all of the FUSB302 PD work +extern struct pdb_config pdb_config_data; +#include + +//returns 1 if the FUSB302 is on the I2C bus +uint8_t fusb302_detect(); + +void fusb302_start_processing(); +#endif /* DRIVERS_FUSB302_FUSBPD_H_ */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp new file mode 100644 index 00000000..648a7f4e --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp @@ -0,0 +1,148 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hard_reset.h" +#include "fusbpd.h" +#include +#include "policy_engine.h" +#include "protocol_rx.h" +#include "protocol_tx.h" +#include "fusb302b.h" + +osThreadId ResetHandler::TaskHandle; +uint32_t ResetHandler::TaskBuffer[ResetHandler::TaskStackSize]; +osStaticThreadDef_t ResetHandler::TaskControlBlock; + +/* + * PRL_HR_Reset_Layer state + */ +ResetHandler::hardrst_state ResetHandler::hardrst_reset_layer() { + /* First, wait for the signal to run a hard reset. */ + eventmask_t evt = waitForEvent( + PDB_EVT_HARDRST_RESET | PDB_EVT_HARDRST_I_HARDRST); + + /* Reset the Protocol RX machine */ + ProtocolReceive::notify( PDB_EVT_PRLRX_RESET); + taskYIELD(); + + /* Reset the Protocol TX machine */ + ProtocolTransmit::notify(PDB_EVT_PRLTX_RESET); + taskYIELD(); + + /* Continue the process based on what event started the reset. */ + if (evt & PDB_EVT_HARDRST_RESET) { + /* Policy Engine started the reset. */ + return PRLHRRequestHardReset; + } else { + /* PHY started the reset */ + return PRLHRIndicateHardReset; + } +} + +ResetHandler::hardrst_state ResetHandler::hardrst_indicate_hard_reset() { + /* Tell the PE that we're doing a hard reset */ + PolicyEngine::notify( PDB_EVT_PE_RESET); + + return PRLHRWaitPE; +} + +ResetHandler::hardrst_state ResetHandler::hardrst_request_hard_reset() { + /* Tell the PHY to send a hard reset */ + fusb_send_hardrst(); + + return PRLHRWaitPHY; +} + +ResetHandler::hardrst_state ResetHandler::hardrst_wait_phy() { + /* Wait for the PHY to tell us that it's done sending the hard reset */ + waitForEvent(PDB_EVT_HARDRST_I_HARDSENT, PD_T_HARD_RESET_COMPLETE); + + /* Move on no matter what made us stop waiting. */ + return PRLHRHardResetRequested; +} + +ResetHandler::hardrst_state ResetHandler::hardrst_hard_reset_requested() { + /* Tell the PE that the hard reset was sent */ + PolicyEngine::notify( PDB_EVT_PE_HARD_SENT); + + return PRLHRWaitPE; +} + +ResetHandler::hardrst_state ResetHandler::hardrst_wait_pe() { + /* Wait for the PE to tell us that it's done */ + waitForEvent(PDB_EVT_HARDRST_DONE); + + return PRLHRComplete; +} + +ResetHandler::hardrst_state ResetHandler::hardrst_complete() { + /* I'm not aware of anything we have to tell the FUSB302B, so just finish + * the reset routine. */ + return PRLHRResetLayer; +} + +void ResetHandler::init() { + osThreadStaticDef(Task, Thread, PDB_PRIO_PE, 0, TaskStackSize, TaskBuffer, + &TaskControlBlock); + TaskHandle = osThreadCreate(osThread(Task), NULL); +} + +void ResetHandler::notify(uint32_t notification) { + xTaskNotify(TaskHandle, notification, + eNotifyAction::eSetValueWithOverwrite); +} + +void ResetHandler::Thread(const void *arg) { + (void) arg; + ResetHandler::hardrst_state state = PRLHRResetLayer; + + while (true) { + switch (state) { + case PRLHRResetLayer: + state = hardrst_reset_layer(); + break; + case PRLHRIndicateHardReset: + state = hardrst_indicate_hard_reset(); + break; + case PRLHRRequestHardReset: + state = hardrst_request_hard_reset(); + break; + case PRLHRWaitPHY: + state = hardrst_wait_phy(); + break; + case PRLHRHardResetRequested: + state = hardrst_hard_reset_requested(); + break; + case PRLHRWaitPE: + state = hardrst_wait_pe(); + break; + case PRLHRComplete: + state = hardrst_complete(); + break; + default: + /* This is an error. It really shouldn't happen. We might + * want to handle it anyway, though. */ + break; + } + } +} + +uint32_t ResetHandler::waitForEvent(uint32_t mask, uint32_t ticksToWait) { + uint32_t pulNotificationValue; + xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait); + return pulNotificationValue; +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h new file mode 100644 index 00000000..46ab9bd8 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h @@ -0,0 +1,63 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PDB_HARD_RESET_H +#define PDB_HARD_RESET_H + +#include + +/* Events for the Hard Reset thread */ +#define PDB_EVT_HARDRST_RESET EVENT_MASK(0) +#define PDB_EVT_HARDRST_I_HARDRST EVENT_MASK(1) +#define PDB_EVT_HARDRST_I_HARDSENT EVENT_MASK(2) +#define PDB_EVT_HARDRST_DONE EVENT_MASK(3) + +class ResetHandler { +public: + static void init(); + static void notify(uint32_t notification); +private: + static void Thread(const void *arg); + static osThreadId TaskHandle; + static const size_t TaskStackSize = 1024 / 4; + static uint32_t TaskBuffer[TaskStackSize]; + static osStaticThreadDef_t TaskControlBlock; + static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait = + portMAX_DELAY); + + /* + * Hard Reset machine states + */ + enum hardrst_state { + PRLHRResetLayer, + PRLHRIndicateHardReset, + PRLHRRequestHardReset, + PRLHRWaitPHY, + PRLHRHardResetRequested, + PRLHRWaitPE, + PRLHRComplete + }; + static hardrst_state hardrst_reset_layer(); + static hardrst_state hardrst_indicate_hard_reset(); + static hardrst_state hardrst_request_hard_reset(); + static hardrst_state hardrst_wait_phy(); + static hardrst_state hardrst_hard_reset_requested(); + static hardrst_state hardrst_wait_pe(); + static hardrst_state hardrst_complete(); +}; + +#endif /* PDB_HARD_RESET_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp new file mode 100644 index 00000000..58ea1b9d --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -0,0 +1,97 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "int_n.h" +#include "fusbpd.h" +#include +#include "fusb302b.h" +#include "protocol_rx.h" +#include "protocol_tx.h" +#include "hard_reset.h" +#include "policy_engine.h" +#include "protocol_rx.h" +#include "protocol_tx.h" +#include "BSP.h" + +osThreadId InterruptHandler::TaskHandle; +uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize]; +osStaticThreadDef_t InterruptHandler::TaskControlBlock; + +void InterruptHandler::init() { + osThreadStaticDef(Task, Thread, PDB_PRIO_PE, 0, TaskStackSize, TaskBuffer, + &TaskControlBlock); + TaskHandle = osThreadCreate(osThread(Task), NULL); +} + +void InterruptHandler::Thread(const void *arg) { + (void) arg; + union fusb_status status; + eventmask_t events; + //TODO use IRQ task notification to unblock this thread to stop it spinning + while (true) { + /* If the INT_N line is low */ + if (pd_irq_read() == 0) { + /* Read the FUSB302B status and interrupt registers */ + fusb_get_status(&status); + //Check for rx alerts + { + /* If the I_GCRCSENT flag is set, tell the Protocol RX thread */ + if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) { + ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT); + } + } + /* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX + * thread */ + { + events = 0; + if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) { + events |= PDB_EVT_PRLTX_I_RETRYFAIL; + } + if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) { + events |= PDB_EVT_PRLTX_I_TXSENT; + } + if (events) { + ProtocolTransmit::notify(events); + } + } + /* If the I_HARDRST or I_HARDSENT flag is set, tell the Hard Reset + * thread */ + { + events = 0; + if (status.interrupta & FUSB_INTERRUPTA_I_HARDRST) { + events |= PDB_EVT_HARDRST_I_HARDRST; + } + if (status.interrupta & FUSB_INTERRUPTA_I_HARDSENT) { + events |= PDB_EVT_HARDRST_I_HARDSENT; + } + if (events) { + ResetHandler::notify(events); + } + } + { + /* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy + * Engine thread */ + if (status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP + && status.status1 & FUSB_STATUS1_OVRTEMP) { + PolicyEngine::notify(PDB_EVT_PE_I_OVRTEMP); + } + } + + } + osDelay(1); + } +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.h b/workspace/TS100/Core/Drivers/FUSB302/int_n.h new file mode 100644 index 00000000..68dc04d8 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.h @@ -0,0 +1,56 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PDB_INT_N_OLD_H +#define PDB_INT_N_OLD_H + +#include + +class InterruptHandler { +public: + //Creates the thread to handle the Interrupt pin + static void init(); + //TODO handle irq callbacks instead of polling the pin + +private: + static void Thread(const void *arg); + static osThreadId TaskHandle; + static const size_t TaskStackSize = 1024 / 4; + static uint32_t TaskBuffer[TaskStackSize]; + static osStaticThreadDef_t TaskControlBlock; + /* + * Hard Reset machine states + */ + enum hardrst_state { + PRLHRResetLayer, + PRLHRIndicateHardReset, + PRLHRRequestHardReset, + PRLHRWaitPHY, + PRLHRHardResetRequested, + PRLHRWaitPE, + PRLHRComplete + }; + static enum hardrst_state hardrst_reset_layer(); + static enum hardrst_state hardrst_indicate_hard_reset(); + static enum hardrst_state hardrst_request_hard_reset(); + static enum hardrst_state hardrst_wait_phy(); + static enum hardrst_state hardrst_hard_reset_requested(); + static enum hardrst_state hardrst_wait_pe(); + static enum hardrst_state hardrst_complete(); +}; + +#endif /* PDB_INT_N_OLD_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/pd.h b/workspace/TS100/Core/Drivers/FUSB302/pd.h new file mode 100644 index 00000000..c6b94c6c --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/pd.h @@ -0,0 +1,402 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PDB_PD_H +#define PDB_PD_H + +#include +#include "FreeRTOS.h" +#include "pdb_msg.h" +#include "cmsis_os.h" +#include "pdb_conf.h" +/* + * Macros for working with USB Power Delivery messages. + * + * This file is mostly written from the PD Rev. 2.0 spec, but the header is + * written from the Rev. 3.0 spec. + */ + +/* + * PD Header + */ +#define PD_HDR_MSGTYPE_SHIFT 0 +#define PD_HDR_MSGTYPE (0x1F << PD_HDR_MSGTYPE_SHIFT) +#define PD_HDR_DATAROLE_SHIFT 5 +#define PD_HDR_DATAROLE (0x1 << PD_HDR_DATAROLE_SHIFT) +#define PD_HDR_SPECREV_SHIFT 6 +#define PD_HDR_SPECREV (0x3 << PD_HDR_SPECREV_SHIFT) +#define PD_HDR_POWERROLE_SHIFT 8 +#define PD_HDR_POWERROLE (1 << PD_HDR_POWERROLE_SHIFT) +#define PD_HDR_MESSAGEID_SHIFT 9 +#define PD_HDR_MESSAGEID (0x7 << PD_HDR_MESSAGEID_SHIFT) +#define PD_HDR_NUMOBJ_SHIFT 12 +#define PD_HDR_NUMOBJ (0x7 << PD_HDR_NUMOBJ_SHIFT) +#define PD_HDR_EXT (1 << 15) + +/* Message types */ +#define PD_MSGTYPE_GET(msg) (((msg)->hdr & PD_HDR_MSGTYPE) >> PD_HDR_MSGTYPE_SHIFT) +/* Control Message */ +#define PD_MSGTYPE_GOODCRC 0x01 +#define PD_MSGTYPE_GOTOMIN 0x02 +#define PD_MSGTYPE_ACCEPT 0x03 +#define PD_MSGTYPE_REJECT 0x04 +#define PD_MSGTYPE_PING 0x05 +#define PD_MSGTYPE_PS_RDY 0x06 +#define PD_MSGTYPE_GET_SOURCE_CAP 0x07 +#define PD_MSGTYPE_GET_SINK_CAP 0x08 +#define PD_MSGTYPE_DR_SWAP 0x09 +#define PD_MSGTYPE_PR_SWAP 0x0A +#define PD_MSGTYPE_VCONN_SWAP 0x0B +#define PD_MSGTYPE_WAIT 0x0C +#define PD_MSGTYPE_SOFT_RESET 0x0D +#define PD_MSGTYPE_NOT_SUPPORTED 0x10 +#define PD_MSGTYPE_GET_SOURCE_CAP_EXTENDED 0x11 +#define PD_MSGTYPE_GET_STATUS 0x12 +#define PD_MSGTYPE_FR_SWAP 0x13 +#define PD_MSGTYPE_GET_PPS_STATUS 0x14 +#define PD_MSGTYPE_GET_COUNTRY_CODES 0x15 +/* Data Message */ +#define PD_MSGTYPE_SOURCE_CAPABILITIES 0x01 +#define PD_MSGTYPE_REQUEST 0x02 +#define PD_MSGTYPE_BIST 0x03 +#define PD_MSGTYPE_SINK_CAPABILITIES 0x04 +#define PD_MSGTYPE_BATTERY_STATUS 0x05 +#define PD_MSGTYPE_ALERT 0x06 +#define PD_MSGTYPE_GET_COUNTRY_INFO 0x07 +#define PD_MSGTYPE_VENDOR_DEFINED 0x0F +/* Extended Message */ +#define PD_MSGTYPE_SOURCE_CAPABILITIES_EXTENDED 0x01 +#define PD_MSGTYPE_STATUS 0x02 +#define PD_MSGTYPE_GET_BATTERY_CAP 0x03 +#define PD_MSGTYPE_GET_BATTERY_STATUS 0x04 +#define PD_MSGTYPE_BATTERY_CAPABILITIES 0x05 +#define PD_MSGTYPE_GET_MANUFACTURER_INFO 0x06 +#define PD_MSGTYPE_MANUFACTURER_INFO 0x07 +#define PD_MSGTYPE_SECURITY_REQUEST 0x08 +#define PD_MSGTYPE_SECURITY_RESPONSE 0x09 +#define PD_MSGTYPE_FIRMWARE_UPDATE_REQUEST 0x0A +#define PD_MSGTYPE_FIRMWARE_UPDATE_RESPONSE 0x0B +#define PD_MSGTYPE_PPS_STATUS 0x0C +#define PD_MSGTYPE_COUNTRY_INFO 0x0D +#define PD_MSGTYPE_COUNTRY_CODES 0x0E + +/* Data roles */ +#define PD_DATAROLE_UFP (0x0 << PD_HDR_DATAROLE_SHIFT) +#define PD_DATAROLE_DFP (0x1 << PD_HDR_DATAROLE_SHIFT) + +/* Specification revisions */ +#define PD_SPECREV_1_0 (0x0 << PD_HDR_SPECREV_SHIFT) +#define PD_SPECREV_2_0 (0x1 << PD_HDR_SPECREV_SHIFT) +#define PD_SPECREV_3_0 (0x2 << PD_HDR_SPECREV_SHIFT) + +/* Port power roles */ +#define PD_POWERROLE_SINK (0x0 << PD_HDR_POWERROLE_SHIFT) +#define PD_POWERROLE_SOURCE (0x1 << PD_HDR_POWERROLE_SHIFT) + +/* Message ID */ +#define PD_MESSAGEID_GET(msg) (((msg)->hdr & PD_HDR_MESSAGEID) >> PD_HDR_MESSAGEID_SHIFT) + +/* Number of data objects */ +#define PD_NUMOBJ(n) (((n) << PD_HDR_NUMOBJ_SHIFT) & PD_HDR_NUMOBJ) +#define PD_NUMOBJ_GET(msg) (((msg)->hdr & PD_HDR_NUMOBJ) >> PD_HDR_NUMOBJ_SHIFT) + +/* + * PD Extended Message Header + */ +#define PD_EXTHDR_DATA_SIZE_SHIFT 0 +#define PD_EXTHDR_DATA_SIZE (0x1FF << PD_EXTHDR_DATA_SIZE_SHIFT) +#define PD_EXTHDR_REQUEST_CHUNK_SHIFT 10 +#define PD_EXTHDR_REQUEST_CHUNK (1 << PD_EXTHDR_REQUEST_CHUNK_SHIFT) +#define PD_EXTHDR_CHUNK_NUMBER_SHIFT 11 +#define PD_EXTHDR_CHUNK_NUMBER (0xF << PD_EXTHDR_CHUNK_NUMBER_SHIFT) +#define PD_EXTHDR_CHUNKED_SHIFT 15 +#define PD_EXTHDR_CHUNKED (1 << PD_EXTHDR_CHUNKED_SHIFT) + +/* Data size */ +#define PD_DATA_SIZE(n) (((n) << PD_EXTHDR_DATA_SIZE_SHIFT) & PD_EXTHDR_DATA_SIZE) +#define PD_DATA_SIZE_GET(msg) (((msg)->exthdr & PD_EXTHDR_DATA_SIZE) >> PD_EXTHDR_DATA_SIZE_SHIFT) + +/* Chunk number */ +#define PD_CHUNK_NUMBER(n) (((n) << PD_EXTHDR_CHUNK_NUMBER_SHIFT) & PD_EXTHDR_CHUNK_NUMBER) +#define PD_CHUNK_NUMBER_GET(msg) (((msg)->exthdr & PD_EXTHDR_CHUNK_NUMBER) >> PD_EXTHDR_CHUNK_NUMBER_SHIFT) + +/* + * PD Power Data Object + */ +#define PD_PDO_TYPE_SHIFT 30 +#define PD_PDO_TYPE (0x3 << PD_PDO_TYPE_SHIFT) + +/* PDO types */ +#define PD_PDO_TYPE_FIXED ((unsigned) (0x0 << PD_PDO_TYPE_SHIFT)) +#define PD_PDO_TYPE_BATTERY ((unsigned) (0x1 << PD_PDO_TYPE_SHIFT)) +#define PD_PDO_TYPE_VARIABLE ((unsigned) (0x2 << PD_PDO_TYPE_SHIFT)) +#define PD_PDO_TYPE_AUGMENTED ((unsigned) (0x3 << PD_PDO_TYPE_SHIFT)) + +#define PD_APDO_TYPE_SHIFT 28 +#define PD_APDO_TYPE (0x3 << PD_APDO_TYPE_SHIFT) + +/* APDO types */ +#define PD_APDO_TYPE_PPS (0x0 << PD_APDO_TYPE_SHIFT) + +/* PD Source Fixed PDO */ +#define PD_PDO_SRC_FIXED_DUAL_ROLE_PWR_SHIFT 29 +#define PD_PDO_SRC_FIXED_DUAL_ROLE_PWR (1 << PD_PDO_SRC_FIXED_DUAL_ROLE_PWR_SHIFT) +#define PD_PDO_SRC_FIXED_USB_SUSPEND_SHIFT 28 +#define PD_PDO_SRC_FIXED_USB_SUSPEND (1 << PD_PDO_SRC_FIXED_USB_SUSPEND_SHIFT) +#define PD_PDO_SRC_FIXED_UNCONSTRAINED_SHIFT 27 +#define PD_PDO_SRC_FIXED_UNCONSTRAINED (1 << PD_PDO_SRC_FIXED_UNCONSTRAINED_SHIFT) +#define PD_PDO_SRC_FIXED_USB_COMMS_SHIFT 26 +#define PD_PDO_SRC_FIXED_USB_COMMS (1 << PD_PDO_SRC_FIXED_USB_COMMS_SHIFT) +#define PD_PDO_SRC_FIXED_DUAL_ROLE_DATA_SHIFT 25 +#define PD_PDO_SRC_FIXED_DUAL_ROLE_DATA (1 << PD_PDO_SRC_FIXED_DUAL_ROLE_DATA_SHIFT) +#define PD_PDO_SRC_FIXED_UNCHUNKED_EXT_MSG_SHIFT 24 +#define PD_PDO_SRC_FIXED_UNCHUNKED_EXT_MSG (1 << PD_PDO_SRC_FIXED_UNCHUNKED_EXT_MSG_SHIFT) +#define PD_PDO_SRC_FIXED_PEAK_CURRENT_SHIFT 20 +#define PD_PDO_SRC_FIXED_PEAK_CURRENT (0x3 << PD_PDO_SRC_FIXED_PEAK_CURRENT_SHIFT) +#define PD_PDO_SRC_FIXED_VOLTAGE_SHIFT 10 +#define PD_PDO_SRC_FIXED_VOLTAGE (0x3FF << PD_PDO_SRC_FIXED_VOLTAGE_SHIFT) +#define PD_PDO_SRC_FIXED_CURRENT_SHIFT 0 +#define PD_PDO_SRC_FIXED_CURRENT (0x3FF << PD_PDO_SRC_FIXED_CURRENT_SHIFT) + +/* PD Source Fixed PDO current */ +#define PD_PDO_SRC_FIXED_CURRENT_GET(pdo) (((pdo) & PD_PDO_SRC_FIXED_CURRENT) >> PD_PDO_SRC_FIXED_CURRENT_SHIFT) + +/* PD Source Fixed PDO voltage */ +#define PD_PDO_SRC_FIXED_VOLTAGE_GET(pdo) (((pdo) & PD_PDO_SRC_FIXED_VOLTAGE) >> PD_PDO_SRC_FIXED_VOLTAGE_SHIFT) + +/* PD Programmable Power Supply APDO */ +#define PD_APDO_PPS_MAX_VOLTAGE_SHIFT 17 +#define PD_APDO_PPS_MAX_VOLTAGE (0xFF << PD_APDO_PPS_MAX_VOLTAGE_SHIFT) +#define PD_APDO_PPS_MIN_VOLTAGE_SHIFT 8 +#define PD_APDO_PPS_MIN_VOLTAGE (0xFF << PD_APDO_PPS_MIN_VOLTAGE_SHIFT) +#define PD_APDO_PPS_CURRENT_SHIFT 0 +#define PD_APDO_PPS_CURRENT (0x7F << PD_APDO_PPS_CURRENT_SHIFT) + +/* PD Programmable Power Supply APDO voltages */ +#define PD_APDO_PPS_MAX_VOLTAGE_GET(pdo) (((pdo) & PD_APDO_PPS_MAX_VOLTAGE) >> PD_APDO_PPS_MAX_VOLTAGE_SHIFT) +#define PD_APDO_PPS_MIN_VOLTAGE_GET(pdo) (((pdo) & PD_APDO_PPS_MIN_VOLTAGE) >> PD_APDO_PPS_MIN_VOLTAGE_SHIFT) + +#define PD_APDO_PPS_MAX_VOLTAGE_SET(v) (((v) << PD_APDO_PPS_MAX_VOLTAGE_SHIFT) & PD_APDO_PPS_MAX_VOLTAGE) +#define PD_APDO_PPS_MIN_VOLTAGE_SET(v) (((v) << PD_APDO_PPS_MIN_VOLTAGE_SHIFT) & PD_APDO_PPS_MIN_VOLTAGE) + +/* PD Programmable Power Supply APDO current */ +#define PD_APDO_PPS_CURRENT_GET(pdo) ((uint8_t) (((pdo) & PD_APDO_PPS_CURRENT) >> PD_APDO_PPS_CURRENT_SHIFT)) + +#define PD_APDO_PPS_CURRENT_SET(i) (((i) << PD_APDO_PPS_CURRENT_SHIFT) & PD_APDO_PPS_CURRENT) + + +/* PD Sink Fixed PDO */ +#define PD_PDO_SNK_FIXED_DUAL_ROLE_PWR_SHIFT 29 +#define PD_PDO_SNK_FIXED_DUAL_ROLE_PWR (1 << PD_PDO_SNK_FIXED_DUAL_ROLE_PWR_SHIFT) +#define PD_PDO_SNK_FIXED_HIGHER_CAP_SHIFT 28 +#define PD_PDO_SNK_FIXED_HIGHER_CAP (1 << PD_PDO_SNK_FIXED_HIGHER_CAP_SHIFT) +#define PD_PDO_SNK_FIXED_UNCONSTRAINED_SHIFT 27 +#define PD_PDO_SNK_FIXED_UNCONSTRAINED (1 << PD_PDO_SNK_FIXED_UNCONSTRAINED_SHIFT) +#define PD_PDO_SNK_FIXED_USB_COMMS_SHIFT 26 +#define PD_PDO_SNK_FIXED_USB_COMMS (1 << PD_PDO_SNK_FIXED_USB_COMMS_SHIFT) +#define PD_PDO_SNK_FIXED_DUAL_ROLE_DATA_SHIFT 25 +#define PD_PDO_SNK_FIXED_DUAL_ROLE_DATA (1 << PD_PDO_SNK_FIXED_DUAL_ROLE_DATA_SHIFT) +#define PD_PDO_SNK_FIXED_VOLTAGE_SHIFT 10 +#define PD_PDO_SNK_FIXED_VOLTAGE (0x3FF << PD_PDO_SNK_FIXED_VOLTAGE_SHIFT) +#define PD_PDO_SNK_FIXED_CURRENT_SHIFT 0 +#define PD_PDO_SNK_FIXED_CURRENT (0x3FF << PD_PDO_SNK_FIXED_CURRENT_SHIFT) + +/* PD Sink Fixed PDO current */ +#define PD_PDO_SNK_FIXED_CURRENT_SET(i) (((i) << PD_PDO_SNK_FIXED_CURRENT_SHIFT) & PD_PDO_SNK_FIXED_CURRENT) + +/* PD Sink Fixed PDO voltage */ +#define PD_PDO_SNK_FIXED_VOLTAGE_SET(v) (((v) << PD_PDO_SNK_FIXED_VOLTAGE_SHIFT) & PD_PDO_SNK_FIXED_VOLTAGE) + + +/* + * PD Request Data Object + */ +#define PD_RDO_OBJPOS_SHIFT 28 +#define PD_RDO_OBJPOS (0x7 << PD_RDO_OBJPOS_SHIFT) +#define PD_RDO_GIVEBACK_SHIFT 27 +#define PD_RDO_GIVEBACK (1 << PD_RDO_GIVEBACK_SHIFT) +#define PD_RDO_CAP_MISMATCH_SHIFT 26 +#define PD_RDO_CAP_MISMATCH (1 << PD_RDO_CAP_MISMATCH_SHIFT) +#define PD_RDO_USB_COMMS_SHIFT 25 +#define PD_RDO_USB_COMMS (1 << PD_RDO_USB_COMMS_SHIFT) +#define PD_RDO_NO_USB_SUSPEND_SHIFT 24 +#define PD_RDO_NO_USB_SUSPEND (1 << PD_RDO_NO_USB_SUSPEND_SHIFT) +#define PD_RDO_UNCHUNKED_EXT_MSG_SHIFT 23 +#define PD_RDO_UNCHUNKED_EXT_MSG (1 << PD_RDO_UNCHUNKED_EXT_MSG_SHIFT) + +#define PD_RDO_OBJPOS_SET(i) (((i) << PD_RDO_OBJPOS_SHIFT) & PD_RDO_OBJPOS) +#define PD_RDO_OBJPOS_GET(msg) (((msg)->obj[0] & PD_RDO_OBJPOS) >> PD_RDO_OBJPOS_SHIFT) + +/* Fixed and Variable RDO, no GiveBack support */ +#define PD_RDO_FV_CURRENT_SHIFT 10 +#define PD_RDO_FV_CURRENT (0x3FF << PD_RDO_FV_CURRENT_SHIFT) +#define PD_RDO_FV_MAX_CURRENT_SHIFT 0 +#define PD_RDO_FV_MAX_CURRENT (0x3FF << PD_RDO_FV_MAX_CURRENT_SHIFT) + +#define PD_RDO_FV_CURRENT_SET(i) (((i) << PD_RDO_FV_CURRENT_SHIFT) & PD_RDO_FV_CURRENT) +#define PD_RDO_FV_MAX_CURRENT_SET(i) (((i) << PD_RDO_FV_MAX_CURRENT_SHIFT) & PD_RDO_FV_MAX_CURRENT) + +/* Fixed and Variable RDO with GiveBack support */ +#define PD_RDO_FV_MIN_CURRENT_SHIFT 0 +#define PD_RDO_FV_MIN_CURRENT (0x3FF << PD_RDO_FV_MIN_CURRENT_SHIFT) + +#define PD_RDO_FV_MIN_CURRENT_SET(i) (((i) << PD_RDO_FV_MIN_CURRENT_SHIFT) & PD_RDO_FV_MIN_CURRENT) + +/* TODO: Battery RDOs */ + +/* Programmable RDO */ +#define PD_RDO_PROG_VOLTAGE_SHIFT 9 +#define PD_RDO_PROG_VOLTAGE (0x7FF << PD_RDO_PROG_VOLTAGE_SHIFT) +#define PD_RDO_PROG_CURRENT_SHIFT 0 +#define PD_RDO_PROG_CURRENT (0x7F << PD_RDO_PROG_CURRENT_SHIFT) + +#define PD_RDO_PROG_VOLTAGE_SET(i) (((i) << PD_RDO_PROG_VOLTAGE_SHIFT) & PD_RDO_PROG_VOLTAGE) +#define PD_RDO_PROG_CURRENT_SET(i) (((i) << PD_RDO_PROG_CURRENT_SHIFT) & PD_RDO_PROG_CURRENT) + +/* + * Time values + * + * Where a range is specified, the middle of the range (rounded down to the + * nearest millisecond) is used. + */ +#define PD_T_CHUNKING_NOT_SUPPORTED (45) +#define PD_T_HARD_RESET_COMPLETE (4) +#define PD_T_PS_TRANSITION (500) +#define PD_T_SENDER_RESPONSE (27) +#define PD_T_SINK_REQUEST (100) +#define PD_T_TYPEC_SINK_WAIT_CAP (465) +#define PD_T_PPS_REQUEST TIME_S2I(10) +/* This is actually from Type-C, not Power Delivery, but who cares? */ +#define PD_T_PD_DEBOUNCE (15) + +/* + * Counter maximums + */ +#define PD_N_HARD_RESET_COUNT 2 + +/* + * Value parameters + */ +#define PD_MAX_EXT_MSG_LEN 260 +#define PD_MAX_EXT_MSG_CHUNK_LEN 26 +#define PD_MAX_EXT_MSG_LEGACY_LEN 26 + +/* + * Unit conversions + * + * V: volt + * CV: centivolt + * MV: millivolt + * PRV: Programmable RDO voltage unit (20 mV) + * PDV: Power Delivery voltage unit (50 mV) + * PAV: PPS APDO voltage unit (100 mV) + * + * A: ampere + * CA: centiampere + * MA: milliampere + * PDI: Power Delivery current unit (10 mA) + * PAI: PPS APDO current unit (50 mA) + * + * W: watt + * CW: centiwatt + * MW: milliwatt + * + * O: ohm + * CO: centiohm + * MO: milliohm + */ +#define PD_MV2PRV(mv) ((mv) / 20) +#define PD_MV2PDV(mv) ((mv) / 50) +#define PD_MV2PAV(mv) ((mv) / 100) +#define PD_PRV2MV(prv) ((prv) * 20) +#define PD_PDV2MV(pdv) ((pdv) * 50) +#define PD_PAV2MV(pav) ((pav) * 100) + +#define PD_MA2CA(ma) (((ma) + 10 - 1) / 10) +#define PD_MA2PDI(ma) (((ma) + 10 - 1) / 10) +#define PD_MA2PAI(ma) (((ma) + 50 - 1) / 50) +#define PD_CA2PAI(ca) (((ca) + 5 - 1) / 5) +#define PD_PDI2MA(pdi) ((pdi) * 10) +#define PD_PAI2MA(pai) ((pai) * 50) +#define PD_PAI2CA(pai) ((pai) * 5) + +#define PD_MW2CW(mw) ((mw) / 10) + +#define PD_MO2CO(mo) ((mo) / 10) + +/* Get portions of a voltage in more normal units */ +#define PD_MV_V(mv) ((mv) / 1000) +#define PD_MV_MV(mv) ((mv) % 1000) + +#define PD_PDV_V(pdv) ((pdv) / 20) +#define PD_PDV_CV(pdv) (5 * ((pdv) % 20)) + +#define PD_PAV_V(pav) ((pav) / 10) +#define PD_PAV_CV(pav) (10 * ((pav) % 10)) + +/* Get portions of a PD current in more normal units */ +#define PD_PDI_A(pdi) ((pdi) / 100) +#define PD_PDI_CA(pdi) ((pdi) % 100) + +#define PD_PAI_A(pai) ((pai) / 20) +#define PD_PAI_CA(pai) (5 * ((pai) % 20)) + +/* Get portions of a power in more normal units */ +#define PD_CW_W(cw) ((cw) / 100) +#define PD_CW_CW(cw) ((cw) % 100) + +/* Get portions of a resistance in more normal units */ +#define PD_CO_O(co) ((co) / 100) +#define PD_CO_CO(co) ((co) % 100) + +/* + * Unit constants + */ +#define PD_MV_MIN 0 +#define PD_MV_MAX 21000 +#define PD_PDV_MIN PD_MV2PDV(PD_MV_MIN) +#define PD_PDV_MAX PD_MV2PDV(PD_MV_MAX) + +#define PD_MA_MIN 0 +#define PD_MA_MAX 5000 +#define PD_CA_MIN PD_MA2CA(PD_MA_MIN) +#define PD_CA_MAX PD_MA2CA(PD_MA_MAX) +#define PD_PDI_MIN PD_MA2PDI(PD_MA_MIN) +#define PD_PDI_MAX PD_MA2PDI(PD_MA_MAX) + +#define PD_MW_MIN 0 +#define PD_MW_MAX 100000 + +#define PD_MO_MIN 500 +#define PD_MO_MAX 655350 + + +/* + * FUSB Type-C Current level enum + */ +enum fusb_typec_current { + fusb_tcc_none = 0, + fusb_tcc_default = 1, + fusb_tcc_1_5 = 2, + fusb_sink_tx_ng = 2, + fusb_tcc_3_0 = 3, + fusb_sink_tx_ok = 3 +}; + + + +#endif /* PDB_PD_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/pdb_conf.h b/workspace/TS100/Core/Drivers/FUSB302/pdb_conf.h new file mode 100644 index 00000000..ef733c3d --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/pdb_conf.h @@ -0,0 +1,47 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PDB_CONF_H +#define PDB_CONF_H + + +/* Number of messages in the message pool */ +#define PDB_MSG_POOL_SIZE 4 + +/* Size of the Policy Engine thread's working area */ +#define PDB_PE_WA_SIZE 256 + +/* Size of the protocol layer RX thread's working area */ +#define PDB_PRLRX_WA_SIZE 256 + +/* Size of the protocol layer TX thread's working area */ +#define PDB_PRLTX_WA_SIZE 256 + +/* Size of the protocol layer hard reset thread's working area */ +#define PDB_HARDRST_WA_SIZE 256 + +/* Size of the INT_N thread's working area */ +#define PDB_INT_N_WA_SIZE 128 + +#define EVENT_MASK(x) (1< + + + +/* + * PD message union + * + * This can be safely read from or written to in any form without any + * transformations because everything in the system is little-endian. + * + * Two bytes of padding are required at the start to prevent problems due to + * alignment. Specifically, without the padding, &obj[0] != &bytes[2], making + * the statement in the previous paragraph invalid. + */ +union pd_msg { + struct { + uint8_t _pad1[2]; + uint8_t bytes[30]; + } __attribute__((packed)); + struct { + uint8_t _pad2[2]; + uint16_t hdr; + union { + uint32_t obj[7]; + struct { + uint16_t exthdr; + uint8_t data[26]; + }; + }; + } __attribute__((packed)); +}; + + + +#endif /* PDB_MSG_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp new file mode 100644 index 00000000..fa076ba7 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -0,0 +1,799 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "policy_engine.h" +#include + +#include +#include "protocol_tx.h" +#include "hard_reset.h" +#include "fusb302b.h" +bool PolicyEngine::pdNegotiationComplete; +bool PolicyEngine::pdHasEnteredLowPower; +int PolicyEngine::current_voltage_mv; +int PolicyEngine::_requested_voltage; +bool PolicyEngine::_unconstrained_power; +union pd_msg PolicyEngine::currentMessage; +uint16_t PolicyEngine::hdr_template; +bool PolicyEngine::_explicit_contract; +bool PolicyEngine::_min_power; +int8_t PolicyEngine::_hard_reset_counter; +int8_t PolicyEngine::_old_tcc_match; +uint8_t PolicyEngine::_pps_index; +uint8_t PolicyEngine::_last_pps; +osThreadId PolicyEngine::TaskHandle; +uint32_t PolicyEngine::TaskBuffer[PolicyEngine::TaskStackSize]; +osStaticThreadDef_t PolicyEngine::TaskControlBlock; +union pd_msg PolicyEngine::tempMessage; +union pd_msg PolicyEngine::_last_dpm_request; +StaticQueue_t PolicyEngine::xStaticQueue; +uint8_t PolicyEngine::ucQueueStorageArea[PDB_MSG_POOL_SIZE + * sizeof(union pd_msg)]; +QueueHandle_t PolicyEngine::messagesWaiting; +void PolicyEngine::init() { + messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, + sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue); + //Create static thread at PDB_PRIO_PE priority + osThreadStaticDef(Task, pe_task, PDB_PRIO_PE, 0, TaskStackSize, TaskBuffer, + &TaskControlBlock); + TaskHandle = osThreadCreate(osThread(Task), NULL); +} + +void PolicyEngine::notify(uint32_t notification) { + xTaskNotify(TaskHandle, notification, + eNotifyAction::eSetValueWithOverwrite); +} + +void PolicyEngine::pe_task(const void *arg) { + (void) arg; +//Internal thread loop + hdr_template = PD_DATAROLE_UFP | PD_POWERROLE_SINK; + /* Initialize the old_tcc_match */ + _old_tcc_match = -1; + /* Initialize the pps_index */ + _pps_index = 8; + /* Initialize the last_pps */ + _last_pps = 8; + PolicyEngine::policy_engine_state state = PESinkStartup; + for (;;) { + //Loop based on state + switch (state) { + case PESinkStartup: + state = pe_sink_startup(); + break; + case PESinkDiscovery: + state = pe_sink_discovery(); + break; + case PESinkWaitCap: + state = pe_sink_wait_cap(); + break; + case PESinkEvalCap: + state = pe_sink_eval_cap(); + break; + case PESinkSelectCap: + state = pe_sink_select_cap(); + break; + case PESinkTransitionSink: + state = pe_sink_transition_sink(); + break; + case PESinkReady: + state = pe_sink_ready(); + break; + case PESinkGetSourceCap: + state = pe_sink_get_source_cap(); + break; + case PESinkGiveSinkCap: + state = pe_sink_give_sink_cap(); + break; + case PESinkHardReset: + state = pe_sink_hard_reset(); + break; + case PESinkTransitionDefault: + state = pe_sink_transition_default(); + break; + case PESinkSoftReset: + state = pe_sink_soft_reset(); + break; + case PESinkSendSoftReset: + state = pe_sink_send_soft_reset(); + break; + case PESinkSendNotSupported: + state = pe_sink_send_not_supported(); + break; + case PESinkChunkReceived: + state = pe_sink_chunk_received(); + break; + case PESinkSourceUnresponsive: + state = pe_sink_source_unresponsive(); + break; + case PESinkNotSupportedReceived: + state = pe_sink_not_supported_received(); + break; + default: + state = PESinkStartup; + break; + } + } +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_startup() { + /* We don't have an explicit contract currently */ + _explicit_contract = false; + +//If desired could send an alert that PD is starting + + /* No need to reset the protocol layer here. There are two ways into this + * state: startup and exiting hard reset. On startup, the protocol layer + * is reset by the startup procedure. When exiting hard reset, the + * protocol layer is reset by the hard reset state machine. Since it's + * already done somewhere else, there's no need to do it again here. */ + + return PESinkDiscovery; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_discovery() { + /* Wait for VBUS. Since it's our only power source, we already know that + * we have it, so just move on. */ + + return PESinkWaitCap; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_wait_cap() { + /* Fetch a message from the protocol layer */ + eventmask_t evt = waitForEvent( + PDB_EVT_PE_MSG_RX | PDB_EVT_PE_I_OVRTEMP | PDB_EVT_PE_RESET, + PD_T_TYPEC_SINK_WAIT_CAP); + /* If we timed out waiting for Source_Capabilities, send a hard reset */ + if (evt == 0) { + return PESinkHardReset; + } + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + /* If we're too hot, we shouldn't negotiate power yet */ + if (evt & PDB_EVT_PE_I_OVRTEMP) { + return PESinkWaitCap; + } + + /* If we got a message */ + if (evt & PDB_EVT_PE_MSG_RX) { + /* Get the message */ + readMessage(); + /* If we got a Source_Capabilities message, read it. */ + if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOURCE_CAPABILITIES + && PD_NUMOBJ_GET(&tempMessage) > 0) { + /* First, determine what PD revision we're using */ + if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_1_0) { + /* If the other end is using at least version 3.0, we'll + * use version 3.0. */ + if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { + hdr_template |= PD_SPECREV_3_0; + /* Otherwise, use 2.0. Don't worry about the 1.0 case + * because we don't have hardware for PD 1.0 signaling. */ + } else { + hdr_template |= PD_SPECREV_2_0; + } + } + return PESinkEvalCap; + /* If the message was a Soft_Reset, do the soft reset procedure */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET + && PD_NUMOBJ_GET(&tempMessage) == 0) { + + return PESinkSoftReset; + /* If we got an unexpected message, reset */ + } else { + /* Free the received message */ + return PESinkHardReset; + + } + } + + /* If we failed to get a message, send a hard reset */ + return PESinkHardReset; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_eval_cap() { + /* If we have a Source_Capabilities message, remember the index of the + * first PPS APDO so we can check if the request is for a PPS APDO in + * PE_SNK_Select_Cap. */ + /* Start by assuming we won't find a PPS APDO (set the index greater + * than the maximum possible) */ + _pps_index = 8; + /* Search for the first PPS APDO */ + for (int8_t i = 0; i < PD_NUMOBJ_GET(&tempMessage); i++) { + if ((tempMessage.obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED + && (tempMessage.obj[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS) { + _pps_index = i + 1; + break; + } + } + /* New capabilities also means we can't be making a request from the + * same PPS APDO */ + _last_pps = 8; + /* Get a message object for the request if we don't have one already */ + + /* Remember the last PDO we requested if it was a PPS APDO */ + if (PD_RDO_OBJPOS_GET(&_last_dpm_request) >= _pps_index) { + _last_pps = PD_RDO_OBJPOS_GET(&_last_dpm_request); + /* Otherwise, forget any PPS APDO we had requested */ + } else { + _last_pps = 8; + } + + /* Ask the DPM what to request */ + pdbs_dpm_evaluate_capability(&tempMessage, &_last_dpm_request); + + return PESinkSelectCap; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { + /* Transmit the request */ + ProtocolTransmit::pushMessage(&_last_dpm_request); +//Send indication that there is a message pending + ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + eventmask_t evt = waitForEvent( + PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); + /* Don't free the request; we might need it again */ + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + /* If the message transmission failed, send a hard reset */ + if ((evt & PDB_EVT_PE_TX_DONE) == 0) { + return PESinkHardReset; + } + + /* If we're using PD 3.0 */ + if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_3_0) { + /* If the request was for a PPS APDO, start SinkPPSPeriodicTimer */ + if (PD_RDO_OBJPOS_GET(&_last_dpm_request) >= _pps_index) { + start_pps_timer(); + /* Otherwise, stop SinkPPSPeriodicTimer */ + } else { + stop_pps_timer(); + } + } + /* This will use a virtual timer to send an event flag to this thread after + * PD_T_PPS_REQUEST */ + + /* Wait for a response */ + evt = waitForEvent(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET, + PD_T_SENDER_RESPONSE); + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + /* If we didn't get a response before the timeout, send a hard reset */ + if (evt == 0) { + return PESinkHardReset; + } + + /* Get the response message */ + if (messageWaiting()) { + readMessage(); + /* If the source accepted our request, wait for the new power */ + if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_ACCEPT + && PD_NUMOBJ_GET(&tempMessage) == 0) { + /* Transition to Sink Standby if necessary */ + if (PD_RDO_OBJPOS_GET(&_last_dpm_request) != _last_pps) { + pdbs_dpm_transition_standby(); + } + + _min_power = false; + return PESinkTransitionSink; + /* If the message was a Soft_Reset, do the soft reset procedure */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET + && PD_NUMOBJ_GET(&tempMessage) == 0) { + return PESinkSoftReset; + /* If the message was Wait or Reject */ + } else if ((PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_REJECT + || PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_WAIT) + && PD_NUMOBJ_GET(&tempMessage) == 0) { + /* If we don't have an explicit contract, wait for capabilities */ + if (!_explicit_contract) { + return PESinkWaitCap; + /* If we do have an explicit contract, go to the ready state */ + } else { + /* If we got here from a Wait message, we Should run + * SinkRequestTimer in the Ready state. */ + _min_power = (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_WAIT); + + return PESinkReady; + } + } else { + return PESinkSendSoftReset; + } + } + return PESinkHardReset; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_transition_sink() { + /* Wait for the PS_RDY message */ + eventmask_t evt = waitForEvent(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET, + PD_T_PS_TRANSITION); + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + /* If no message was received, send a hard reset */ + if (evt == 0) { + return PESinkHardReset; + } + + /* If we received a message, read it */ + if (messageWaiting()) { + readMessage(); + /* If we got a PS_RDY, handle it */ + if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_PS_RDY + && PD_NUMOBJ_GET(&tempMessage) == 0) { + /* We just finished negotiating an explicit contract */ + _explicit_contract = true; + + /* Set the output appropriately */ + if (!_min_power) { + pdbs_dpm_transition_requested(); + } + + return PESinkReady; + /* If there was a protocol error, send a hard reset */ + } else { + /* Turn off the power output before this hard reset to make sure we + * don't supply an incorrect voltage to the device we're powering. + */ + pdbs_dpm_transition_default(); + + return PESinkHardReset; + } + } + + return PESinkHardReset; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_ready() { + eventmask_t evt; + + /* Wait for an event */ + if (_min_power) { + evt = waitForEvent( + PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET | PDB_EVT_PE_I_OVRTEMP + | PDB_EVT_PE_GET_SOURCE_CAP | PDB_EVT_PE_NEW_POWER + | PDB_EVT_PE_PPS_REQUEST, + PD_T_SINK_REQUEST); + } else { + evt = waitForEvent( + PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET | PDB_EVT_PE_I_OVRTEMP + | PDB_EVT_PE_GET_SOURCE_CAP | PDB_EVT_PE_NEW_POWER + | PDB_EVT_PE_PPS_REQUEST); + } + + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + + /* If we overheated, send a hard reset */ + if (evt & PDB_EVT_PE_I_OVRTEMP) { + return PESinkHardReset; + } + + /* If the DPM wants us to, send a Get_Source_Cap message */ + if (evt & PDB_EVT_PE_GET_SOURCE_CAP) { + /* Tell the protocol layer we're starting an AMS */ + ProtocolTransmit::notify( PDB_EVT_PRLTX_START_AMS); + return PESinkGetSourceCap; + } + + /* If the DPM wants new power, let it figure out what power it wants + * exactly. This isn't exactly the transition from the spec (that would be + * SelectCap, not EvalCap), but this works better with the particular + * design of this firmware. */ + if (evt & PDB_EVT_PE_NEW_POWER) { + /* Tell the protocol layer we're starting an AMS */ + ProtocolTransmit::notify( PDB_EVT_PRLTX_START_AMS); + return PESinkEvalCap; + } + + /* If SinkPPSPeriodicTimer ran out, send a new request */ + if (evt & PDB_EVT_PE_PPS_REQUEST) { + /* Tell the protocol layer we're starting an AMS */ + ProtocolTransmit::notify( PDB_EVT_PRLTX_START_AMS); + return PESinkSelectCap; + } + + /* If no event was received, the timer ran out. */ + if (evt == 0) { + /* Repeat our Request message */ + return PESinkSelectCap; + } + + /* If we received a message */ + if (evt & PDB_EVT_PE_MSG_RX) { + if (messageWaiting()) { + readMessage(); + /* Ignore vendor-defined messages */ + if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_VENDOR_DEFINED + && PD_NUMOBJ_GET(&tempMessage) > 0) { + + return PESinkReady; + /* Ignore Ping messages */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_PING + && PD_NUMOBJ_GET(&tempMessage) == 0) { + + return PESinkReady; + /* DR_Swap messages are not supported */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_DR_SWAP + && PD_NUMOBJ_GET(&tempMessage) == 0) { + + return PESinkSendNotSupported; + /* Get_Source_Cap messages are not supported */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_GET_SOURCE_CAP + && PD_NUMOBJ_GET(&tempMessage) == 0) { + + return PESinkSendNotSupported; + /* PR_Swap messages are not supported */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_PR_SWAP + && PD_NUMOBJ_GET(&tempMessage) == 0) { + + return PESinkSendNotSupported; + /* VCONN_Swap messages are not supported */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_VCONN_SWAP + && PD_NUMOBJ_GET(&tempMessage) == 0) { + + return PESinkSendNotSupported; + /* Request messages are not supported */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_REQUEST + && PD_NUMOBJ_GET(&tempMessage) > 0) { + + return PESinkSendNotSupported; + /* Sink_Capabilities messages are not supported */ + } else if (PD_MSGTYPE_GET(&tempMessage) + == PD_MSGTYPE_SINK_CAPABILITIES + && PD_NUMOBJ_GET(&tempMessage) > 0) { + + return PESinkSendNotSupported; + /* Handle GotoMin messages */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_GOTOMIN + && PD_NUMOBJ_GET(&tempMessage) == 0) { + if (pdbs_dpm_giveback_enabled()) { + /* Transition to the minimum current level */ + pdbs_dpm_transition_min(); + _min_power = true; + return PESinkTransitionSink; + } else { + /* GiveBack is not supported */ + + return PESinkSendNotSupported; + } + /* Evaluate new Source_Capabilities */ + } else if (PD_MSGTYPE_GET(&tempMessage) + == PD_MSGTYPE_SOURCE_CAPABILITIES + && PD_NUMOBJ_GET(&tempMessage) > 0) { + /* Don't free the message: we need to keep the + * Source_Capabilities message so we can evaluate it. */ + return PESinkEvalCap; + /* Give sink capabilities when asked */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_GET_SINK_CAP + && PD_NUMOBJ_GET(&tempMessage) == 0) { + + return PESinkGiveSinkCap; + /* If the message was a Soft_Reset, do the soft reset procedure */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET + && PD_NUMOBJ_GET(&tempMessage) == 0) { + + return PESinkSoftReset; + /* PD 3.0 messges */ + } else if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_3_0) { + /* If the message is a multi-chunk extended message, let it + * time out. */ + if ((tempMessage.hdr & PD_HDR_EXT) + && (PD_DATA_SIZE_GET(&tempMessage) + > PD_MAX_EXT_MSG_LEGACY_LEN)) { + + return PESinkChunkReceived; + /* Tell the DPM a message we sent got a response of + * Not_Supported. */ + } else if (PD_MSGTYPE_GET(&tempMessage) + == PD_MSGTYPE_NOT_SUPPORTED + && PD_NUMOBJ_GET(&tempMessage) == 0) { + + return PESinkNotSupportedReceived; + /* If we got an unknown message, send a soft reset */ + } else { + + return PESinkSendSoftReset; + } + /* If we got an unknown message, send a soft reset ??? */ + } else { + + return PESinkSendSoftReset; + } + } + } + + return PESinkReady; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_get_source_cap() { + /* Get a message object */ + union pd_msg *get_source_cap = &tempMessage; + /* Make a Get_Source_Cap message */ + get_source_cap->hdr = hdr_template | PD_MSGTYPE_GET_SOURCE_CAP + | PD_NUMOBJ(0); + /* Transmit the Get_Source_Cap */ + ProtocolTransmit::pushMessage(get_source_cap); + ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + eventmask_t evt = waitForEvent( + PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); + /* Free the sent message */ + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + /* If the message transmission failed, send a hard reset */ + if ((evt & PDB_EVT_PE_TX_DONE) == 0) { + return PESinkHardReset; + } + + return PESinkReady; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_give_sink_cap() { + /* Get a message object */ + union pd_msg *snk_cap = &tempMessage; + /* Get our capabilities from the DPM */ + pdbs_dpm_get_sink_capability(snk_cap); + + /* Transmit our capabilities */ + ProtocolTransmit::pushMessage(snk_cap); + ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + eventmask_t evt = waitForEvent( + PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); + + /* Free the Sink_Capabilities message */ + + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + /* If the message transmission failed, send a hard reset */ + if ((evt & PDB_EVT_PE_TX_DONE) == 0) { + return PESinkHardReset; + } + + return PESinkReady; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_hard_reset() { + /* If we've already sent the maximum number of hard resets, assume the + * source is unresponsive. */ + if (_hard_reset_counter > PD_N_HARD_RESET_COUNT) { + return PESinkSourceUnresponsive; + } + + /* Generate a hard reset signal */ + ResetHandler::notify(PDB_EVT_HARDRST_RESET); + waitForEvent(PDB_EVT_PE_HARD_SENT); + + /* Increment HardResetCounter */ + _hard_reset_counter++; + + return PESinkTransitionDefault; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_transition_default() { + _explicit_contract = false; + + /* Tell the DPM to transition to default power */ + pdbs_dpm_transition_default(); + + /* There is no local hardware to reset. */ + /* Since we never change our data role from UFP, there is no reason to set + * it here. */ + + /* Tell the protocol layer we're done with the reset */ + ResetHandler::notify( PDB_EVT_HARDRST_DONE); + + return PESinkStartup; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_soft_reset() { + /* No need to explicitly reset the protocol layer here. It resets itself + * when a Soft_Reset message is received. */ + + /* Get a message object */ + union pd_msg accept; + /* Make an Accept message */ + accept.hdr = hdr_template | PD_MSGTYPE_ACCEPT | PD_NUMOBJ(0); + /* Transmit the Accept */ + ProtocolTransmit::pushMessage(&accept); + ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + eventmask_t evt = waitForEvent( + PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); + /* Free the sent message */ + + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + /* If the message transmission failed, send a hard reset */ + if ((evt & PDB_EVT_PE_TX_DONE) == 0) { + return PESinkHardReset; + } + + return PESinkWaitCap; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_send_soft_reset() { + /* No need to explicitly reset the protocol layer here. It resets itself + * just before a Soft_Reset message is transmitted. */ + + /* Get a message object */ + union pd_msg *softrst = &tempMessage; + /* Make a Soft_Reset message */ + softrst->hdr = hdr_template | PD_MSGTYPE_SOFT_RESET | PD_NUMOBJ(0); + /* Transmit the soft reset */ + ProtocolTransmit::pushMessage(softrst); + ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + eventmask_t evt = waitForEvent( + PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + /* If the message transmission failed, send a hard reset */ + if ((evt & PDB_EVT_PE_TX_DONE) == 0) { + return PESinkHardReset; + } + + /* Wait for a response */ + evt = waitForEvent(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET, + PD_T_SENDER_RESPONSE); + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + /* If we didn't get a response before the timeout, send a hard reset */ + if (evt == 0) { + return PESinkHardReset; + } + + /* Get the response message */ + if (messageWaiting()) { + readMessage(); + /* If the source accepted our soft reset, wait for capabilities. */ + if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_ACCEPT + && PD_NUMOBJ_GET(&tempMessage) == 0) { + + return PESinkWaitCap; + /* If the message was a Soft_Reset, do the soft reset procedure */ + } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET + && PD_NUMOBJ_GET(&tempMessage) == 0) { + + return PESinkSoftReset; + /* Otherwise, send a hard reset */ + } else { + + return PESinkHardReset; + } + } + return PESinkHardReset; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_send_not_supported() { + /* Get a message object */ + union pd_msg *not_supported = &tempMessage; + + if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_2_0) { + /* Make a Reject message */ + not_supported->hdr = hdr_template | PD_MSGTYPE_REJECT | PD_NUMOBJ(0); + } else if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_3_0) { + /* Make a Not_Supported message */ + not_supported->hdr = hdr_template | PD_MSGTYPE_NOT_SUPPORTED + | PD_NUMOBJ(0); + } + + /* Transmit the message */ + ProtocolTransmit::pushMessage(not_supported); + ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + eventmask_t evt = waitForEvent( + PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); + + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + /* If the message transmission failed, send a soft reset */ + if ((evt & PDB_EVT_PE_TX_DONE) == 0) { + return PESinkSendSoftReset; + } + + return PESinkReady; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_chunk_received() { + + /* Wait for tChunkingNotSupported */ + eventmask_t evt = waitForEvent(PDB_EVT_PE_RESET, + PD_T_CHUNKING_NOT_SUPPORTED); + /* If we got reset signaling, transition to default */ + if (evt & PDB_EVT_PE_RESET) { + return PESinkTransitionDefault; + } + + return PESinkSendNotSupported; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_not_supported_received() { + /* Inform the Device Policy Manager that we received a Not_Supported + * message. */ + + return PESinkReady; +} + +PolicyEngine::policy_engine_state PolicyEngine::pe_sink_source_unresponsive() { + /* If the DPM can evaluate the Type-C Current advertisement */ + //TS80P doesnt +// if (cfg->dpm.evaluate_typec_current != NULL) { +// /* Make the DPM evaluate the Type-C Current advertisement */ +// int tcc_match = cfg->dpm.evaluate_typec_current(cfg, +// fusb_get_typec_current(&cfg->fusb)); +// +// /* If the last two readings are the same, set the output */ +// if (_old_tcc_match == tcc_match) { +// cfg->dpm.transition_typec(cfg); +// } +// +// /* Remember whether or not the last measurement succeeded */ +// _old_tcc_match = tcc_match; +// } + /* Wait tPDDebounce between measurements */ + osDelay(PD_T_PD_DEBOUNCE); + + return PESinkSourceUnresponsive; +} + +void PolicyEngine::PPSTimerCallBack() { + notify(PDB_EVT_PE_PPS_REQUEST); +} + +bool PolicyEngine::pdHasNegotiated() { + return pdNegotiationComplete; +} + +bool PolicyEngine::heatingAllowed() { + if (pdHasNegotiated()) + return !pdHasEnteredLowPower; + //Not pd -- pass through + return true; +} + +uint32_t PolicyEngine::waitForEvent(uint32_t mask, uint32_t ticksToWait) { + uint32_t pulNotificationValue; + xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait); + return pulNotificationValue; +} + +bool PolicyEngine::isPD3_0() { + return (hdr_template & PD_HDR_SPECREV) == PD_SPECREV_3_0; +} + +void PolicyEngine::start_pps_timer() { +} + +void PolicyEngine::stop_pps_timer() { +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h new file mode 100644 index 00000000..781158ed --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h @@ -0,0 +1,197 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PDB_POLICY_ENGINE_H +#define PDB_POLICY_ENGINE_H + +#include + +/* + * Events for the Policy Engine thread, used internally + sent by user code + * + */ +/* Tell the PE to send a Get_Source_Cap message */ +#define PDB_EVT_PE_GET_SOURCE_CAP EVENT_MASK(7) +/* Tell the PE that new power is required */ +#define PDB_EVT_PE_NEW_POWER EVENT_MASK(8) + +#define PDB_EVT_PE_RESET EVENT_MASK(0) +#define PDB_EVT_PE_MSG_RX EVENT_MASK(1) +#define PDB_EVT_PE_TX_DONE EVENT_MASK(2) +#define PDB_EVT_PE_TX_ERR EVENT_MASK(3) +#define PDB_EVT_PE_HARD_SENT EVENT_MASK(4) +#define PDB_EVT_PE_I_OVRTEMP EVENT_MASK(5) +#define PDB_EVT_PE_PPS_REQUEST EVENT_MASK(6) + +class PolicyEngine { +public: + //Sets up internal state and registers the thread + static void init(); + //Push an incoming message to the Policy Engine + static void handleMessage(union pd_msg *msg); + //Send a notification + static void notify(uint32_t notification); + //Returns true if headers indicate PD3.0 compliant + static bool isPD3_0(); + + static void PPSTimerCallBack(); + //Has pd negotiation completed + static bool pdHasNegotiated(); + //Used in case the USB-C PD source requests minimum power + static bool heatingAllowed(); +private: + static bool pdNegotiationComplete; + static bool pdHasEnteredLowPower; + static int current_voltage_mv; //The current voltage PD is expecting + static int _requested_voltage; //The voltage the unit wanted to requests + static bool _unconstrained_power; // If the source is unconstrained + //Current message being handled + static union pd_msg currentMessage; + /* PD message header template */ + static uint16_t hdr_template; + /* Whether or not we have an explicit contract */ + static bool _explicit_contract; + /* Whether or not we're receiving minimum power */ + static bool _min_power; + /* The number of hard resets we've sent */ + static int8_t _hard_reset_counter; + /* The result of the last Type-C Current match comparison */ + static int8_t _old_tcc_match; + /* The index of the first PPS APDO */ + static uint8_t _pps_index; + /* The index of the just-requested PPS APDO */ + static uint8_t _last_pps; + static void pe_task(const void *arg); + enum policy_engine_state { + PESinkStartup, + PESinkDiscovery, + PESinkWaitCap, + PESinkEvalCap, + PESinkSelectCap, + PESinkTransitionSink, + PESinkReady, + PESinkGetSourceCap, + PESinkGiveSinkCap, + PESinkHardReset, + PESinkTransitionDefault, + PESinkSoftReset, + PESinkSendSoftReset, + PESinkSendNotSupported, + PESinkChunkReceived, + PESinkNotSupportedReceived, + PESinkSourceUnresponsive + }; + static enum policy_engine_state pe_sink_startup(); + static enum policy_engine_state pe_sink_discovery(); + static enum policy_engine_state pe_sink_wait_cap(); + static enum policy_engine_state pe_sink_eval_cap(); + static enum policy_engine_state pe_sink_select_cap(); + static enum policy_engine_state pe_sink_transition_sink(); + static enum policy_engine_state pe_sink_ready(); + static enum policy_engine_state pe_sink_get_source_cap(); + static enum policy_engine_state pe_sink_give_sink_cap(); + static enum policy_engine_state pe_sink_hard_reset(); + static enum policy_engine_state pe_sink_transition_default(); + static enum policy_engine_state pe_sink_soft_reset(); + static enum policy_engine_state pe_sink_send_soft_reset(); + static enum policy_engine_state pe_sink_send_not_supported(); + static enum policy_engine_state pe_sink_chunk_received(); + static enum policy_engine_state pe_sink_not_supported_received(); + static enum policy_engine_state pe_sink_source_unresponsive(); + static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait = + portMAX_DELAY); + //Task resources + static osThreadId TaskHandle; + static const size_t TaskStackSize = 1024 / 4; + static uint32_t TaskBuffer[TaskStackSize]; + static osStaticThreadDef_t TaskControlBlock; + static union pd_msg tempMessage; + static union pd_msg _last_dpm_request; + //queue of up to PDB_MSG_POOL_SIZE messages to send + static StaticQueue_t xStaticQueue; + /* The array to use as the queue's storage area. This must be at least + uxQueueLength * uxItemSize bytes. */ + static uint8_t ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)]; + static QueueHandle_t messagesWaiting; + static bool messageWaiting(); +//Read a pending message into the temp message + static void readMessage(); + static void start_pps_timer(); + static void stop_pps_timer(); + + // These callbacks are called to implement the logic for the iron to select the desired voltage + + /* + * Create a Request message based on the given Source_Capabilities message. If + * capabilities is NULL, the last non-null Source_Capabilities message passes + * is used. If none has been provided, the behavior is undefined. + * + * Returns true if sufficient power is available, false otherwise. + */ + static bool pdbs_dpm_evaluate_capability(const union pd_msg *capabilities, + union pd_msg *request); + + /* + * Create a Sink_Capabilities message for our current capabilities. + */ + static void pdbs_dpm_get_sink_capability(union pd_msg *cap); + + /* + * Return whether or not GiveBack support is enabled. + */ + static bool pdbs_dpm_giveback_enabled(); + + /* + * Evaluate whether or not the currently offered Type-C Current can fulfill our + * power needs. + * + * Returns true if sufficient power is available, false otherwise. + */ + static bool pdbs_dpm_evaluate_typec_current(enum fusb_typec_current tcc); + + /* + * Indicate that power negotiations are starting. + */ + static void pdbs_dpm_pd_start(); + + /* + * Transition the sink to default power. + */ + static void pdbs_dpm_transition_default(); + + /* + * Transition to the requested minimum current. + */ + static void pdbs_dpm_transition_min(); + + /* + * Transition to Sink Standby if necessary. + */ + static void pdbs_dpm_transition_standby(); + + /* + * Transition to the requested power level + */ + static void pdbs_dpm_transition_requested(); + + /* + * Transition to the Type-C Current power level + */ + static void pdbs_dpm_transition_typec(); +}; + +#endif /* PDB_POLICY_ENGINE_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp new file mode 100644 index 00000000..72364ae3 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp @@ -0,0 +1,305 @@ +/* + * policy_engine_user.cpp + * + * Created on: 14 Jun 2020 + * Author: Ralim + */ +#include "pd.h" +#include "policy_engine.h" + +/* The current draw when the output is disabled */ +#define DPM_MIN_CURRENT PD_MA2PDI(50) +/* + * Find the index of the first PDO from capabilities in the voltage range, + * using the desired order. + * + * If there is no such PDO, returns -1 instead. + */ +static int8_t dpm_get_range_fixed_pdo_index(const union pd_msg *caps) { + /* Get the number of PDOs */ + uint8_t numobj = PD_NUMOBJ_GET(caps); + + /* Get ready to iterate over the PDOs */ + int8_t i; + int8_t step; + i = numobj - 1; + step = -1; + uint16_t current = 100; // in centiamps + uint16_t voltagemin = 8000; + uint16_t voltagemax = 10000; + /* Look at the PDOs to see if one falls in our voltage range. */ + while (0 <= i && i < numobj) { + /* If we have a fixed PDO, its V is within our range, and its I is at + * least our desired I */ + uint16_t v = PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i]); + if ((caps->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) { + if ( PD_PDO_SRC_FIXED_CURRENT_GET(caps->obj[i]) >= current) { + if (v >= PD_MV2PDV(voltagemin) && v <= PD_MV2PDV(voltagemax)) { + return i; + } + } + } + i += step; + } + return -1; +} +bool PolicyEngine::pdbs_dpm_evaluate_capability( + const union pd_msg *capabilities, union pd_msg *request) { + + /* Get the number of PDOs */ + uint8_t numobj = PD_NUMOBJ_GET(capabilities); + + /* Get whether or not the power supply is constrained */ + _unconstrained_power = + capabilities->obj[0] & PD_PDO_SRC_FIXED_UNCONSTRAINED; + + /* Make sure we have configuration */ + /* Look at the PDOs to see if one matches our desires */ + for (uint8_t i = 0; i < numobj; i++) { + /* If we have a fixed PDO, its V equals our desired V, and its I is + * at least our desired I */ + if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) { + //This is a fixed PDO entry + int voltage = PD_PDV2MV( + PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities->obj[i])); + int current = PD_PDO_SRC_FIXED_CURRENT_GET(capabilities->obj[i]); + if (voltage == 9000) { + + /* We got what we wanted, so build a request for that */ + request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); + + /* GiveBack disabled */ + request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET( + current) | PD_RDO_FV_CURRENT_SET(current) + | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1); + + request->obj[0] |= PD_RDO_USB_COMMS; + + /* Update requested voltage */ + _requested_voltage = voltage; + + return true; + } + } + /* If we have a PPS APDO, our desired V lies within its range, and + * its I is at least our desired I */ + if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED + && (capabilities->obj[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS) { + int min_mv = PD_PAV2MV( + PD_APDO_PPS_MIN_VOLTAGE_GET(capabilities->obj[i])); + int max_mv = PD_PAV2MV( + PD_APDO_PPS_MAX_VOLTAGE_GET(capabilities->obj[i])); + int current = PD_CA2PAI( + PD_APDO_PPS_CURRENT_GET(capabilities->obj[i])); + /* We got what we wanted, so build a request for that */ +// +// request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); +// +// /* Build a request */ +// request->obj[0] = +// PD_RDO_PROG_CURRENT_SET( +// PD_CA2PAI(current)) | PD_RDO_PROG_VOLTAGE_SET(PD_MV2PRV(voltage)) +// | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1); +// +// request->obj[0] |= PD_RDO_USB_COMMS; +// +// /* Update requested voltage */ +// _requested_voltage = PD_PRV2MV(PD_MV2PRV(voltage)); +// +// return true; + } + } + /* If there's a PDO in the voltage range, use it */ +// int8_t i = dpm_get_range_fixed_pdo_index(caps, scfg); +// if (i >= 0) { +// /* We got what we wanted, so build a request for that */ +// request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); +// /* Get the current we need at this voltage */ +// current = dpm_get_current(scfg, +// PD_PDV2MV(PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i]))); +// if (scfg->flags & PDBS_CONFIG_FLAGS_GIVEBACK) { +// /* GiveBack enabled */ +// request->obj[0] = +// PD_RDO_FV_MIN_CURRENT_SET( +// DPM_MIN_CURRENT) | PD_RDO_FV_CURRENT_SET(current) | PD_RDO_NO_USB_SUSPEND +// | PD_RDO_GIVEBACK | PD_RDO_OBJPOS_SET(i + 1); +// } else { +// /* GiveBack disabled */ +// request->obj[0] = +// PD_RDO_FV_MAX_CURRENT_SET( +// current) | PD_RDO_FV_CURRENT_SET(current) | PD_RDO_NO_USB_SUSPEND +// | PD_RDO_OBJPOS_SET(i + 1); +// } +// if (usb_comms) { +// request->obj[0] |= PD_RDO_USB_COMMS; +// } +// +// /* Update requested voltage */ +// _requested_voltage = PD_PDV2MV( +// PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i])); +// +// _capability_match = true; +// return true; +// } + /* Nothing matched (or no configuration), so get 5 V at low current */ + request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); + request->obj[0] = + PD_RDO_FV_MAX_CURRENT_SET( + DPM_MIN_CURRENT) | PD_RDO_FV_CURRENT_SET(DPM_MIN_CURRENT) | PD_RDO_NO_USB_SUSPEND + | PD_RDO_OBJPOS_SET(1); + /* If the output is enabled and we got here, it must be a capability + * mismatch. */ + if (pdNegotiationComplete) { + request->obj[0] |= PD_RDO_CAP_MISMATCH; + } + /* If we can do USB communications, tell the power supply */ + request->obj[0] |= PD_RDO_USB_COMMS; + + /* Update requested voltage */ + _requested_voltage = 5000; + + /* At this point, we have a capability match iff the output is disabled */ + return false; +} + +void PolicyEngine::pdbs_dpm_get_sink_capability(union pd_msg *cap) { + /* Keep track of how many PDOs we've added */ + int numobj = 0; + + /* If we have no configuration or want something other than 5 V, add a PDO + * for vSafe5V */ + /* Minimum current, 5 V, and higher capability. */ + cap->obj[numobj++] = + PD_PDO_TYPE_FIXED + | PD_PDO_SNK_FIXED_VOLTAGE_SET( + PD_MV2PDV(5000)) | PD_PDO_SNK_FIXED_CURRENT_SET(DPM_MIN_CURRENT); + + /* Get the current we want */ + uint16_t current = 100; // In centi-amps + uint16_t voltage = 9000; // in mv + /* Add a PDO for the desired power. */ + cap->obj[numobj++] = PD_PDO_TYPE_FIXED + | PD_PDO_SNK_FIXED_VOLTAGE_SET( + PD_MV2PDV(voltage)) | PD_PDO_SNK_FIXED_CURRENT_SET(current); + + /* Get the PDO from the voltage range */ + int8_t i = dpm_get_range_fixed_pdo_index(cap); + + /* If it's vSafe5V, set our vSafe5V's current to what we want */ + if (i == 0) { + cap->obj[0] &= ~PD_PDO_SNK_FIXED_CURRENT; + cap->obj[0] |= PD_PDO_SNK_FIXED_CURRENT_SET(current); + } else { + /* If we want more than 5 V, set the Higher Capability flag */ + if (PD_MV2PDV(voltage) != PD_MV2PDV(5000)) { + cap->obj[0] |= PD_PDO_SNK_FIXED_HIGHER_CAP; + } + + /* If the range PDO is a different voltage than the preferred + * voltage, add it to the array. */ + if (i + > 0&& PD_PDO_SRC_FIXED_VOLTAGE_GET(cap->obj[i]) != PD_MV2PDV(voltage)) { + cap->obj[numobj++] = + PD_PDO_TYPE_FIXED + | PD_PDO_SNK_FIXED_VOLTAGE_SET( + PD_PDO_SRC_FIXED_VOLTAGE_GET(cap->obj[i])) | PD_PDO_SNK_FIXED_CURRENT_SET( + PD_PDO_SRC_FIXED_CURRENT_GET(cap->obj[i])); + } + + /* If we have three PDOs at this point, make sure the last two are + * sorted by voltage. */ + if (numobj == 3 + && (cap->obj[1] & PD_PDO_SNK_FIXED_VOLTAGE) + > (cap->obj[2] & PD_PDO_SNK_FIXED_VOLTAGE)) { + cap->obj[1] ^= cap->obj[2]; + cap->obj[2] ^= cap->obj[1]; + cap->obj[1] ^= cap->obj[2]; + } + } + + /* If we're using PD 3.0, add a PPS APDO for our desired voltage */ + if (isPD3_0()) { + cap->obj[numobj++] = + PD_PDO_TYPE_AUGMENTED | PD_APDO_TYPE_PPS + | PD_APDO_PPS_MAX_VOLTAGE_SET( + PD_MV2PAV(voltage)) | PD_APDO_PPS_MIN_VOLTAGE_SET(PD_MV2PAV(voltage)) + | PD_APDO_PPS_CURRENT_SET(PD_CA2PAI(current)); + } + + /* Set the unconstrained power flag. */ + if (_unconstrained_power) { + cap->obj[0] |= PD_PDO_SNK_FIXED_UNCONSTRAINED; + } + /* Set the USB communications capable flag. */ + cap->obj[0] |= PD_PDO_SNK_FIXED_USB_COMMS; + + /* Set the Sink_Capabilities message header */ + cap->hdr = hdr_template | PD_MSGTYPE_SINK_CAPABILITIES | PD_NUMOBJ(numobj); +} + +bool PolicyEngine::pdbs_dpm_giveback_enabled() { + return false; +//We do not support giveback +} + +bool PolicyEngine::pdbs_dpm_evaluate_typec_current( + enum fusb_typec_current tcc) { +//This is for evaluating 5V static current advertised by resistors + /* We don't control the voltage anymore; it will always be 5 V. */ + current_voltage_mv = _requested_voltage = 5000; +//For the soldering iron we accept this as a fallback, but it sucks + return true; +} + +void PolicyEngine::pdbs_dpm_pd_start() { +//PD neg is starting +} + +void PolicyEngine::pdbs_dpm_transition_default() { + /* Cast the dpm_data to the right type */ + + /* Pretend we requested 5 V */ + current_voltage_mv = 5000; + /* Turn the output off */ + pdNegotiationComplete = false; + pdHasEnteredLowPower = true; +} + +void PolicyEngine::pdbs_dpm_transition_min() { + pdHasEnteredLowPower = true; +} + +void PolicyEngine::pdbs_dpm_transition_standby() { + /* If the voltage is changing, enter Sink Standby */ + if (_requested_voltage != current_voltage_mv) { + /* For the PD Buddy Sink, entering Sink Standby is equivalent to + * turning the output off. However, we don't want to change the LED + * state for standby mode. */ + pdHasEnteredLowPower = true; + } +} + +void PolicyEngine::pdbs_dpm_transition_requested() { + /* Cast the dpm_data to the right type */ + pdNegotiationComplete = true; + pdHasEnteredLowPower = false; +} + +void PolicyEngine::handleMessage(union pd_msg *msg) { + xQueueSend(messagesWaiting, msg, 100); +} + +bool PolicyEngine::messageWaiting() { + return uxQueueMessagesWaiting(messagesWaiting) > 0; +} + +void PolicyEngine::readMessage() { + xQueueReceive(messagesWaiting, &tempMessage, 1); +} + +void PolicyEngine::pdbs_dpm_transition_typec() { +//This means PD failed, so we either have a dump 5V only type C or a QC charger +//For now; treat this as failed neg + pdNegotiationComplete = false; + pdHasEnteredLowPower = false; +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp new file mode 100644 index 00000000..a3ebb2b2 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp @@ -0,0 +1,171 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "protocol_rx.h" + +#include + +#include +#include "policy_engine.h" +#include "protocol_tx.h" +#include "fusb302b.h" +osThreadId ProtocolReceive::TaskHandle; +uint32_t ProtocolReceive::TaskBuffer[ProtocolReceive::TaskStackSize]; +osStaticThreadDef_t ProtocolReceive::TaskControlBlock; +union pd_msg ProtocolReceive::tempMessage; +uint8_t ProtocolReceive::_rx_messageid; +uint8_t ProtocolReceive::_tx_messageidcounter; +/* + * PRL_Rx_Wait_for_PHY_Message state + */ +ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_wait_phy() { + /* Wait for an event */ + eventmask_t evt = waitForEvent(0xFFFFFFFF); + + /* If we got a reset event, reset */ + if (evt & PDB_EVT_PRLRX_RESET) { + return PRLRxWaitPHY; + } + /* If we got an I_GCRCSENT event, read the message and decide what to do */ + if (evt & PDB_EVT_PRLRX_I_GCRCSENT) { + /* Get a buffer to read the message into. Guaranteed to not fail + * because we have a big enough pool and are careful. */ + union pd_msg *_rx_message = &tempMessage; + /* Read the message */ + fusb_read_message(_rx_message); + /* If it's a Soft_Reset, go to the soft reset state */ + if (PD_MSGTYPE_GET(_rx_message) == PD_MSGTYPE_SOFT_RESET + && PD_NUMOBJ_GET(_rx_message) == 0) { + return PRLRxReset; + } else { + /* Otherwise, check the message ID */ + return PRLRxCheckMessageID; + } + } + + return PRLRxWaitPHY; +} + +/* + * PRL_Rx_Layer_Reset_for_Receive state + */ +ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_reset() { + /* Reset MessageIDCounter */ + _tx_messageidcounter = 0; + + /* Clear stored MessageID */ + _rx_messageid = -1; + + /* TX transitions to its reset state */ + ProtocolTransmit::notify( PDB_EVT_PRLTX_RESET); + taskYIELD(); + + /* If we got a RESET signal, reset the machine */ + if (waitForEvent(PDB_EVT_PRLRX_RESET) != 0) { + return PRLRxWaitPHY; + } + + /* Go to the Check_MessageID state */ + return PRLRxCheckMessageID; +} + +/* + * PRL_Rx_Check_MessageID state + */ +ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_check_messageid() { + /* If we got a RESET signal, reset the machine */ + if (waitForEvent(PDB_EVT_PRLRX_RESET) != 0) { + + return PRLRxWaitPHY; + } + + /* If the message has the stored ID, we've seen this message before. Free + * it and don't pass it to the policy engine. */ + if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) { + return PRLRxWaitPHY; + /* Otherwise, there's either no stored ID or this message has an ID we + * haven't just seen. Transition to the Store_MessageID state. */ + } else { + return PRLRxStoreMessageID; + } +} + +/* + * PRL_Rx_Store_MessageID state + */ +ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_store_messageid() { + /* Tell ProtocolTX to discard the message being transmitted */ + + ProtocolTransmit::notify( PDB_EVT_PRLTX_DISCARD); + taskYIELD(); + + /* Update the stored MessageID */ + _rx_messageid = PD_MESSAGEID_GET(&tempMessage); + + /* Pass the message to the policy engine. */ + + PolicyEngine::handleMessage(&tempMessage); + PolicyEngine::notify( PDB_EVT_PE_MSG_RX); + + /* Don't check if we got a RESET because we'd do nothing different. */ + + return PRLRxWaitPHY; +} + +void ProtocolReceive::init() { + osThreadStaticDef(Task, thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, + &TaskControlBlock); + TaskHandle = osThreadCreate(osThread(Task), NULL); +} + +void ProtocolReceive::thread(const void *args) { + (void) args; + ProtocolReceive::protocol_rx_state state = PRLRxWaitPHY; + + while (true) { + switch (state) { + case PRLRxWaitPHY: + state = protocol_rx_wait_phy(); + break; + case PRLRxReset: + state = protocol_rx_reset(); + break; + case PRLRxCheckMessageID: + state = protocol_rx_check_messageid(); + break; + case PRLRxStoreMessageID: + state = protocol_rx_store_messageid(); + break; + default: + /* This is an error. It really shouldn't happen. We might + * want to handle it anyway, though. */ + state = PRLRxWaitPHY; + break; + } + } +} + +void ProtocolReceive::notify(uint32_t notification) { + xTaskNotify(TaskHandle, notification, + eNotifyAction::eSetValueWithOverwrite); +} + +uint32_t ProtocolReceive::waitForEvent(uint32_t mask, uint32_t ticksToWait) { + uint32_t pulNotificationValue; + xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait); + return pulNotificationValue; +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h new file mode 100644 index 00000000..920e80a2 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h @@ -0,0 +1,61 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PDB_PROTOCOL_RX_H +#define PDB_PROTOCOL_RX_H + +#include + +#include + +/* Events for the Protocol RX thread */ +#define PDB_EVT_PRLRX_RESET EVENT_MASK(0) +#define PDB_EVT_PRLRX_I_GCRCSENT EVENT_MASK(1) + +class ProtocolReceive { +public: + static void init(); + static void notify(uint32_t notification); +private: + static void thread(const void *args); + + static osThreadId TaskHandle; + static const size_t TaskStackSize = 512 / 4; + static uint32_t TaskBuffer[TaskStackSize]; + static osStaticThreadDef_t TaskControlBlock; + /* + * Protocol RX machine states + * + * There is no Send_GoodCRC state because the PHY sends the GoodCRC for us. + * All transitions that would go to that state instead go to Check_MessageID. + */ + enum protocol_rx_state { + PRLRxWaitPHY, PRLRxReset, PRLRxCheckMessageID, PRLRxStoreMessageID + }; + static protocol_rx_state protocol_rx_store_messageid(); + static protocol_rx_state protocol_rx_check_messageid(); + static protocol_rx_state protocol_rx_reset(); + static protocol_rx_state protocol_rx_wait_phy(); + static union pd_msg tempMessage; + static uint8_t _rx_messageid; + static uint8_t _tx_messageidcounter; + static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait = + portMAX_DELAY); + +}; + +#endif /* PDB_PROTOCOL_RX_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp new file mode 100644 index 00000000..759cb003 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp @@ -0,0 +1,285 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "protocol_tx.h" +#include +#include "policy_engine.h" +#include "protocol_rx.h" +#include "fusb302b.h" +#include "fusbpd.h" + +osThreadId ProtocolTransmit::TaskHandle; +uint32_t ProtocolTransmit::TaskBuffer[ProtocolTransmit::TaskStackSize]; +osStaticThreadDef_t ProtocolTransmit::TaskControlBlock; +StaticQueue_t ProtocolTransmit::xStaticQueue; + +uint8_t ProtocolTransmit::ucQueueStorageArea[PDB_MSG_POOL_SIZE + * sizeof(union pd_msg)]; +QueueHandle_t ProtocolTransmit::messagesWaiting; +uint8_t ProtocolTransmit::_tx_messageidcounter; +union pd_msg ProtocolTransmit::temp_msg; +/* + * PRL_Tx_PHY_Layer_Reset state + */ +ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_phy_reset() { + /* Reset the PHY */ + fusb_reset(); + + /* If a message was pending when we got here, tell the policy engine that + * we failed to send it */ + if (messagePending()) { + /* Tell the policy engine that we failed */ + PolicyEngine::notify( PDB_EVT_PE_TX_ERR); + /* Finish failing to send the message */ + getMessage(); //Discard + } + + /* Wait for a message request */ + return PRLTxWaitMessage; +} + +/* + * PRL_Tx_Wait_for_Message_Request state + */ +ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_message() { + /* Wait for an event */ + eventmask_t evt = waitForEvent( + PDB_EVT_PRLTX_RESET | PDB_EVT_PRLTX_DISCARD | PDB_EVT_PRLTX_MSG_TX); + + if (evt & PDB_EVT_PRLTX_RESET) { + return PRLTxPHYReset; + } + if (evt & PDB_EVT_PRLTX_DISCARD) { + return PRLTxDiscardMessage; + } + + /* If the policy engine is trying to send a message */ + if (evt & PDB_EVT_PRLTX_MSG_TX) { + /* Get the message */ + getMessage(); + + /* If it's a Soft_Reset, reset the TX layer first */ + if (PD_MSGTYPE_GET(&temp_msg) == PD_MSGTYPE_SOFT_RESET + && PD_NUMOBJ_GET(&(temp_msg)) == 0) { + return PRLTxReset; + /* Otherwise, just send the message */ + } else { + return PRLTxConstructMessage; + } + } + + /* Silence the compiler warning */ + return PRLTxDiscardMessage; +} + +ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_reset() { + /* Clear MessageIDCounter */ + _tx_messageidcounter = 0; + + /* Tell the Protocol RX thread to reset */ + ProtocolReceive::notify( PDB_EVT_PRLRX_RESET); + taskYIELD(); + + return PRLTxConstructMessage; +} + +/* + * PRL_Tx_Construct_Message state + */ +ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_message() { + /* Make sure nobody wants us to reset */ + eventmask_t evt = waitForEvent( + PDB_EVT_PRLTX_RESET | PDB_EVT_PRLTX_DISCARD); + + if (evt & PDB_EVT_PRLTX_RESET) { + return PRLTxPHYReset; + } + if (evt & PDB_EVT_PRLTX_DISCARD) { + return PRLTxDiscardMessage; + } + + /* Set the correct MessageID in the message */ + temp_msg.hdr &= ~PD_HDR_MESSAGEID; + temp_msg.hdr |= (_tx_messageidcounter % 8) << PD_HDR_MESSAGEID_SHIFT; + + /* PD 3.0 collision avoidance */ + if (PolicyEngine::isPD3_0()) { + /* If we're starting an AMS, wait for permission to transmit */ + evt = waitForEvent(PDB_EVT_PRLTX_START_AMS); + if (evt & PDB_EVT_PRLTX_START_AMS) { + while (fusb_get_typec_current() != fusb_sink_tx_ok) { + osDelay(1); + } + } + } + + /* Send the message to the PHY */ + fusb_send_message(&temp_msg); + + return PRLTxWaitResponse; +} + +/* + * PRL_Tx_Wait_for_PHY_Response state + */ +ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_response() { + /* Wait for an event. There is no need to run CRCReceiveTimer, since the + * FUSB302B handles that as part of its retry mechanism. */ + eventmask_t evt = waitForEvent( + PDB_EVT_PRLTX_RESET | PDB_EVT_PRLTX_DISCARD | PDB_EVT_PRLTX_I_TXSENT + | PDB_EVT_PRLTX_I_RETRYFAIL); + + if (evt & PDB_EVT_PRLTX_RESET) { + return PRLTxPHYReset; + } + if (evt & PDB_EVT_PRLTX_DISCARD) { + return PRLTxDiscardMessage; + } + + /* If the message was sent successfully */ + if (evt & PDB_EVT_PRLTX_I_TXSENT) { + return PRLTxMatchMessageID; + } + /* If the message failed to be sent */ + if (evt & PDB_EVT_PRLTX_I_RETRYFAIL) { + return PRLTxTransmissionError; + } + + /* Silence the compiler warning */ + return PRLTxDiscardMessage; +} + +/* + * PRL_Tx_Match_MessageID state + */ +ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_match_messageid() { + union pd_msg goodcrc; + + /* Read the GoodCRC */ + fusb_read_message(&goodcrc); + + /* Check that the message is correct */ + if (PD_MSGTYPE_GET(&goodcrc) == PD_MSGTYPE_GOODCRC + && PD_NUMOBJ_GET(&goodcrc) == 0 + && PD_MESSAGEID_GET(&goodcrc) == _tx_messageidcounter) { + return PRLTxMessageSent; + } else { + return PRLTxTransmissionError; + } +} + +ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_transmission_error() { + /* Increment MessageIDCounter */ + _tx_messageidcounter = (_tx_messageidcounter + 1) % 8; + + /* Tell the policy engine that we failed */ + PolicyEngine::notify( PDB_EVT_PE_TX_ERR); + + return PRLTxWaitMessage; +} + +ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_message_sent() { + /* Increment MessageIDCounter */ + _tx_messageidcounter = (_tx_messageidcounter + 1) % 8; + + /* Tell the policy engine that we succeeded */ + PolicyEngine::notify( PDB_EVT_PE_TX_DONE); + + return PRLTxWaitMessage; +} + +ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_discard_message() { + /* If we were working on sending a message, increment MessageIDCounter */ + _tx_messageidcounter = (_tx_messageidcounter + 1) % 8; + + return PRLTxPHYReset; +} + +void ProtocolTransmit::thread(const void *args) { + (void) args; + ProtocolTransmit::protocol_tx_state state = PRLTxPHYReset; + + //Init the incoming message queue + + while (true) { + switch (state) { + case PRLTxPHYReset: + state = protocol_tx_phy_reset(); + break; + case PRLTxWaitMessage: + state = protocol_tx_wait_message(); + break; + case PRLTxReset: + state = protocol_tx_reset(); + break; + case PRLTxConstructMessage: + state = protocol_tx_construct_message(); + break; + case PRLTxWaitResponse: + state = protocol_tx_wait_response(); + break; + case PRLTxMatchMessageID: + state = protocol_tx_match_messageid(); + break; + case PRLTxTransmissionError: + state = protocol_tx_transmission_error(); + break; + case PRLTxMessageSent: + state = protocol_tx_message_sent(); + break; + case PRLTxDiscardMessage: + state = protocol_tx_discard_message(); + break; + default: + state = PRLTxPHYReset; + break; + } + } +} + +void ProtocolTransmit::notify(uint32_t notification) { + xTaskNotify(TaskHandle, notification, + eNotifyAction::eSetValueWithOverwrite); +} + +void ProtocolTransmit::init() { + messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, + sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue); + + osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PRL, 0, TaskStackSize, + TaskBuffer, &TaskControlBlock); + TaskHandle = osThreadCreate(osThread(pd_txTask), NULL); +} + +void ProtocolTransmit::pushMessage(union pd_msg *msg) { + xQueueSend(messagesWaiting, msg, 100); +} + +bool ProtocolTransmit::messagePending() { + return uxQueueMessagesWaiting(messagesWaiting) > 0; +} + +void ProtocolTransmit::getMessage() { + //Loads the pending message into the buffer + xQueueReceive(messagesWaiting, &temp_msg, 1); +} + +uint32_t ProtocolTransmit::waitForEvent(uint32_t mask, uint32_t ticksToWait) { + uint32_t pulNotificationValue; + xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait); + return pulNotificationValue; +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h new file mode 100644 index 00000000..bab49336 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h @@ -0,0 +1,91 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PDB_PROTOCOL_TX_H +#define PDB_PROTOCOL_TX_H + +#include +#include "policy_engine.h" +#include "protocol_rx.h" +#include + +/* Events for the Protocol TX thread */ +#define PDB_EVT_PRLTX_RESET EVENT_MASK(0) +#define PDB_EVT_PRLTX_I_TXSENT EVENT_MASK(1) +#define PDB_EVT_PRLTX_I_RETRYFAIL EVENT_MASK(2) +#define PDB_EVT_PRLTX_DISCARD EVENT_MASK(3) +#define PDB_EVT_PRLTX_MSG_TX EVENT_MASK(4) +#define PDB_EVT_PRLTX_START_AMS EVENT_MASK(5) + +class ProtocolTransmit { +public: + static void init(); + //Push a message to the queue to be sent out the pd comms bus + static void pushMessage(union pd_msg *msg); + static void notify(uint32_t notification); +private: + static void thread(const void *args); + + static osThreadId TaskHandle; + static const size_t TaskStackSize = 512 / 4; + static uint32_t TaskBuffer[TaskStackSize]; + static osStaticThreadDef_t TaskControlBlock; + /* + * Protocol TX machine states + * + * Because the PHY can automatically send retries, the Check_RetryCounter state + * has been removed, transitions relating to it are modified appropriately, and + * we don't even keep a RetryCounter. + */ + enum protocol_tx_state { + PRLTxPHYReset, + PRLTxWaitMessage, + PRLTxReset, + PRLTxConstructMessage, + PRLTxWaitResponse, + PRLTxMatchMessageID, + PRLTxTransmissionError, + PRLTxMessageSent, + PRLTxDiscardMessage + }; + //Internal states + static protocol_tx_state protocol_tx_discard_message(); + static protocol_tx_state protocol_tx_message_sent(); + static protocol_tx_state protocol_tx_transmission_error(); + static protocol_tx_state protocol_tx_match_messageid(); + static protocol_tx_state protocol_tx_wait_response(); + static protocol_tx_state protocol_tx_construct_message(); + static protocol_tx_state protocol_tx_reset(); + static protocol_tx_state protocol_tx_wait_message(); + static protocol_tx_state protocol_tx_phy_reset(); + //queue of up to PDB_MSG_POOL_SIZE messages to send + static StaticQueue_t xStaticQueue; + /* The array to use as the queue's storage area. This must be at least + uxQueueLength * uxItemSize bytes. */ + static uint8_t ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)]; + static QueueHandle_t messagesWaiting; + static uint8_t _tx_messageidcounter; + static bool messagePending(); + //Reads a message off the queue into the temp message + static void getMessage(); + static union pd_msg temp_msg; + static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait = + portMAX_DELAY); + +}; + +#endif /* PDB_PROTOCOL_TX_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp b/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp deleted file mode 100644 index bf8b60fb..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * tcpm_driver.c - * - * Created: 11/11/2017 18:42:26 - * Author: jason - */ - -#include "tcpm_driver.h" -#include "I2C_Wrapper.hpp" -#include "I2CBB.hpp" -extern const struct tcpc_config_t tcpc_config; -#define STATUS_OK 0 -/* I2C wrapper functions - get I2C port / slave addr from config struct. */ -int tcpc_write(int reg, int val) { - - I2CBB::Mem_Write(tcpc_config.i2c_slave_addr, reg, (uint8_t*) &val, 1); - return STATUS_OK; -} - -int tcpc_write16(int reg, int val) { - uint8_t data[2]; - data[0] = (0xFF) & val; - data[1] = (0xFF) & (val >> 8); - I2CBB::Mem_Write(tcpc_config.i2c_slave_addr, reg, (uint8_t*) data, 2); - return STATUS_OK; -} - -int tcpc_read(int reg, int *val) { - uint8_t data[1]; - - I2CBB::Mem_Read(tcpc_config.i2c_slave_addr, reg, (uint8_t*) data, 1); - - *val = data[0]; - - return STATUS_OK; -} - -int tcpc_read16(int reg, int *val) { - uint8_t data[2]; - I2CBB::Mem_Write(tcpc_config.i2c_slave_addr, reg, (uint8_t*) data, 2); - - *val = data[0]; - *val |= (data[1] << 8); - - return STATUS_OK; -} - -int tcpc_xfer(const uint8_t *out, int out_size, uint8_t *in, int in_size, - int flags) { - // Write out the I2C port to the given slave address - // Write out the out byte array to the device (sending a stop if the flag is set) - // Then issue a read from the device - - if (flags & I2C_XFER_STOP) { - //Issuing a stop between the requests - //Send as a Tx followed by a Rx - I2CBB::Transmit(tcpc_config.i2c_slave_addr, (uint8_t*) out, - out_size); - I2CBB::Receive(tcpc_config.i2c_slave_addr, in, in_size); - } else { - //issue as a continious transmit & recieve - I2CBB::TransmitReceive(tcpc_config.i2c_slave_addr, (uint8_t*) out, - out_size, in, in_size); - } - - return STATUS_OK; -} - -uint8_t fusb302_detect() { - //Probe the I2C bus for its address - return I2CBB::probe(fusb302_I2C_SLAVE_ADDR); -} diff --git a/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.h b/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.h deleted file mode 100644 index f3180f9f..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/tcpm_driver.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * tcpm_driver.h - * - * Created: 11/11/2017 18:42:39 - * Author: jason - */ - - -#ifndef TCPM_DRIVER_H_ -#define TCPM_DRIVER_H_ - -#include - -// USB-C Stuff -#include "USBC_TCPM/tcpm.h" -#include "FUSB302.h" -#define CONFIG_USB_PD_PORT_COUNT 1 -extern struct i2c_master_module i2c_master_instance; - - - -#endif /* TCPM_DRIVER_H_ */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp deleted file mode 100644 index 7036633d..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* - * usb_pd_driver.c - * - * Created: 11/11/2017 23:55:12 - * Author: jason - */ - -#include "usb_pd_driver.h" -#include "USBC_PD/usb_pd.h" -#include -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(t) (sizeof(t) / sizeof(t[0])) -#endif - -extern struct tc_module tc_instance; -extern uint32_t g_us_timestamp_upper_32bit; - -uint32_t pd_task_set_event(uint32_t event, int wait_for_reply) { - switch (event) { - case PD_EVENT_TX: - break; - default: - break; - } - return 0; -} - -const uint32_t pd_src_pdo[] = { PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), }; - -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); - -const uint32_t pd_snk_pdo[] = { PDO_FIXED(5000, 1000, PDO_FIXED_FLAGS), - PDO_FIXED(9000, 1500, PDO_FIXED_FLAGS), PDO_FIXED(12000, 3500, - PDO_FIXED_FLAGS), }; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); - -void pd_set_input_current_limit(uint32_t max_ma, uint32_t supply_voltage) { - -} - -int pd_is_valid_input_voltage(int mv) { - return 1; -} - -int pd_snk_is_vbus_provided() { - return 1; -} - -timestamp_t get_time(void) { - timestamp_t t; - //TODO -// -// system_interrupt_enter_critical_section(); -// t.le.lo = tc_get_count_value(&tc_instance); -// t.le.hi = g_us_timestamp_upper_32bit; -// system_interrupt_leave_critical_section(); - - return t; -} - -void pd_power_supply_reset() { - return; -} - -void pd_execute_data_swap(int data_role) { - /* Do nothing */ -} - -int pd_check_data_swap(int data_role) { - // Never allow data swap - return 0; -} - -int pd_check_power_swap() { - /* Always refuse power swap */ - return 0; -} - -int pd_board_checks(void) { - return EC_SUCCESS; -} - -int pd_set_power_supply_ready() { -//Tells other device if we can supply power - return EC_SUCCESS; /* we are ready */ -} - -void pd_transition_voltage(int idx) { - /* No-operation: we are always 5V */ - -#if 0 - timestamp_t deadline; - uint32_t mv = src_pdo_charge[idx - 1].mv; - - /* Is this a transition to a new voltage? */ - if (charge_port_is_active() && vbus[CHG].mv != mv) { - /* - * Alter voltage limit on charge port, this should cause - * the port to select the desired PDO. - */ - pd_set_external_voltage_limit(CHG, mv); - - /* Wait for CHG transition */ - deadline.val = get_time().val + PD_T_PS_TRANSITION; - CPRINTS("Waiting for CHG port transition"); - while (charge_port_is_active() && - vbus[CHG].mv != mv && - get_time().val < deadline.val) - msleep(10); - - if (vbus[CHG].mv != mv) { - CPRINTS("Missed CHG transition, resetting DUT"); - pd_power_supply_reset(DUT); - return; - } - - CPRINTS("CHG transitioned"); - } - - vbus[DUT].mv = vbus[CHG].mv; - vbus[DUT].ma = vbus[CHG].ma; -#endif // if 0 - -} - -void pd_check_dr_role(int dr_role, int flags) { -#if 0 - /* If UFP, try to switch to DFP */ - if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP) - pd_request_data_swap(port); -#endif -} - -void pd_check_pr_role(int pr_role, int flags) { -#if 0 - /* - * If partner is dual-role power and dualrole toggling is on, consider - * if a power swap is necessary. - */ - if ((flags & PD_FLAGS_PARTNER_DR_POWER) && - pd_get_dual_role() == PD_DRP_TOGGLE_ON) { - /* - * If we are a sink and partner is not externally powered, then - * swap to become a source. If we are source and partner is - * externally powered, swap to become a sink. - */ - int partner_extpower = flags & PD_FLAGS_PARTNER_EXTPOWER; - - if ((!partner_extpower && pr_role == PD_ROLE_SINK) || - (partner_extpower && pr_role == PD_ROLE_SOURCE)) - pd_request_power_swap(port); - } -#endif // if 0 -} - -void pd_process_source_cap_callback(int cnt, uint32_t *src_caps) { - char str[256]; - int i; - uint32_t ma, mv, pdo; - - for (i = 0; i < cnt; i++) { - pd_extract_pdo_power(src_caps[i], &ma, &mv); - //Charger can supply power at mv & mA - //TODO we want to ask for the charger to select the closest to our ideal (12V) - //And fall back to 9V - } - -//TODO Handle information on supported voltages? -} - -/* ----------------- Vendor Defined Messages ------------------ */ -/* Holds valid object position (opos) for entered mode */ - -const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ -1, /* data caps as USB device */ -IDH_PTYPE_PERIPH, /* Alternate mode */ -0, /* Does not support alt modes */ -USB_VID_GOOGLE); - -const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); - -const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS, - CONFIG_USB_PD_IDENTITY_SW_VERS, 0, 0, 0, 0, /* SS[TR][12] */ - 0, /* Vconn power */ - 0, /* Vconn power required */ - 1, /* Vbus power required */ - AMA_USBSS_U2_ONLY /* USB 2.0 support */); - -static int svdm_response_identity(uint32_t *payload) { - payload[VDO_I(IDH)] = vdo_idh; - payload[VDO_I(CSTAT)] = VDO_CSTAT(0); - payload[VDO_I(PRODUCT)] = vdo_product; - payload[VDO_I(AMA)] = vdo_ama; - return VDO_I(AMA) + 1; -} -//No custom svdm -static int svdm_response_svids(uint32_t *payload) { - payload[1] = 0; - return 2; -} - -#define OPOS_DP 1 -#define OPOS_GFU 1 - -const uint32_t vdo_dp_modes[1] = { VDO_MODE_DP(0, /* UFP pin cfg supported : none */ -MODE_DP_PIN_C, /* DFP pin cfg supported */ -1, /* no usb2.0 signalling in AMode */ -CABLE_PLUG, /* its a plug */ -MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ -MODE_DP_SNK) /* Its a sink only */ -}; - -static int svdm_response_modes(uint32_t *payload) { - return 0; /* nak */ -} - -static int dp_status(uint32_t *payload) { - int opos = PD_VDO_OPOS(payload[0]); - int hpd = 0; // gpio_get_level(GPIO_DP_HPD); - if (opos != OPOS_DP) - return 0; /* nak */ - - payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ - (hpd == 1), /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - 0, /* MF pref */ - 0, //gpio_get_level(GPIO_PD_SBU_ENABLE), - 0, /* power low */ - 0x2); - return 2; -} - -static int dp_config(uint32_t *payload) { - return 1; -} - -static int svdm_enter_mode(uint32_t *payload) { - int rv = 0; /* will generate a NAK */ - - return rv; -} - -int pd_alt_mode(uint16_t svid) { - - return 0; -} - -static int svdm_exit_mode(uint32_t *payload) { - return 1; /* Must return ACK */ -} - -static struct amode_fx dp_fx = { .status = &dp_status, .config = &dp_config, }; - -const struct svdm_response svdm_rsp = { &svdm_response_identity, - &svdm_response_svids, &svdm_response_modes, &svdm_enter_mode, - &svdm_exit_mode, &dp_fx, }; - diff --git a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h b/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h deleted file mode 100644 index 18100253..00000000 --- a/workspace/TS100/Core/Drivers/FUSB302/usb_pd_driver.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * usb_pd_driver.h - * - * Created: 11/11/2017 23:55:25 - * Author: jason - */ - - -#ifndef USB_PD_DRIVER_H_ -#define USB_PD_DRIVER_H_ - -#include "USBC_PD/usb_pd.h" -#include "cmsis_os.h" -#include - -//#define CONFIG_BBRAM -#define CONFIG_CHARGE_MANAGER -//#define CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP -//#define CONFIG_USBC_VCONN_SWAP -//#define CONFIG_USB_PD_ALT_MODE -//#define CONFIG_USB_PD_CHROMEOS -//#define CONFIG_USB_PD_DUAL_ROLE -//#define CONFIG_USB_PD_GIVE_BACK -//#define CONFIG_USB_PD_SIMPLE_DFP -//#define CONFIG_USB_PD_TCPM_TCPCI -#define PD_PREFER_HIGH_VOLTAGE - -/* Default pull-up value on the USB-C ports when they are used as source. */ -#define CONFIG_USB_PD_PULLUP TYPEC_RP_USB - -/* Override PD_ROLE_DEFAULT in usb_pd.h */ -#define PD_ROLE_DEFAULT(port) (PD_ROLE_SINK) - -/* Don't automatically change roles */ -#undef CONFIG_USB_PD_INITIAL_DRP_STATE -#define CONFIG_USB_PD_INITIAL_DRP_STATE PD_DRP_FREEZE - -/* Prefer higher voltage, and more importantly, lower current */ -#define PD_PREFER_HIGH_VOLTAGE -//#define PD_PREFER_LOW_VOLTAGE - -/* board specific type-C power constants */ -/* - * delay to turn on the power supply max is ~16ms. - * delay to turn off the power supply max is about ~180ms. - */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 10000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 20000 /* us */ - -/* Define typical operating power and max power */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 100000 -#define PD_MAX_CURRENT_MA 5000 -#define PD_MAX_VOLTAGE_MV 20000 - -#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ -PDO_FIXED_COMM_CAP) - -/* USB configuration */ -#define CONFIG_USB_PID 0x502f // Stolen, so should change for anything useful -#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */ - -/* Optional features */ -#define CONFIG_USB_PD_IDENTITY_HW_VERS 1 -#define CONFIG_USB_PD_IDENTITY_SW_VERS 1 - -#define usleep(us) (osDelay(1)) -#define msleep(us) (osDelay(us)) - -typedef union { - uint64_t val; - struct { - uint32_t lo; - uint32_t hi; - } le /* little endian words */; - } timestamp_t; - -uint32_t pd_task_set_event(uint32_t event, int wait_for_reply); -void pd_power_supply_reset(int port); - -// Get the current timestamp from the system timer. -timestamp_t get_time(void); - -/* Standard macros / definitions */ -#ifndef MAX -#define MAX(a, b) \ -({ \ - __typeof__(a) temp_a = (a); \ - __typeof__(b) temp_b = (b); \ - \ - temp_a > temp_b ? temp_a : temp_b; \ -}) -#endif -#ifndef MIN -#define MIN(a, b) \ -({ \ - __typeof__(a) temp_a = (a); \ - __typeof__(b) temp_b = (b); \ - \ - temp_a < temp_b ? temp_a : temp_b; \ -}) -#endif - -#endif /* USB_PD_DRIVER_H_ */ diff --git a/workspace/TS100/Core/Inc/FreeRTOSConfig.h b/workspace/TS100/Core/Inc/FreeRTOSConfig.h index 8989a8d8..ae12d43d 100644 --- a/workspace/TS100/Core/Inc/FreeRTOSConfig.h +++ b/workspace/TS100/Core/Inc/FreeRTOSConfig.h @@ -1,173 +1,171 @@ -/* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. - All rights reserved - - VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - - *************************************************************************** - >>! NOTE: The modification to the GPL is included to allow you to !<< - >>! distribute a combined work that includes FreeRTOS without being !<< - >>! obliged to provide the source code for proprietary components !<< - >>! outside of the FreeRTOS kernel. !<< - *************************************************************************** - - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. Full license text is available on the following - link: http://www.freertos.org/a00114.html - - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that is more than just the market leader, it * - * is the industry's de facto standard. * - * * - * Help yourself get started quickly while simultaneously helping * - * to support the FreeRTOS project by purchasing a FreeRTOS * - * tutorial book, reference manual, or both: * - * http://www.FreeRTOS.org/Documentation * - * * - *************************************************************************** - - http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading - the FAQ page "My application does not run, what could be wrong?". Have you - defined configASSERT()? - - http://www.FreeRTOS.org/support - In return for receiving this top quality - embedded software for free we request you assist our global community by - participating in the support forum. - - http://www.FreeRTOS.org/training - Investing in training allows your team to - be as productive as possible as early as possible. Now you can receive - FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers - Ltd, and the world's leading authority on the world's leading RTOS. - - http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, - including FreeRTOS+Trace - an indispensable productivity tool, a DOS - compatible FAT file system, and our tiny thread aware UDP/IP stack. - - http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. - Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. - - http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High - Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and commercial middleware. - - http://www.SafeRTOS.com - High Integrity Systems also provide a safety - engineered and independently SIL3 certified version for use in safety and - mission critical applications that require provable dependability. - - 1 tab == 4 spaces! -*/ - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html. - *----------------------------------------------------------*/ - -/* USER CODE BEGIN Includes */ -/* Section where include file can be added */ -/* USER CODE END Includes */ - -/* Ensure stdint is only used by the compiler, and not the assembler. */ -#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) - #include - extern uint32_t SystemCoreClock; -#endif - -#define configUSE_PREEMPTION 1 -#define configSUPPORT_STATIC_ALLOCATION 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 0 -#define configUSE_IDLE_HOOK 1 -#define configUSE_TICK_HOOK 0 -#define configCPU_CLOCK_HZ ( SystemCoreClock ) -#define configTICK_RATE_HZ ((TickType_t)100) -#define configMAX_PRIORITIES ( 4 ) -#define configMINIMAL_STACK_SIZE ((uint16_t)256) -#define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/ -#define configMAX_TASK_NAME_LEN ( 24 ) -#define configUSE_16_BIT_TICKS 0 -#define configUSE_MUTEXES 1 -#define configQUEUE_REGISTRY_SIZE 8 -#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 -#define configCHECK_FOR_STACK_OVERFLOW 2 /*Bump this to 2 during development and bug hunting*/ - - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) - -/* Set the following definitions to 1 to include the API function, or zero -to exclude the API function. */ -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 0 -#define INCLUDE_vTaskDelete 0 -#define INCLUDE_vTaskCleanUpResources 0 -#define INCLUDE_vTaskSuspend 0 -#define INCLUDE_vTaskDelayUntil 0 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 1 - -/* Cortex-M specific definitions. */ -#ifdef __NVIC_PRIO_BITS - /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ - #define configPRIO_BITS __NVIC_PRIO_BITS -#else - #define configPRIO_BITS 4 -#endif - -/* The lowest interrupt priority that can be used in a call to a "set priority" -function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 - -/* The highest interrupt priority that can be used by any interrupt service -routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL -INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER -PRIORITY THAN THIS! (higher priorities are lower numeric values. */ -#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 - -/* Interrupt priorities used by the kernel port layer itself. These are generic -to all Cortex-M ports, and do not rely on any particular library functions. */ -#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) -/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! -See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ -#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) - -/* Normal assert() semantics without relying on the provision of an assert.h -header file. */ -/* USER CODE BEGIN 1 */ -#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} -/* USER CODE END 1 */ - -/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS -standard names. */ -#define vPortSVCHandler SVC_Handler -#define xPortPendSVHandler PendSV_Handler - -/* IMPORTANT: This define MUST be commented when used with STM32Cube firmware, - to prevent overwriting SysTick_Handler defined within STM32Cube HAL */ -/* #define xPortSysTickHandler SysTick_Handler */ - -/* USER CODE BEGIN Defines */ -/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */ -/* USER CODE END Defines */ - -#endif /* FREERTOS_CONFIG_H */ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +/* USER CODE BEGIN Includes */ +/* Section where include file can be added */ +/* USER CODE END Includes */ + +/* Ensure stdint is only used by the compiler, and not the assembler. */ +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) +#include +extern uint32_t SystemCoreClock; +#endif + +#define configUSE_PREEMPTION 1 +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 0 +#define configCPU_CLOCK_HZ ( SystemCoreClock ) +#define configTICK_RATE_HZ ((TickType_t)100) +#define configMAX_PRIORITIES ( 6 ) +#define configMINIMAL_STACK_SIZE ((uint16_t)256) +#define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/ +#define configMAX_TASK_NAME_LEN ( 24 ) +#define configUSE_16_BIT_TICKS 0 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configUSE_TIMERS 1 /* Required for PD 10ms callback for PPS mode*/ +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configCHECK_FOR_STACK_OVERFLOW 2 /*Bump this to 2 during development and bug hunting*/ + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* Set the following definitions to 1 to include the API function, or zero + to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 0 +#define INCLUDE_vTaskDelayUntil 0 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 + +/* Cortex-M specific definitions. */ +#ifdef __NVIC_PRIO_BITS + /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ + #define configPRIO_BITS __NVIC_PRIO_BITS +#else +#define configPRIO_BITS 4 +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" + function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 + +/* The highest interrupt priority that can be used by any interrupt service + routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL + INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER + PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 + +/* Interrupt priorities used by the kernel port layer itself. These are generic + to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! + See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* Normal assert() semantics without relying on the provision of an assert.h + header file. */ +/* USER CODE BEGIN 1 */ +#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} +/* USER CODE END 1 */ + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS + standard names. */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler + +#if configUSE_TIMERS +#define configTIMER_TASK_PRIORITY 2 +#define configTIMER_QUEUE_LENGTH 8 +#define configTIMER_TASK_STACK_DEPTH (512/4) +#endif + +#endif /* FREERTOS_CONFIG_H */ diff --git a/workspace/TS100/Core/Src/FreeRTOSHooks.c b/workspace/TS100/Core/Src/FreeRTOSHooks.c index 1e9c3dc6..4807480a 100644 --- a/workspace/TS100/Core/Src/FreeRTOSHooks.c +++ b/workspace/TS100/Core/Src/FreeRTOSHooks.c @@ -22,6 +22,16 @@ void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* place for user code */ } +static StaticTask_t xTimerTaskTCBBuffer; +static StackType_t xTimerStack[configTIMER_TASK_STACK_DEPTH]; + +void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, + StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) { + *ppxTimerTaskTCBBuffer = &xTimerTaskTCBBuffer; + *ppxTimerTaskStackBuffer = &xTimerStack[0]; + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; + /* place for user code */ +} void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCHAR *pcTaskName) { From 61f991e4235a54cac8bbf8ba0a8ef62fb3d19870 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 14 Jun 2020 21:12:25 +1000 Subject: [PATCH 06/53] Fix watchdog timeouts && get unit to boot --- workspace/TS100/Core/BSP/Miniware/BSP.cpp | 3 +++ workspace/TS100/Core/BSP/Miniware/I2CBB.cpp | 5 +++-- workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp | 12 ++++++++++-- workspace/TS100/Core/Drivers/FUSB302/fusb302b.h | 8 ++++---- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/BSP.cpp b/workspace/TS100/Core/BSP/Miniware/BSP.cpp index da79b46f..760c7afd 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP.cpp +++ b/workspace/TS100/Core/BSP/Miniware/BSP.cpp @@ -94,6 +94,9 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { sum += samples[i]; sum /= BATTFILTERDEPTH; + if (divisor == 0) { + divisor = 1; + } return sum * 4 / divisor; } diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp index 44db8cb2..1c561c77 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp @@ -13,7 +13,7 @@ #define SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET) #define SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0) #define SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0) -#define I2C_DELAY() HAL_Delay(1); +#define I2C_DELAY() {for(int xx=0;xx<100;xx++){asm("nop");}} void I2CBB::init() { //Set GPIO's to output open drain GPIO_InitTypeDef GPIO_InitStruct; @@ -70,6 +70,7 @@ bool I2CBB::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, return false; } while (Size) { + resetWatchdog(); bool ack = send(pData[0]); if (!ack) { stop(); @@ -182,7 +183,7 @@ bool I2CBB::send(uint8_t value) { value <<= 1; } - bool ack = read_bit()==0; + bool ack = read_bit() == 0; return ack; } diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp index 46956178..6e57b9fc 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp @@ -152,14 +152,21 @@ void fusb_setup() { /* Flush the RX buffer */ fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); + resetWatchdog(); /* Measure CC1 */ fusb_write_byte( FUSB_SWITCHES0, 0x07); - osDelay(1); + resetWatchdog(); + delay_ms(1); + resetWatchdog(); uint8_t cc1 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; + resetWatchdog(); /* Measure CC2 */ + resetWatchdog(); fusb_write_byte( FUSB_SWITCHES0, 0x0B); - osDelay(1); + resetWatchdog(); + delay_ms(1); + resetWatchdog(); uint8_t cc2 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; /* Select the correct CC line for BMC signaling; also enable AUTO_CRC */ @@ -170,6 +177,7 @@ void fusb_setup() { fusb_write_byte( FUSB_SWITCHES1, 0x26); fusb_write_byte( FUSB_SWITCHES0, 0x0B); } + resetWatchdog(); /* Reset the PD logic */ fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h index 7bb4ed2c..d11979a9 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h +++ b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h @@ -24,10 +24,10 @@ #include /* I2C addresses of the FUSB302B chips */ -#define FUSB302B_ADDR 0x22 -#define FUSB302B01_ADDR 0x23 -#define FUSB302B10_ADDR 0x24 -#define FUSB302B11_ADDR 0x25 +#define FUSB302B_ADDR (0x22<<1) +#define FUSB302B01_ADDR (0x23<<1) +#define FUSB302B10_ADDR (0x24<<1) +#define FUSB302B11_ADDR (0x25<<1) /* Device ID register */ #define FUSB_DEVICE_ID 0x01 From 9ea92a3c17b9b3ff78ecfb71d60d897457d23804 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 14 Jun 2020 21:12:41 +1000 Subject: [PATCH 07/53] Disable i2c slave code (shaves off a few hundred bytes) --- .../Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c index 09846a44..4f839a3f 100644 --- a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c +++ b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c @@ -3479,6 +3479,7 @@ void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) } } /* Slave mode selected */ +#if 0 else { /* ADDR set --------------------------------------------------------------*/ @@ -3520,6 +3521,7 @@ void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) } } } +#endif } /** From 54a8aa7ac6259f9c66412d10af76d9de3d25ebe8 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 16 Jun 2020 20:19:06 +1000 Subject: [PATCH 08/53] I2C protection --- workspace/TS100/Core/BSP/Miniware/I2CBB.cpp | 58 +++++++++++++++++++-- workspace/TS100/Core/BSP/Miniware/I2CBB.hpp | 6 +++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp index 1c561c77..ef19db03 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp @@ -6,14 +6,16 @@ */ #include - +#include "FreeRTOS.h" #define SCL_HIGH() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_SET) #define SCL_LOW() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_RESET) #define SDA_HIGH() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_SET) #define SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET) #define SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0) #define SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0) -#define I2C_DELAY() {for(int xx=0;xx<100;xx++){asm("nop");}} +#define I2C_DELAY() {for(int xx=0;xx<700;xx++){asm("nop");}} +SemaphoreHandle_t I2CBB::I2CSemaphore = NULL; +StaticSemaphore_t I2CBB::xSemaphoreBuffer; void I2CBB::init() { //Set GPIO's to output open drain GPIO_InitTypeDef GPIO_InitStruct; @@ -25,6 +27,9 @@ void I2CBB::init() { HAL_GPIO_Init(SDA2_GPIO_Port, &GPIO_InitStruct); SDA_HIGH(); SCL_HIGH(); + I2CSemaphore = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer); + xSemaphoreGive(I2CSemaphore); + unlock(); } bool I2CBB::probe(uint8_t address) { @@ -36,15 +41,26 @@ bool I2CBB::probe(uint8_t address) { bool I2CBB::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { + if (!lock()) + return false; start(); - bool ack = send(DevAddress | 1); + bool ack = send(DevAddress); if (!ack) { stop(); + unlock(); return false; } ack = send(MemAddress); if (!ack) { stop(); + unlock(); + return false; + } + start(); + ack = send(DevAddress | 1); + if (!ack) { + stop(); + unlock(); return false; } while (Size) { @@ -53,20 +69,27 @@ bool I2CBB::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, Size--; } stop(); + unlock(); return true; } bool I2CBB::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { + if (!lock()) + return false; start(); bool ack = send(DevAddress); if (!ack) { stop(); + asm("bkpt"); + unlock(); return false; } ack = send(MemAddress); if (!ack) { stop(); + asm("bkpt"); + unlock(); return false; } while (Size) { @@ -74,40 +97,51 @@ bool I2CBB::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, bool ack = send(pData[0]); if (!ack) { stop(); + asm("bkpt"); + unlock(); return false; } pData++; Size--; } stop(); + unlock(); return true; } void I2CBB::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { + if (!lock()) + return; start(); bool ack = send(DevAddress); if (!ack) { stop(); + unlock(); return; } while (Size) { bool ack = send(pData[0]); if (!ack) { stop(); + unlock(); return; } pData++; Size--; } stop(); + unlock(); } void I2CBB::Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { + if (!lock()) + return; start(); bool ack = send(DevAddress | 1); if (!ack) { stop(); + unlock(); return; } while (Size) { @@ -116,23 +150,28 @@ void I2CBB::Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { Size--; } stop(); + unlock(); } void I2CBB::TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx) { if (Size_tx == 0 && Size_rx == 0) return; + if (lock() == false) + return; if (Size_tx) { start(); bool ack = send(DevAddress); if (!ack) { stop(); + unlock(); return; } while (Size_tx) { bool ack = send(pData_tx[0]); if (!ack) { stop(); + unlock(); return; } pData_tx++; @@ -144,6 +183,7 @@ void I2CBB::TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, bool ack = send(DevAddress | 1); if (!ack) { stop(); + unlock(); return; } while (Size_rx) { @@ -153,6 +193,7 @@ void I2CBB::TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, } } stop(); + unlock(); } void I2CBB::start() { @@ -220,6 +261,17 @@ uint8_t I2CBB::read_bit() { return b; } +void I2CBB::unlock() { + xSemaphoreGive(I2CSemaphore); +} + +bool I2CBB::lock() { + if (I2CSemaphore == NULL) { + asm("bkpt"); + } + return xSemaphoreTake(I2CSemaphore, (TickType_t) 50) == pdTRUE; +} + void I2CBB::write_bit(uint8_t val) { if (val > 0) SDA_HIGH(); diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp index 5be764d8..8c67cd19 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp @@ -10,6 +10,8 @@ #include "BSP.h" #include "Setup.h" #include "Pins.h" +#include "FreeRTOS.h" +#include "semphr.h" /* * Simple static I2C bit-bang class used on the TS80P * SCL = PA5 @@ -31,6 +33,10 @@ public: static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); private: + static SemaphoreHandle_t I2CSemaphore; + static StaticSemaphore_t xSemaphoreBuffer; + static void unlock(); + static bool lock(); static void start(); static void stop(); static bool send(uint8_t value); From 2fd06887e8e875ad623bb11a85c02876741f2e4a Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 16 Jun 2020 20:21:26 +1000 Subject: [PATCH 09/53] Better messages flowing --- workspace/TS100/Core/BSP/Miniware/Pins.h | 47 +++++++++++++++++-- workspace/TS100/Core/BSP/Miniware/Power.cpp | 15 +++--- workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp | 4 +- .../TS100/Core/BSP/Miniware/UnitSettings.h | 2 +- workspace/TS100/Core/BSP/Miniware/preRTOS.cpp | 2 +- .../TS100/Core/Drivers/FUSB302/fusb302b.cpp | 12 +++-- .../TS100/Core/Drivers/FUSB302/fusbpd.cpp | 2 +- .../TS100/Core/Drivers/FUSB302/hard_reset.cpp | 2 +- workspace/TS100/Core/Drivers/FUSB302/pd.h | 6 +-- .../TS100/Core/Drivers/FUSB302/pdb_conf.h | 15 ------ .../Core/Drivers/FUSB302/policy_engine.cpp | 2 +- .../Drivers/FUSB302/policy_engine_user.cpp | 2 + .../Core/Drivers/FUSB302/protocol_rx.cpp | 18 +++---- .../Core/Drivers/FUSB302/protocol_tx.cpp | 12 +++-- workspace/TS100/Core/Inc/power.hpp | 11 +---- workspace/TS100/Core/Src/main.cpp | 4 +- workspace/TS100/Makefile | 4 +- workspace/TS100/configuration.h | 47 +++++++++++++++---- 18 files changed, 132 insertions(+), 75 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/Pins.h b/workspace/TS100/Core/BSP/Miniware/Pins.h index ff6586b6..e932d9eb 100644 --- a/workspace/TS100/Core/BSP/Miniware/Pins.h +++ b/workspace/TS100/Core/BSP/Miniware/Pins.h @@ -8,9 +8,9 @@ #ifndef BSP_MINIWARE_PINS_H_ #define BSP_MINIWARE_PINS_H_ -#if defined(MODEL_TS100) + defined(MODEL_TS80) > 1 +#if defined(MODEL_TS100) + defined(MODEL_TS80)+defined(MODEL_TS80P) > 1 #error "Multiple models defined!" -#elif defined(MODEL_TS100) + defined(MODEL_TS80) == 0 +#elif defined(MODEL_TS100) + defined(MODEL_TS80)+ defined(MODEL_TS80P) == 0 #error "No model defined!" #endif @@ -45,8 +45,8 @@ #define SCL_GPIO_Port GPIOB #define SDA_Pin GPIO_PIN_7 #define SDA_GPIO_Port GPIOB - -#else +#endif +#ifdef MODEL_TS80 // TS80 pin map #define KEY_B_Pin GPIO_PIN_0 #define KEY_B_GPIO_Port GPIOB @@ -84,6 +84,45 @@ #define INT_PD_Pin GPIO_PIN_9 #define INT_PD_GPIO_Port GPIOA +#endif +#ifdef MODEL_TS80P +// TS80P pin map +#define KEY_B_Pin GPIO_PIN_0 +#define KEY_B_GPIO_Port GPIOB +#define TMP36_INPUT_Pin GPIO_PIN_4 +#define TMP36_INPUT_GPIO_Port GPIOA +#define TMP36_ADC1_CHANNEL ADC_CHANNEL_4 +#define TIP_TEMP_Pin GPIO_PIN_3 +#define TIP_TEMP_GPIO_Port GPIOA +#define TIP_TEMP_ADC1_CHANNEL ADC_CHANNEL_3 +#define TIP_TEMP_ADC2_CHANNEL ADC_CHANNEL_3 + +#define VIN_Pin GPIO_PIN_2 +#define VIN_GPIO_Port GPIOA +#define VIN_ADC1_CHANNEL ADC_CHANNEL_2 +#define VIN_ADC2_CHANNEL ADC_CHANNEL_2 +#define OLED_RESET_Pin GPIO_PIN_15 +#define OLED_RESET_GPIO_Port GPIOA +#define KEY_A_Pin GPIO_PIN_1 +#define KEY_A_GPIO_Port GPIOB +#define INT_Orientation_Pin GPIO_PIN_4 +#define INT_Orientation_GPIO_Port GPIOB +#define PWM_Out_Pin GPIO_PIN_6 +#define PWM_Out_GPIO_Port GPIOA +#define PWM_Out_CHANNEL TIM_CHANNEL_1 +#define INT_Movement_Pin GPIO_PIN_5 +#define INT_Movement_GPIO_Port GPIOB +#define SCL_Pin GPIO_PIN_6 +#define SCL_GPIO_Port GPIOB +#define SDA_Pin GPIO_PIN_7 +#define SDA_GPIO_Port GPIOB +#define SCL2_Pin GPIO_PIN_5 +#define SCL2_GPIO_Port GPIOA +#define SDA2_Pin GPIO_PIN_1 +#define SDA2_GPIO_Port GPIOA +#define INT_PD_Pin GPIO_PIN_9 +#define INT_PD_GPIO_Port GPIOA + #endif #endif /* BSP_MINIWARE_PINS_H_ */ diff --git a/workspace/TS100/Core/BSP/Miniware/Power.cpp b/workspace/TS100/Core/BSP/Miniware/Power.cpp index 4421151e..3faeedb5 100644 --- a/workspace/TS100/Core/BSP/Miniware/Power.cpp +++ b/workspace/TS100/Core/BSP/Miniware/Power.cpp @@ -8,10 +8,9 @@ bool FUSB302_present = false; void power_probe() { // If TS80 probe for QC // If TS100 - noop -#ifdef MODEL_TS80 +#ifdef defined(MODEL_TS80)+defined(MODEL_TS80P)>0 startQC(systemSettings.voltageDiv); - seekQC((systemSettings.cutoutSetting) ? 120 : 90, systemSettings.voltageDiv); // this will move the QC output to the preferred voltage to start with @@ -19,12 +18,12 @@ void power_probe() { } void power_check() { -#ifdef MODEL_TS80 +#ifdef defined(MODEL_TS80)+defined(MODEL_TS80P)>0 QC_resync(); #endif } uint8_t usb_pd_detect() { -#ifdef MODEL_TS80 +#ifdef MODEL_TS80P FUSB302_present = fusb302_detect(); if (FUSB302_present) { GPIO_InitTypeDef GPIO_InitStruct; @@ -39,9 +38,11 @@ uint8_t usb_pd_detect() { return false; } uint8_t pd_irq_read() { -#ifdef MODEL_TS80 - return HAL_GPIO_ReadPin(INT_PD_GPIO_Port, INT_PD_Pin) == GPIO_PIN_SET ? - 1 : 0; +#ifdef MODEL_TS80P + if (FUSB302_present) { + return HAL_GPIO_ReadPin(INT_PD_GPIO_Port, INT_PD_Pin) == GPIO_PIN_SET ? + 1 : 0; + } #endif return 0; } diff --git a/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp b/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp index bd3841c3..5d5f3b10 100644 --- a/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp +++ b/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp @@ -67,8 +67,8 @@ void QC_Post_Probe_En() { uint8_t QC_DM_PulledDown() { return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == GPIO_PIN_RESET ? 1 : 0; } void QC_resync() { -#ifdef MODEL_TS80 +#if defined(MODEL_TS80) + defined(MODEL_TS80P) >0 seekQC((systemSettings.cutoutSetting) ? 120 : 90, systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much #endif -} \ No newline at end of file +} diff --git a/workspace/TS100/Core/BSP/Miniware/UnitSettings.h b/workspace/TS100/Core/BSP/Miniware/UnitSettings.h index f3588b8b..46a1b78c 100644 --- a/workspace/TS100/Core/BSP/Miniware/UnitSettings.h +++ b/workspace/TS100/Core/BSP/Miniware/UnitSettings.h @@ -8,7 +8,7 @@ #ifndef BSP_MINIWARE_UNITSETTINGS_H_ #define BSP_MINIWARE_UNITSETTINGS_H_ //On the TS80, the LIS accel is mounted backwards -#ifdef MODEL_TS80 +#if defined(MODEL_TS80)+defined(MODEL_TS80P)>0 #define LIS_ORI_FLIP #endif diff --git a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp index 2e81642a..f342f8a7 100644 --- a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp +++ b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp @@ -20,7 +20,7 @@ void preRToSInit() { HAL_Delay(50); HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET); HAL_Delay(50); -#ifdef MODEL_TS80 +#ifdef MODEL_TS80P I2CBB::init(); //Spawn all of the USB-C processors fusb302_start_processing(); diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp index 6e57b9fc..df6e105f 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp @@ -42,7 +42,9 @@ static uint8_t fusb_read_byte(uint8_t addr) { * buf: The buffer into which data will be read */ static void fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) { - I2CBB::Mem_Read(FUSB302B_ADDR, addr, (uint8_t*) buf, size); + if(!I2CBB::Mem_Read(FUSB302B_ADDR, addr, (uint8_t*) buf, size)){ + asm("bkpt"); + } } @@ -54,7 +56,9 @@ static void fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) { * byte: The value to write */ static void fusb_write_byte(uint8_t addr, uint8_t byte) { - I2CBB::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &byte, 1); + if(!I2CBB::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &byte, 1)){ + asm("bkpt"); + } } @@ -67,7 +71,9 @@ static void fusb_write_byte(uint8_t addr, uint8_t byte) { * buf: The buffer to write */ static void fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) { - I2CBB::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &buf, size); + if(!I2CBB::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &buf, size)){ + asm("bkpt"); + } } diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp index 00b84e96..f6afe163 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -21,7 +21,7 @@ uint8_t fusb302_detect() { } void fusb302_start_processing() { - + HAL_Delay(30); /* Initialize the FUSB302B */ fusb_setup(); diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp index 648a7f4e..0f81f646 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp @@ -103,7 +103,7 @@ void ResetHandler::init() { void ResetHandler::notify(uint32_t notification) { xTaskNotify(TaskHandle, notification, - eNotifyAction::eSetValueWithOverwrite); + eNotifyAction::eSetBits); } void ResetHandler::Thread(const void *arg) { diff --git a/workspace/TS100/Core/Drivers/FUSB302/pd.h b/workspace/TS100/Core/Drivers/FUSB302/pd.h index c6b94c6c..e94e9cbe 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/pd.h +++ b/workspace/TS100/Core/Drivers/FUSB302/pd.h @@ -278,15 +278,13 @@ #define PD_T_PS_TRANSITION (500) #define PD_T_SENDER_RESPONSE (27) #define PD_T_SINK_REQUEST (100) -#define PD_T_TYPEC_SINK_WAIT_CAP (465) -#define PD_T_PPS_REQUEST TIME_S2I(10) -/* This is actually from Type-C, not Power Delivery, but who cares? */ +#define PD_T_TYPEC_SINK_WAIT_CAP (465+100) #define PD_T_PD_DEBOUNCE (15) /* * Counter maximums */ -#define PD_N_HARD_RESET_COUNT 2 +#define PD_N_HARD_RESET_COUNT 10 /* * Value parameters diff --git a/workspace/TS100/Core/Drivers/FUSB302/pdb_conf.h b/workspace/TS100/Core/Drivers/FUSB302/pdb_conf.h index ef733c3d..c2ca0f3f 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/pdb_conf.h +++ b/workspace/TS100/Core/Drivers/FUSB302/pdb_conf.h @@ -22,21 +22,6 @@ /* Number of messages in the message pool */ #define PDB_MSG_POOL_SIZE 4 -/* Size of the Policy Engine thread's working area */ -#define PDB_PE_WA_SIZE 256 - -/* Size of the protocol layer RX thread's working area */ -#define PDB_PRLRX_WA_SIZE 256 - -/* Size of the protocol layer TX thread's working area */ -#define PDB_PRLTX_WA_SIZE 256 - -/* Size of the protocol layer hard reset thread's working area */ -#define PDB_HARDRST_WA_SIZE 256 - -/* Size of the INT_N thread's working area */ -#define PDB_INT_N_WA_SIZE 128 - #define EVENT_MASK(x) (1<obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED @@ -108,6 +109,7 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability( // // return true; } +#endif } /* If there's a PDO in the voltage range, use it */ // int8_t i = dpm_get_range_fixed_pdo_index(caps, scfg); diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp index a3ebb2b2..14573aca 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp @@ -34,10 +34,12 @@ uint8_t ProtocolReceive::_tx_messageidcounter; */ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_wait_phy() { /* Wait for an event */ + _rx_messageid = 0; eventmask_t evt = waitForEvent(0xFFFFFFFF); /* If we got a reset event, reset */ if (evt & PDB_EVT_PRLRX_RESET) { + waitForEvent(PDB_EVT_PRLRX_RESET, 0); return PRLRxWaitPHY; } /* If we got an I_GCRCSENT event, read the message and decide what to do */ @@ -75,7 +77,7 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_reset() { taskYIELD(); /* If we got a RESET signal, reset the machine */ - if (waitForEvent(PDB_EVT_PRLRX_RESET) != 0) { + if (waitForEvent(PDB_EVT_PRLRX_RESET, 0) != 0) { return PRLRxWaitPHY; } @@ -88,17 +90,16 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_reset() { */ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_check_messageid() { /* If we got a RESET signal, reset the machine */ - if (waitForEvent(PDB_EVT_PRLRX_RESET) != 0) { - + if (waitForEvent(PDB_EVT_PRLRX_RESET, 0) == PDB_EVT_PRLRX_RESET) { return PRLRxWaitPHY; } - /* If the message has the stored ID, we've seen this message before. Free * it and don't pass it to the policy engine. */ + + /* Otherwise, there's either no stored ID or this message has an ID we + * haven't just seen. Transition to the Store_MessageID state. */ if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) { return PRLRxWaitPHY; - /* Otherwise, there's either no stored ID or this message has an ID we - * haven't just seen. Transition to the Store_MessageID state. */ } else { return PRLRxStoreMessageID; } @@ -160,12 +161,11 @@ void ProtocolReceive::thread(const void *args) { } void ProtocolReceive::notify(uint32_t notification) { - xTaskNotify(TaskHandle, notification, - eNotifyAction::eSetValueWithOverwrite); + xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits); } uint32_t ProtocolReceive::waitForEvent(uint32_t mask, uint32_t ticksToWait) { uint32_t pulNotificationValue; xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait); - return pulNotificationValue; + return pulNotificationValue & mask; } diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp index 759cb003..00fd8f02 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp @@ -45,7 +45,9 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_phy_reset() { /* Tell the policy engine that we failed */ PolicyEngine::notify( PDB_EVT_PE_TX_ERR); /* Finish failing to send the message */ - getMessage(); //Discard + while (messagePending()) { + getMessage(); //Discard + } } /* Wait for a message request */ @@ -103,7 +105,7 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_reset() { ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_message() { /* Make sure nobody wants us to reset */ eventmask_t evt = waitForEvent( - PDB_EVT_PRLTX_RESET | PDB_EVT_PRLTX_DISCARD); + PDB_EVT_PRLTX_RESET | PDB_EVT_PRLTX_DISCARD, 0); if (evt & PDB_EVT_PRLTX_RESET) { return PRLTxPHYReset; @@ -119,7 +121,7 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_mess /* PD 3.0 collision avoidance */ if (PolicyEngine::isPD3_0()) { /* If we're starting an AMS, wait for permission to transmit */ - evt = waitForEvent(PDB_EVT_PRLTX_START_AMS); + evt = waitForEvent(PDB_EVT_PRLTX_START_AMS, 0); if (evt & PDB_EVT_PRLTX_START_AMS) { while (fusb_get_typec_current() != fusb_sink_tx_ok) { osDelay(1); @@ -253,14 +255,14 @@ void ProtocolTransmit::thread(const void *args) { void ProtocolTransmit::notify(uint32_t notification) { xTaskNotify(TaskHandle, notification, - eNotifyAction::eSetValueWithOverwrite); + eNotifyAction::eSetBits); } void ProtocolTransmit::init() { messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue); - osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PRL, 0, TaskStackSize, + osThreadStaticDef(pd_txTask, thread,osPriorityAboveNormal, 0, TaskStackSize, TaskBuffer, &TaskControlBlock); TaskHandle = osThreadCreate(osThread(pd_txTask), NULL); } diff --git a/workspace/TS100/Core/Inc/power.hpp b/workspace/TS100/Core/Inc/power.hpp index c882a99a..31fddd33 100644 --- a/workspace/TS100/Core/Inc/power.hpp +++ b/workspace/TS100/Core/Inc/power.hpp @@ -9,6 +9,7 @@ #include #include "BSP.h" #include "expMovingAverage.h" +#include "../../configuration.h" #ifndef POWER_HPP_ #define POWER_HPP_ @@ -18,16 +19,6 @@ // This is necessary because of the temp noise and thermal lag in the system. // Once we have feed-forward temp estimation we should be able to better tune this. -#ifdef MODEL_TS100 -const int32_t tipMass = 45; // X10 watts to raise 1 deg C in 1 second -const uint8_t tipResistance = 85; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80 - -#endif -#ifdef MODEL_TS80 -const uint32_t tipMass = 40; -const uint8_t tipResistance = 45; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80 - -#endif const uint8_t wattHistoryFilter = 24; // I term look back weighting extern expMovingAverage x10WattHistory; diff --git a/workspace/TS100/Core/Src/main.cpp b/workspace/TS100/Core/Src/main.cpp index e8258523..023fd287 100644 --- a/workspace/TS100/Core/Src/main.cpp +++ b/workspace/TS100/Core/Src/main.cpp @@ -43,6 +43,8 @@ int main(void) { OLED::setFont(0); // default to bigger font // Testing for which accelerometer is mounted resetWatchdog(); + usb_pd_available = usb_pd_detect(); + resetWatchdog(); settingsWereReset = restoreSettings(); // load the settings from flash if (MMA8652FC::detect()) { PCBVersion = 1; @@ -58,8 +60,6 @@ int main(void) { systemSettings.sensitivity = 0; } resetWatchdog(); - usb_pd_available = usb_pd_detect(); - resetWatchdog(); /* Create the thread(s) */ /* definition and creation of GUITask */ diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index a9868318..ba6ba490 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -22,6 +22,7 @@ FRTOS_CMIS_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS FRTOS_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/include FRTOS_GCC_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3 DRIVER_INC_DIR =./Core/Drivers +FUSB_DRIVERS_INC_DIR = ./Core/Drivers/FUSB302 BSP_INC_DIR = ./Core/BSP MINIWARE_INC_DIR = ./Core/BSP/Miniware THREADS_INC_DIR = ./Core/Threads @@ -37,7 +38,8 @@ INCLUDES = -I$(APP_INC_DIR) \ -I$(DRIVER_INC_DIR) \ -I$(BSP_INC_DIR) \ -I$(MINIWARE_INC_DIR) \ - -I$(THREADS_INC_DIR) + -I$(THREADS_INC_DIR) \ + -I$(FUSB_DRIVERS_INC_DIR) # output folder HEXFILE_DIR=Hexfile diff --git a/workspace/TS100/configuration.h b/workspace/TS100/configuration.h index 1bdc13d0..66688f12 100644 --- a/workspace/TS100/configuration.h +++ b/workspace/TS100/configuration.h @@ -76,7 +76,6 @@ #define DETAILED_SOLDERING 0 // 0: Disable 1: Enable - Default 0 #define DETAILED_IDLE 0 // 0: Disable 1: Enable - Default 0 - #define CUT_OUT_SETTING 0 // default to no cut-off voltage (or 18W for TS80) #define TEMPERATURE_INF 0 // default to 0 #define DESCRIPTION_SCROLL_SPEED 0 // 0: Slow 1: Fast - default to slow @@ -94,6 +93,10 @@ #define OP_AMP_GAIN_STAGE_TS80 (1+(OP_AMP_Rf_TS80/OP_AMP_Rin_TS80)) +//Deriving the Voltage div: +// Vin_max = (3.3*(r1+r2))/(r2) +//vdiv = (32768*4)/(vin_max*10) + #ifdef MODEL_TS100 #define VOLTAGE_DIV 467 // 467 - Default divider from schematic #define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV @@ -105,11 +108,39 @@ #endif #ifdef MODEL_TS80 - #define VOLTAGE_DIV 780 // Default divider from schematic - #define PID_POWER_LIMIT 24 // Sets the max pwm power limit - #define CALIBRATION_OFFSET 900 // the adc offset in uV - #define POWER_LIMIT 24 // 24 watts default power limit - #define MAX_POWER_LIMIT 30 // - #define POWER_LIMIT_STEPS 2 - #define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80 +#define VOLTAGE_DIV_TS80P 768 // Default for TS80P with slightly different resistors +#define VOLTAGE_DIV 780 // Default divider from schematic +#define PID_POWER_LIMIT 24 // Sets the max pwm power limit +#define CALIBRATION_OFFSET 900 // the adc offset in uV +#define POWER_LIMIT 24 // 24 watts default power limit +#define MAX_POWER_LIMIT 30 // +#define POWER_LIMIT_STEPS 2 +#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80 +#endif + +#ifdef MODEL_TS80P +#define VOLTAGE_DIV 768 // Default for TS80P with slightly different resistors +#define PID_POWER_LIMIT 30 // Sets the max pwm power limit +#define CALIBRATION_OFFSET 900 // the adc offset in uV +#define POWER_LIMIT 24 // 24 watts default power limit +#define MAX_POWER_LIMIT 30 // +#define POWER_LIMIT_STEPS 2 +#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80 +#endif + + + +#ifdef MODEL_TS100 +const int32_t tipMass = 45; // X10 watts to raise 1 deg C in 1 second +const uint8_t tipResistance = 85; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80 +#endif + +#ifdef MODEL_TS80 +const uint32_t tipMass = 40; +const uint8_t tipResistance = 45; //x10 ohms, 4.5 typical for ts80 tips +#endif + +#ifdef MODEL_TS80P +const uint32_t tipMass = 40; +const uint8_t tipResistance = 45; //x10 ohms, 4.5 typical for ts80 tips #endif From 4c2fb11d3269b8e43ef0ef51e087e0bd07c10e5d Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 16 Jun 2020 21:25:28 +1000 Subject: [PATCH 10/53] Filter returned WFE --- workspace/TS100/Core/BSP/Miniware/Power.cpp | 24 ++++++++----------- .../TS100/Core/Drivers/FUSB302/hard_reset.cpp | 4 ++-- .../TS100/Core/Drivers/FUSB302/int_n.cpp | 2 ++ workspace/TS100/Core/Drivers/FUSB302/pd.h | 2 +- .../Core/Drivers/FUSB302/policy_engine.cpp | 7 +++--- .../Core/Drivers/FUSB302/protocol_rx.cpp | 6 +++-- .../Core/Drivers/FUSB302/protocol_tx.cpp | 9 ++++--- workspace/TS100/Core/Src/main.cpp | 16 ++++++------- 8 files changed, 35 insertions(+), 35 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/Power.cpp b/workspace/TS100/Core/BSP/Miniware/Power.cpp index 3faeedb5..d65c5d4f 100644 --- a/workspace/TS100/Core/BSP/Miniware/Power.cpp +++ b/workspace/TS100/Core/BSP/Miniware/Power.cpp @@ -8,7 +8,7 @@ bool FUSB302_present = false; void power_probe() { // If TS80 probe for QC // If TS100 - noop -#ifdef defined(MODEL_TS80)+defined(MODEL_TS80P)>0 +#if defined(MODEL_TS80)+defined(MODEL_TS80P)>0 startQC(systemSettings.voltageDiv); seekQC((systemSettings.cutoutSetting) ? 120 : 90, @@ -18,31 +18,27 @@ void power_probe() { } void power_check() { -#ifdef defined(MODEL_TS80)+defined(MODEL_TS80P)>0 +#if defined(MODEL_TS80)+defined(MODEL_TS80P)>0 QC_resync(); #endif } uint8_t usb_pd_detect() { #ifdef MODEL_TS80P FUSB302_present = fusb302_detect(); - if (FUSB302_present) { - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; - GPIO_InitStruct.Pin = GPIO_PIN_9; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_PULLUP; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); return FUSB302_present; #endif return false; } uint8_t pd_irq_read() { #ifdef MODEL_TS80P - if (FUSB302_present) { - return HAL_GPIO_ReadPin(INT_PD_GPIO_Port, INT_PD_Pin) == GPIO_PIN_SET ? - 1 : 0; - } + return HAL_GPIO_ReadPin(INT_PD_GPIO_Port, INT_PD_Pin) == GPIO_PIN_SET ? + 1 : 0; #endif return 0; } diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp index 0f81f646..772aa6b6 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp @@ -37,11 +37,11 @@ ResetHandler::hardrst_state ResetHandler::hardrst_reset_layer() { /* Reset the Protocol RX machine */ ProtocolReceive::notify( PDB_EVT_PRLRX_RESET); - taskYIELD(); + osDelay(1); /* Reset the Protocol TX machine */ ProtocolTransmit::notify(PDB_EVT_PRLTX_RESET); - taskYIELD(); + osDelay(1); /* Continue the process based on what event started the reset. */ if (evt & PDB_EVT_HARDRST_RESET) { diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index 58ea1b9d..d2329226 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -91,6 +91,8 @@ void InterruptHandler::Thread(const void *arg) { } } + } else { + osDelay(1); } osDelay(1); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/pd.h b/workspace/TS100/Core/Drivers/FUSB302/pd.h index e94e9cbe..7bd754b5 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/pd.h +++ b/workspace/TS100/Core/Drivers/FUSB302/pd.h @@ -278,7 +278,7 @@ #define PD_T_PS_TRANSITION (500) #define PD_T_SENDER_RESPONSE (27) #define PD_T_SINK_REQUEST (100) -#define PD_T_TYPEC_SINK_WAIT_CAP (465+100) +#define PD_T_TYPEC_SINK_WAIT_CAP (465) #define PD_T_PD_DEBOUNCE (15) /* diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp index 1a0b9e23..7adf5cd3 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -54,8 +54,7 @@ void PolicyEngine::init() { } void PolicyEngine::notify(uint32_t notification) { - xTaskNotify(TaskHandle, notification, - eNotifyAction::eSetBits); + xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits); } void PolicyEngine::pe_task(const void *arg) { @@ -242,6 +241,8 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_eval_cap() { } PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { + waitForEvent( + PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET, 0); /* Transmit the request */ ProtocolTransmit::pushMessage(&_last_dpm_request); //Send indication that there is a message pending @@ -785,7 +786,7 @@ bool PolicyEngine::heatingAllowed() { uint32_t PolicyEngine::waitForEvent(uint32_t mask, uint32_t ticksToWait) { uint32_t pulNotificationValue; xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait); - return pulNotificationValue; + return pulNotificationValue & mask; } bool PolicyEngine::isPD3_0() { diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp index 14573aca..26117da5 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp @@ -98,9 +98,11 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_check_messageid( /* Otherwise, there's either no stored ID or this message has an ID we * haven't just seen. Transition to the Store_MessageID state. */ - if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) { + /*if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) { return PRLRxWaitPHY; - } else { + } else*/ + + { return PRLRxStoreMessageID; } } diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp index 00fd8f02..43c8a945 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp @@ -254,16 +254,15 @@ void ProtocolTransmit::thread(const void *args) { } void ProtocolTransmit::notify(uint32_t notification) { - xTaskNotify(TaskHandle, notification, - eNotifyAction::eSetBits); + xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits); } void ProtocolTransmit::init() { messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue); - osThreadStaticDef(pd_txTask, thread,osPriorityAboveNormal, 0, TaskStackSize, - TaskBuffer, &TaskControlBlock); + osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PRL, 0, + TaskStackSize, TaskBuffer, &TaskControlBlock); TaskHandle = osThreadCreate(osThread(pd_txTask), NULL); } @@ -283,5 +282,5 @@ void ProtocolTransmit::getMessage() { uint32_t ProtocolTransmit::waitForEvent(uint32_t mask, uint32_t ticksToWait) { uint32_t pulNotificationValue; xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait); - return pulNotificationValue; + return pulNotificationValue & mask; } diff --git a/workspace/TS100/Core/Src/main.cpp b/workspace/TS100/Core/Src/main.cpp index 023fd287..78a7d5d9 100644 --- a/workspace/TS100/Core/Src/main.cpp +++ b/workspace/TS100/Core/Src/main.cpp @@ -46,14 +46,14 @@ int main(void) { usb_pd_available = usb_pd_detect(); resetWatchdog(); settingsWereReset = restoreSettings(); // load the settings from flash - if (MMA8652FC::detect()) { - PCBVersion = 1; - MMA8652FC::initalize(); // this sets up the I2C registers - } else if (LIS2DH12::detect()) { - PCBVersion = 2; - // Setup the ST Accelerometer - LIS2DH12::initalize(); // startup the accelerometer - } else { + /*if (MMA8652FC::detect()) { + PCBVersion = 1; + MMA8652FC::initalize(); // this sets up the I2C registers + } else if (LIS2DH12::detect()) { + PCBVersion = 2; + // Setup the ST Accelerometer + LIS2DH12::initalize(); // startup the accelerometer + } else*/{ PCBVersion = 3; systemSettings.SleepTime = 0; systemSettings.ShutdownTime = 0; // No accel -> disable sleep From 6d2361767018d624f4431f15e9aa60aca5d6423d Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 17 Jun 2020 18:14:17 +1000 Subject: [PATCH 11/53] IRQ int --- workspace/TS100/Core/BSP/Miniware/I2CBB.cpp | 8 +- workspace/TS100/Core/BSP/Miniware/IRQ.cpp | 5 + workspace/TS100/Core/BSP/Miniware/IRQ.h | 1 + .../TS100/Core/Drivers/FUSB302/int_n.cpp | 97 +++++++++---------- workspace/TS100/Core/Drivers/FUSB302/int_n.h | 3 +- 5 files changed, 61 insertions(+), 53 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp index ef19db03..c7c04c4f 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp @@ -13,7 +13,7 @@ #define SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET) #define SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0) #define SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0) -#define I2C_DELAY() {for(int xx=0;xx<700;xx++){asm("nop");}} +#define I2C_DELAY() {for(int xx=0;xx<100;xx++){asm("nop");}} SemaphoreHandle_t I2CBB::I2CSemaphore = NULL; StaticSemaphore_t I2CBB::xSemaphoreBuffer; void I2CBB::init() { @@ -269,7 +269,11 @@ bool I2CBB::lock() { if (I2CSemaphore == NULL) { asm("bkpt"); } - return xSemaphoreTake(I2CSemaphore, (TickType_t) 50) == pdTRUE; + bool a = xSemaphoreTake(I2CSemaphore, (TickType_t) 50) == pdTRUE; + if (!a) { + asm("bkpt"); + } + return a; } void I2CBB::write_bit(uint8_t val) { diff --git a/workspace/TS100/Core/BSP/Miniware/IRQ.cpp b/workspace/TS100/Core/BSP/Miniware/IRQ.cpp index eac8cdbc..15d26b64 100644 --- a/workspace/TS100/Core/BSP/Miniware/IRQ.cpp +++ b/workspace/TS100/Core/BSP/Miniware/IRQ.cpp @@ -6,6 +6,7 @@ */ #include "IRQ.h" +#include "int_n.h" /* * Catch the IRQ that says that the conversion is done on the temperature * readings coming in Once these have come in we can unblock the PID so that it @@ -41,3 +42,7 @@ void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c __unused) { void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); } + +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { + InterruptHandler::irqCallback(); +} diff --git a/workspace/TS100/Core/BSP/Miniware/IRQ.h b/workspace/TS100/Core/BSP/Miniware/IRQ.h index 09d79c36..bcd42d04 100644 --- a/workspace/TS100/Core/BSP/Miniware/IRQ.h +++ b/workspace/TS100/Core/BSP/Miniware/IRQ.h @@ -24,6 +24,7 @@ void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c); void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c); void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c); void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_GPIO_EXTI_Callback(uint16_t); #ifdef __cplusplus } diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index d2329226..32d020fc 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -41,59 +41,56 @@ void InterruptHandler::Thread(const void *arg) { (void) arg; union fusb_status status; eventmask_t events; - //TODO use IRQ task notification to unblock this thread to stop it spinning while (true) { /* If the INT_N line is low */ - if (pd_irq_read() == 0) { - /* Read the FUSB302B status and interrupt registers */ - fusb_get_status(&status); - //Check for rx alerts - { - /* If the I_GCRCSENT flag is set, tell the Protocol RX thread */ - if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) { - ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT); - } - } - /* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX - * thread */ - { - events = 0; - if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) { - events |= PDB_EVT_PRLTX_I_RETRYFAIL; - } - if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) { - events |= PDB_EVT_PRLTX_I_TXSENT; - } - if (events) { - ProtocolTransmit::notify(events); - } - } - /* If the I_HARDRST or I_HARDSENT flag is set, tell the Hard Reset - * thread */ - { - events = 0; - if (status.interrupta & FUSB_INTERRUPTA_I_HARDRST) { - events |= PDB_EVT_HARDRST_I_HARDRST; - } - if (status.interrupta & FUSB_INTERRUPTA_I_HARDSENT) { - events |= PDB_EVT_HARDRST_I_HARDSENT; - } - if (events) { - ResetHandler::notify(events); - } - } - { - /* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy - * Engine thread */ - if (status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP - && status.status1 & FUSB_STATUS1_OVRTEMP) { - PolicyEngine::notify(PDB_EVT_PE_I_OVRTEMP); - } - } + xTaskNotifyWait(0x00, 0x0F, NULL, 5); + /* Read the FUSB302B status and interrupt registers */ + fusb_get_status(&status); + //Check for rx alerts - } else { - osDelay(1); + /* If the I_GCRCSENT flag is set, tell the Protocol RX thread */ + if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) { + ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT); } - osDelay(1); + + /* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX + * thread */ + + events = 0; + if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) { + events |= PDB_EVT_PRLTX_I_RETRYFAIL; + } + if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) { + events |= PDB_EVT_PRLTX_I_TXSENT; + } + if (events) { + ProtocolTransmit::notify(events); + } + + /* If the I_HARDRST or I_HARDSENT flag is set, tell the Hard Reset + * thread */ + + events = 0; + if (status.interrupta & FUSB_INTERRUPTA_I_HARDRST) { + events |= PDB_EVT_HARDRST_I_HARDRST; + } + if (status.interrupta & FUSB_INTERRUPTA_I_HARDSENT) { + events |= PDB_EVT_HARDRST_I_HARDSENT; + } + if (events) { + ResetHandler::notify(events); + } + + /* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy + * Engine thread */ + if (status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP + && status.status1 & FUSB_STATUS1_OVRTEMP) { + PolicyEngine::notify(PDB_EVT_PE_I_OVRTEMP); + } + } } + +void InterruptHandler::irqCallback() { + xTaskNotify(TaskHandle, 0x0F, eNotifyAction::eSetBits); +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.h b/workspace/TS100/Core/Drivers/FUSB302/int_n.h index 68dc04d8..e168171e 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.h +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.h @@ -24,8 +24,9 @@ class InterruptHandler { public: //Creates the thread to handle the Interrupt pin static void init(); - //TODO handle irq callbacks instead of polling the pin + + static void irqCallback(); private: static void Thread(const void *arg); static osThreadId TaskHandle; From c55b91af6a5cef2cfe1f764f0433a6be18f4fdd1 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 17 Jun 2020 18:15:16 +1000 Subject: [PATCH 12/53] static state --- workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp | 3 ++- workspace/TS100/Core/Drivers/FUSB302/policy_engine.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp index 7adf5cd3..22b76589 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -40,6 +40,7 @@ uint32_t PolicyEngine::TaskBuffer[PolicyEngine::TaskStackSize]; osStaticThreadDef_t PolicyEngine::TaskControlBlock; union pd_msg PolicyEngine::tempMessage; union pd_msg PolicyEngine::_last_dpm_request; +PolicyEngine::policy_engine_state PolicyEngine::state = PESinkStartup; StaticQueue_t PolicyEngine::xStaticQueue; uint8_t PolicyEngine::ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)]; @@ -67,7 +68,7 @@ void PolicyEngine::pe_task(const void *arg) { _pps_index = 8; /* Initialize the last_pps */ _last_pps = 8; - PolicyEngine::policy_engine_state state = PESinkStartup; + for (;;) { //Loop based on state switch (state) { diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h index 781158ed..8e4de84a 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h @@ -121,6 +121,7 @@ private: static osStaticThreadDef_t TaskControlBlock; static union pd_msg tempMessage; static union pd_msg _last_dpm_request; + static policy_engine_state state; //queue of up to PDB_MSG_POOL_SIZE messages to send static StaticQueue_t xStaticQueue; /* The array to use as the queue's storage area. This must be at least From 12e8d2a93df0db11b7af6f2ef1660f2551772f2f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 17 Jun 2020 18:15:22 +1000 Subject: [PATCH 13/53] Update hard_reset.cpp --- workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp index 772aa6b6..3e3540ac 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp @@ -37,12 +37,10 @@ ResetHandler::hardrst_state ResetHandler::hardrst_reset_layer() { /* Reset the Protocol RX machine */ ProtocolReceive::notify( PDB_EVT_PRLRX_RESET); - osDelay(1); - + taskYIELD(); /* Reset the Protocol TX machine */ ProtocolTransmit::notify(PDB_EVT_PRLTX_RESET); - osDelay(1); - + taskYIELD(); /* Continue the process based on what event started the reset. */ if (evt & PDB_EVT_HARDRST_RESET) { /* Policy Engine started the reset. */ @@ -96,7 +94,7 @@ ResetHandler::hardrst_state ResetHandler::hardrst_complete() { } void ResetHandler::init() { - osThreadStaticDef(Task, Thread, PDB_PRIO_PE, 0, TaskStackSize, TaskBuffer, + osThreadStaticDef(Task, Thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, &TaskControlBlock); TaskHandle = osThreadCreate(osThread(Task), NULL); } From 43b79476455a9b45eb7c912515693035e6df3c0b Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 17 Jun 2020 18:15:27 +1000 Subject: [PATCH 14/53] Update fusbpd.cpp --- workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp index f6afe163..b4b1fafb 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -21,10 +21,8 @@ uint8_t fusb302_detect() { } void fusb302_start_processing() { - HAL_Delay(30); /* Initialize the FUSB302B */ fusb_setup(); - /* Create the policy engine thread. */ PolicyEngine::init(); From c70689df7d36a9ecb462a7994d52b3c5f7070171 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 17 Jun 2020 18:22:43 +1000 Subject: [PATCH 15/53] Hook up IRQ --- workspace/TS100/Core/BSP/Miniware/Power.cpp | 6 +++++- workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/workspace/TS100/Core/BSP/Miniware/Power.cpp b/workspace/TS100/Core/BSP/Miniware/Power.cpp index d65c5d4f..b188e31c 100644 --- a/workspace/TS100/Core/BSP/Miniware/Power.cpp +++ b/workspace/TS100/Core/BSP/Miniware/Power.cpp @@ -4,6 +4,7 @@ #include "Settings.h" #include "Pins.h" #include "fusbpd.h" +#include "int_n.h" bool FUSB302_present = false; void power_probe() { // If TS80 probe for QC @@ -28,9 +29,12 @@ uint8_t usb_pd_detect() { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; GPIO_InitStruct.Pin = GPIO_PIN_9; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + HAL_NVIC_SetPriority(EXTI9_5_IRQn, 15, 0); + HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); + InterruptHandler::irqCallback(); return FUSB302_present; #endif return false; diff --git a/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c b/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c index b411c980..b9ee5c51 100644 --- a/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c +++ b/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c @@ -82,3 +82,6 @@ void DMA1_Channel6_IRQHandler(void) { void DMA1_Channel7_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_i2c1_rx); } +void EXTI9_5_IRQHandler(void){ + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9); +} From b6c61cfb525dfd647c59c46f043d3479f36835bc Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 21 Jul 2020 13:39:50 +1000 Subject: [PATCH 16/53] Still testing --- workspace/TS100/Core/BSP/Miniware/BSP.cpp | 1 + workspace/TS100/Core/BSP/Miniware/I2CBB.cpp | 41 +- workspace/TS100/Core/BSP/Miniware/I2CBB.hpp | 6 +- workspace/TS100/Core/BSP/Miniware/Power.cpp | 10 +- workspace/TS100/Core/BSP/Miniware/Setup.c | 13 +- .../Core/BSP/Miniware/system_stm32f1xx.c | 1 + .../TS100/Core/Drivers/FUSB302/fusb302b.cpp | 114 ++- .../TS100/Core/Drivers/FUSB302/fusb302b.h | 2 + .../TS100/Core/Drivers/FUSB302/fusbpd.cpp | 3 +- .../TS100/Core/Drivers/FUSB302/hard_reset.cpp | 33 +- .../TS100/Core/Drivers/FUSB302/hard_reset.h | 2 +- .../TS100/Core/Drivers/FUSB302/int_n.cpp | 42 +- workspace/TS100/Core/Drivers/FUSB302/int_n.h | 2 +- workspace/TS100/Core/Drivers/FUSB302/pd.h | 16 +- .../Core/Drivers/FUSB302/policy_engine.cpp | 41 +- .../Core/Drivers/FUSB302/policy_engine.h | 2 +- .../Core/Drivers/FUSB302/protocol_rx.cpp | 21 +- .../TS100/Core/Drivers/FUSB302/protocol_rx.h | 2 +- .../Core/Drivers/FUSB302/protocol_tx.cpp | 55 +- .../TS100/Core/Drivers/FUSB302/protocol_tx.h | 24 +- workspace/TS100/Core/Drivers/OLED.cpp | 2 +- .../TS100/Core/Drivers/TipThermoModel.cpp | 5 +- workspace/TS100/Core/Inc/FreeRTOSConfig.h | 4 +- workspace/TS100/Core/Inc/stm32f1xx_hal_conf.h | 729 +++++++++--------- workspace/TS100/Core/Src/FreeRTOSHooks.c | 1 + workspace/TS100/Core/Src/QC3.c | 18 +- workspace/TS100/Core/Src/gui.cpp | 18 +- workspace/TS100/Core/Src/main.cpp | 10 +- workspace/TS100/Core/Threads/GUIThread.cpp | 8 +- workspace/TS100/LinkerScript.ld | 4 +- workspace/TS100/configuration.h | 1 - 31 files changed, 674 insertions(+), 557 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/BSP.cpp b/workspace/TS100/Core/BSP/Miniware/BSP.cpp index 760c7afd..df32c8e2 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP.cpp +++ b/workspace/TS100/Core/BSP/Miniware/BSP.cpp @@ -217,6 +217,7 @@ uint8_t getButtonB() { } void reboot() { + asm("bkpt"); NVIC_SystemReset(); } diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp index c7c04c4f..27ce6811 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp @@ -13,9 +13,11 @@ #define SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET) #define SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0) #define SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0) -#define I2C_DELAY() {for(int xx=0;xx<100;xx++){asm("nop");}} +#define I2C_DELAY() {for(int xx=0;xx<1000;xx++){asm("nop");}} SemaphoreHandle_t I2CBB::I2CSemaphore = NULL; StaticSemaphore_t I2CBB::xSemaphoreBuffer; +SemaphoreHandle_t I2CBB::I2CSemaphore2 = NULL; +StaticSemaphore_t I2CBB::xSemaphoreBuffer2; void I2CBB::init() { //Set GPIO's to output open drain GPIO_InitTypeDef GPIO_InitStruct; @@ -28,8 +30,14 @@ void I2CBB::init() { SDA_HIGH(); SCL_HIGH(); I2CSemaphore = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer); - xSemaphoreGive(I2CSemaphore); + I2CSemaphore2 = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer2); unlock(); + unlock2(); + //unstick bus + for (int i = 0; i < 8; i++) { + read_bit(); + } + stop(); } bool I2CBB::probe(uint8_t address) { @@ -73,8 +81,8 @@ bool I2CBB::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, return true; } -bool I2CBB::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, - uint16_t Size) { +bool I2CBB::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, + const uint8_t *pData, uint16_t Size) { if (!lock()) return false; start(); @@ -205,6 +213,7 @@ void I2CBB::start() { I2C_DELAY(); SCL_LOW(); I2C_DELAY(); + SDA_HIGH(); } void I2CBB::stop() { @@ -224,6 +233,7 @@ bool I2CBB::send(uint8_t value) { value <<= 1; } + SDA_HIGH(); bool ack = read_bit() == 0; return ack; } @@ -237,6 +247,7 @@ uint8_t I2CBB::read(bool ack) { B |= read_bit(); } + SDA_HIGH(); if (ack) write_bit(0); else @@ -269,7 +280,7 @@ bool I2CBB::lock() { if (I2CSemaphore == NULL) { asm("bkpt"); } - bool a = xSemaphoreTake(I2CSemaphore, (TickType_t) 50) == pdTRUE; + bool a = xSemaphoreTake(I2CSemaphore, (TickType_t) 100) == pdTRUE; if (!a) { asm("bkpt"); } @@ -277,13 +288,29 @@ bool I2CBB::lock() { } void I2CBB::write_bit(uint8_t val) { - if (val > 0) + if (val) { SDA_HIGH(); - else + } else { SDA_LOW(); + } I2C_DELAY(); SCL_HIGH(); I2C_DELAY(); SCL_LOW(); } + +void I2CBB::unlock2() { + xSemaphoreGive(I2CSemaphore2); +} + +bool I2CBB::lock2() { + if (I2CSemaphore2 == NULL) { + asm("bkpt"); + } + bool a = xSemaphoreTake(I2CSemaphore2, (TickType_t) 500) == pdTRUE; + if (!a) { + asm("bkpt"); + } + return a; +} diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp index 8c67cd19..213dd9c1 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp @@ -27,14 +27,18 @@ public: uint8_t *pData, uint16_t Size); //Implements a register write static bool Mem_Write(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size); + const uint8_t *pData, uint16_t Size); static void Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size); static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size); static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); + static void unlock2(); + static bool lock2(); private: static SemaphoreHandle_t I2CSemaphore; static StaticSemaphore_t xSemaphoreBuffer; + static SemaphoreHandle_t I2CSemaphore2; + static StaticSemaphore_t xSemaphoreBuffer2; static void unlock(); static bool lock(); static void start(); diff --git a/workspace/TS100/Core/BSP/Miniware/Power.cpp b/workspace/TS100/Core/BSP/Miniware/Power.cpp index b188e31c..8340fa7f 100644 --- a/workspace/TS100/Core/BSP/Miniware/Power.cpp +++ b/workspace/TS100/Core/BSP/Miniware/Power.cpp @@ -26,15 +26,7 @@ void power_check() { uint8_t usb_pd_detect() { #ifdef MODEL_TS80P FUSB302_present = fusb302_detect(); - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; - GPIO_InitStruct.Pin = GPIO_PIN_9; - GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; - GPIO_InitStruct.Pull = GPIO_PULLUP; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - HAL_NVIC_SetPriority(EXTI9_5_IRQn, 15, 0); - HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); - InterruptHandler::irqCallback(); + return FUSB302_present; #endif return false; diff --git a/workspace/TS100/Core/BSP/Miniware/Setup.c b/workspace/TS100/Core/BSP/Miniware/Setup.c index 4b3d1f5b..ca1f82f5 100644 --- a/workspace/TS100/Core/BSP/Miniware/Setup.c +++ b/workspace/TS100/Core/BSP/Miniware/Setup.c @@ -33,9 +33,9 @@ static void MX_ADC2_Init(void); void Setup_HAL() { SystemClock_Config(); - __HAL_AFIO_REMAP_SWJ_DISABLE() - ; - +// __HAL_AFIO_REMAP_SWJ_DISABLE() +// ; + __HAL_AFIO_REMAP_SWJ_NOJTAG(); MX_GPIO_Init(); MX_DMA_Init(); MX_I2C1_Init(); @@ -43,7 +43,7 @@ void Setup_HAL() { MX_ADC2_Init(); MX_TIM3_Init(); MX_TIM2_Init(); - MX_IWDG_Init(); +// MX_IWDG_Init(); HAL_ADC_Start(&hadc2); HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*) ADCReadings, 64); // start DMA of normal readings HAL_ADCEx_InjectedStart(&hadc1); // enable injected readings @@ -458,3 +458,8 @@ static void MX_GPIO_Init(void) { HAL_Delay(30); HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET); } +#ifdef USE_FULL_ASSERT +void assert_failed(uint8_t* file, uint32_t line){ + asm("bkpt"); +} +#endif diff --git a/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c b/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c index dfff3485..6af48671 100644 --- a/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c +++ b/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c @@ -11,6 +11,7 @@ #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) /* #define DATA_IN_ExtSRAM */ #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ +#define LOCAL_BUILD #ifndef LOCAL_BUILD #define VECT_TAB_OFFSET 0x00004000U /*!< Vector Table base offset field. This value must be a multiple of 0x200. */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp index df6e105f..9895e99e 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp @@ -18,7 +18,7 @@ #include "fusb302b.h" #include "I2CBB.hpp" #include - +#include "int_n.h" /* * Read a single byte from the FUSB302B * @@ -29,7 +29,9 @@ */ static uint8_t fusb_read_byte(uint8_t addr) { uint8_t data[1]; - I2CBB::Mem_Read(FUSB302B_ADDR, addr, (uint8_t*) data, 1); + if (!I2CBB::Mem_Read(FUSB302B_ADDR, addr, (uint8_t*) data, 1)) { + asm("bkpt"); + } return data[0]; } @@ -41,11 +43,8 @@ static uint8_t fusb_read_byte(uint8_t addr) { * size: The number of bytes to read * buf: The buffer into which data will be read */ -static void fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) { - if(!I2CBB::Mem_Read(FUSB302B_ADDR, addr, (uint8_t*) buf, size)){ - asm("bkpt"); - } - +static bool fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) { + return I2CBB::Mem_Read(FUSB302B_ADDR, addr, buf, size); } /* @@ -55,11 +54,8 @@ static void fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) { * addr: The memory address to which we will write * byte: The value to write */ -static void fusb_write_byte(uint8_t addr, uint8_t byte) { - if(!I2CBB::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &byte, 1)){ - asm("bkpt"); - } - +static bool fusb_write_byte(uint8_t addr, uint8_t byte) { + return I2CBB::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &byte, 1); } /* @@ -70,14 +66,12 @@ static void fusb_write_byte(uint8_t addr, uint8_t byte) { * size: The number of bytes to write * buf: The buffer to write */ -static void fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) { - if(!I2CBB::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &buf, size)){ - asm("bkpt"); - } - +static bool fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) { + return I2CBB::Mem_Write(FUSB302B_ADDR, addr, buf, size); } void fusb_send_message(const union pd_msg *msg) { + /* Token sequences for the FUSB302B */ static uint8_t sop_seq[5] = { FUSB_FIFO_TX_SOP1, @@ -98,16 +92,23 @@ void fusb_send_message(const union pd_msg *msg) { /* Set the number of bytes to be transmitted in the packet */ sop_seq[4] = FUSB_FIFO_TX_PACKSYM | msg_len; - + if (!I2CBB::lock2()) { + asm("bkpt"); + } /* Write all three parts of the message to the TX FIFO */ fusb_write_buf( FUSB_FIFOS, 5, sop_seq); fusb_write_buf( FUSB_FIFOS, msg_len, msg->bytes); fusb_write_buf( FUSB_FIFOS, 4, eop_seq); + I2CBB::unlock2(); + } uint8_t fusb_read_message(union pd_msg *msg) { - uint8_t garbage[4]; + if (!I2CBB::lock2()) { + asm("bkpt"); + } + static uint8_t garbage[4]; uint8_t numobj; /* If this isn't an SOP message, return error. @@ -115,6 +116,8 @@ uint8_t fusb_read_message(union pd_msg *msg) { * buffer is empty, and not try to read past a non-SOP message. */ if ((fusb_read_byte( FUSB_FIFOS) & FUSB_FIFO_RX_TOKEN_BITS) != FUSB_FIFO_RX_SOP) { + + I2CBB::unlock2(); return 1; } /* Read the message header into msg */ @@ -128,33 +131,56 @@ uint8_t fusb_read_message(union pd_msg *msg) { /* Throw the CRC32 in the garbage, since the PHY already checked it. */ fusb_read_buf( FUSB_FIFOS, 4, garbage); + I2CBB::unlock2(); return 0; } void fusb_send_hardrst() { + if (!I2CBB::lock2()) { + asm("bkpt"); + } /* Send a hard reset */ fusb_write_byte( FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET); + I2CBB::unlock2(); } void fusb_setup() { + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + HAL_NVIC_SetPriority(EXTI9_5_IRQn, 10, 0); + HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + if (!I2CBB::lock2()) { + asm("bkpt"); + } + } /* Fully reset the FUSB302B */ fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES); - + delay_ms(2); + if (!fusb_read_id()) { + asm("bkpt"); + } /* Turn on all power */ fusb_write_byte( FUSB_POWER, 0x0F); /* Set interrupt masks */ + //Setting to 0 so interrupts are allowed fusb_write_byte( FUSB_MASK1, 0x00); fusb_write_byte( FUSB_MASKA, 0x00); fusb_write_byte( FUSB_MASKB, 0x00); - fusb_write_byte( FUSB_CONTROL0, 0x04); + fusb_write_byte( FUSB_CONTROL0, 0b11 << 2); /* Enable automatic retransmission */ fusb_write_byte( FUSB_CONTROL3, 0x07); - + //set defaults + fusb_write_byte( FUSB_CONTROL2, 0x00); /* Flush the RX buffer */ fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); @@ -184,29 +210,48 @@ void fusb_setup() { fusb_write_byte( FUSB_SWITCHES0, 0x0B); } resetWatchdog(); - - /* Reset the PD logic */ - fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); - + fusb_reset(); + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + I2CBB::unlock2(); + } } void fusb_get_status(union fusb_status *status) { + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + if (!I2CBB::lock2()) { + asm("bkpt"); + } + } /* Read the interrupt and status flags into status */ fusb_read_buf( FUSB_STATUS0A, 7, status->bytes); + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + I2CBB::unlock2(); + } } enum fusb_typec_current fusb_get_typec_current() { - + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + if (!I2CBB::lock2()) { + asm("bkpt"); + } + } /* Read the BC_LVL into a variable */ enum fusb_typec_current bc_lvl = (enum fusb_typec_current) (fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL); - + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + I2CBB::unlock2(); + } return bc_lvl; } void fusb_reset() { + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + if (!I2CBB::lock2()) { + asm("bkpt"); + } + } /* Flush the TX buffer */ fusb_write_byte( FUSB_CONTROL0, 0x44); @@ -214,5 +259,16 @@ void fusb_reset() { fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); /* Reset the PD logic */ fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); - + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + I2CBB::unlock2(); + } +} + +bool fusb_read_id() { + //Return true if read of the revision ID is sane + uint8_t version = 0; + fusb_read_buf(FUSB_DEVICE_ID, 1, &version); + if (version == 0 || version == 0xFF) + return false; + return true; } diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h index d11979a9..bcd66407 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h +++ b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h @@ -300,4 +300,6 @@ void fusb_setup(); */ void fusb_reset(); +bool fusb_read_id(); + #endif /* PDB_FUSB302B_H */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp index b4b1fafb..03dc87b5 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -23,6 +23,7 @@ uint8_t fusb302_detect() { void fusb302_start_processing() { /* Initialize the FUSB302B */ fusb_setup(); + resetWatchdog(); /* Create the policy engine thread. */ PolicyEngine::init(); @@ -30,7 +31,7 @@ void fusb302_start_processing() { ProtocolReceive::init(); ProtocolTransmit::init(); ResetHandler::init(); - + resetWatchdog(); /* Create the INT_N thread. */ InterruptHandler::init(); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp index 3e3540ac..7b28e1d9 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp @@ -34,20 +34,23 @@ ResetHandler::hardrst_state ResetHandler::hardrst_reset_layer() { /* First, wait for the signal to run a hard reset. */ eventmask_t evt = waitForEvent( PDB_EVT_HARDRST_RESET | PDB_EVT_HARDRST_I_HARDRST); - - /* Reset the Protocol RX machine */ - ProtocolReceive::notify( PDB_EVT_PRLRX_RESET); - taskYIELD(); - /* Reset the Protocol TX machine */ - ProtocolTransmit::notify(PDB_EVT_PRLTX_RESET); - taskYIELD(); - /* Continue the process based on what event started the reset. */ - if (evt & PDB_EVT_HARDRST_RESET) { - /* Policy Engine started the reset. */ - return PRLHRRequestHardReset; + if (evt & (PDB_EVT_HARDRST_RESET | PDB_EVT_HARDRST_I_HARDRST)) { + /* Reset the Protocol RX machine */ + ProtocolReceive::notify( PDB_EVT_PRLRX_RESET); + taskYIELD(); + /* Reset the Protocol TX machine */ + ProtocolTransmit::notify( ProtocolTransmit::Notifications::PDB_EVT_PRLTX_RESET); + taskYIELD(); + /* Continue the process based on what event started the reset. */ + if (evt & PDB_EVT_HARDRST_RESET) { + /* Policy Engine started the reset. */ + return PRLHRRequestHardReset; + } else { + /* PHY started the reset */ + return PRLHRIndicateHardReset; + } } else { - /* PHY started the reset */ - return PRLHRIndicateHardReset; + return PRLHRResetLayer; } } @@ -100,8 +103,7 @@ void ResetHandler::init() { } void ResetHandler::notify(uint32_t notification) { - xTaskNotify(TaskHandle, notification, - eNotifyAction::eSetBits); + xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits); } void ResetHandler::Thread(const void *arg) { @@ -134,6 +136,7 @@ void ResetHandler::Thread(const void *arg) { default: /* This is an error. It really shouldn't happen. We might * want to handle it anyway, though. */ + state = PRLHRResetLayer; break; } } diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h index 46ab9bd8..d4442ed7 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h @@ -33,7 +33,7 @@ public: private: static void Thread(const void *arg); static osThreadId TaskHandle; - static const size_t TaskStackSize = 1024 / 4; + static const size_t TaskStackSize = 1536 / 4; static uint32_t TaskBuffer[TaskStackSize]; static osStaticThreadDef_t TaskControlBlock; static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait = diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index 32d020fc..f137fa1e 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -25,6 +25,7 @@ #include "policy_engine.h" #include "protocol_rx.h" #include "protocol_tx.h" +#include "task.h" #include "BSP.h" osThreadId InterruptHandler::TaskHandle; @@ -32,39 +33,40 @@ uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize]; osStaticThreadDef_t InterruptHandler::TaskControlBlock; void InterruptHandler::init() { - osThreadStaticDef(Task, Thread, PDB_PRIO_PE, 0, TaskStackSize, TaskBuffer, - &TaskControlBlock); + osThreadStaticDef(Task, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize, + TaskBuffer, &TaskControlBlock); TaskHandle = osThreadCreate(osThread(Task), NULL); } void InterruptHandler::Thread(const void *arg) { (void) arg; union fusb_status status; - eventmask_t events; + volatile uint32_t events; while (true) { /* If the INT_N line is low */ - xTaskNotifyWait(0x00, 0x0F, NULL, 5); + xTaskNotifyWait(0x00, 0x0F, NULL, 100); /* Read the FUSB302B status and interrupt registers */ fusb_get_status(&status); - //Check for rx alerts - /* If the I_GCRCSENT flag is set, tell the Protocol RX thread */ + //This means a message was recieved with a good CRC if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) { ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT); } + if ((status.status1 & FUSB_STATUS1_RX_EMPTY) == 0) { + ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT); + } /* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX * thread */ - events = 0; - if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) { - events |= PDB_EVT_PRLTX_I_RETRYFAIL; - } + if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) { - events |= PDB_EVT_PRLTX_I_TXSENT; + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_TXSENT); } - if (events) { - ProtocolTransmit::notify(events); + if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) { + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_RETRYFAIL); } /* If the I_HARDRST or I_HARDSENT flag is set, tell the Hard Reset @@ -72,25 +74,25 @@ void InterruptHandler::Thread(const void *arg) { events = 0; if (status.interrupta & FUSB_INTERRUPTA_I_HARDRST) { - events |= PDB_EVT_HARDRST_I_HARDRST; - } - if (status.interrupta & FUSB_INTERRUPTA_I_HARDSENT) { +// events |= PDB_EVT_HARDRST_I_HARDRST; + } else if (status.interrupta & FUSB_INTERRUPTA_I_HARDSENT) { events |= PDB_EVT_HARDRST_I_HARDSENT; } if (events) { ResetHandler::notify(events); } - /* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy * Engine thread */ if (status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP && status.status1 & FUSB_STATUS1_OVRTEMP) { PolicyEngine::notify(PDB_EVT_PE_I_OVRTEMP); } - } } - +volatile uint8_t irqs = 0; void InterruptHandler::irqCallback() { - xTaskNotify(TaskHandle, 0x0F, eNotifyAction::eSetBits); + irqs++; + BaseType_t taskWoke = pdFALSE; + xTaskNotifyFromISR(TaskHandle, 0x0F, eNotifyAction::eSetBits, &taskWoke); + portYIELD_FROM_ISR(taskWoke); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.h b/workspace/TS100/Core/Drivers/FUSB302/int_n.h index e168171e..e7af6a4c 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.h +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.h @@ -30,7 +30,7 @@ public: private: static void Thread(const void *arg); static osThreadId TaskHandle; - static const size_t TaskStackSize = 1024 / 4; + static const size_t TaskStackSize = 1536 / 4; static uint32_t TaskBuffer[TaskStackSize]; static osStaticThreadDef_t TaskControlBlock; /* diff --git a/workspace/TS100/Core/Drivers/FUSB302/pd.h b/workspace/TS100/Core/Drivers/FUSB302/pd.h index 7bd754b5..11c8f80f 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/pd.h +++ b/workspace/TS100/Core/Drivers/FUSB302/pd.h @@ -273,18 +273,18 @@ * Where a range is specified, the middle of the range (rounded down to the * nearest millisecond) is used. */ -#define PD_T_CHUNKING_NOT_SUPPORTED (45) -#define PD_T_HARD_RESET_COMPLETE (4) -#define PD_T_PS_TRANSITION (500) -#define PD_T_SENDER_RESPONSE (27) -#define PD_T_SINK_REQUEST (100) -#define PD_T_TYPEC_SINK_WAIT_CAP (465) -#define PD_T_PD_DEBOUNCE (15) +#define PD_T_CHUNKING_NOT_SUPPORTED (450) +#define PD_T_HARD_RESET_COMPLETE (400) +#define PD_T_PS_TRANSITION (5000) +#define PD_T_SENDER_RESPONSE (2700) +#define PD_T_SINK_REQUEST (1000) +#define PD_T_TYPEC_SINK_WAIT_CAP (5000) +#define PD_T_PD_DEBOUNCE (2000) /* * Counter maximums */ -#define PD_N_HARD_RESET_COUNT 10 +#define PD_N_HARD_RESET_COUNT 20 /* * Value parameters diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp index 22b76589..da79efc8 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -181,13 +181,13 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_wait_cap() { if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_1_0) { /* If the other end is using at least version 3.0, we'll * use version 3.0. */ - if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { - hdr_template |= PD_SPECREV_3_0; - /* Otherwise, use 2.0. Don't worry about the 1.0 case - * because we don't have hardware for PD 1.0 signaling. */ - } else { - hdr_template |= PD_SPECREV_2_0; - } +// if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { +// hdr_template |= PD_SPECREV_3_0; +// /* Otherwise, use 2.0. Don't worry about the 1.0 case +// * because we don't have hardware for PD 1.0 signaling. */ +// } else { + hdr_template |= PD_SPECREV_2_0; +// } } return PESinkEvalCap; /* If the message was a Soft_Reset, do the soft reset procedure */ @@ -247,7 +247,8 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { /* Transmit the request */ ProtocolTransmit::pushMessage(&_last_dpm_request); //Send indication that there is a message pending - ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX); eventmask_t evt = waitForEvent( PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); /* Don't free the request; we might need it again */ @@ -396,7 +397,8 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_ready() { /* If the DPM wants us to, send a Get_Source_Cap message */ if (evt & PDB_EVT_PE_GET_SOURCE_CAP) { /* Tell the protocol layer we're starting an AMS */ - ProtocolTransmit::notify( PDB_EVT_PRLTX_START_AMS); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_START_AMS); return PESinkGetSourceCap; } @@ -406,14 +408,16 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_ready() { * design of this firmware. */ if (evt & PDB_EVT_PE_NEW_POWER) { /* Tell the protocol layer we're starting an AMS */ - ProtocolTransmit::notify( PDB_EVT_PRLTX_START_AMS); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_START_AMS); return PESinkEvalCap; } /* If SinkPPSPeriodicTimer ran out, send a new request */ if (evt & PDB_EVT_PE_PPS_REQUEST) { /* Tell the protocol layer we're starting an AMS */ - ProtocolTransmit::notify( PDB_EVT_PRLTX_START_AMS); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_START_AMS); return PESinkSelectCap; } @@ -538,7 +542,8 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_get_source_cap() { | PD_NUMOBJ(0); /* Transmit the Get_Source_Cap */ ProtocolTransmit::pushMessage(get_source_cap); - ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX); eventmask_t evt = waitForEvent( PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); /* Free the sent message */ @@ -562,7 +567,8 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_give_sink_cap() { /* Transmit our capabilities */ ProtocolTransmit::pushMessage(snk_cap); - ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX); eventmask_t evt = waitForEvent( PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); @@ -623,7 +629,8 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_soft_reset() { accept.hdr = hdr_template | PD_MSGTYPE_ACCEPT | PD_NUMOBJ(0); /* Transmit the Accept */ ProtocolTransmit::pushMessage(&accept); - ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX); eventmask_t evt = waitForEvent( PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); /* Free the sent message */ @@ -650,7 +657,8 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_send_soft_reset() { softrst->hdr = hdr_template | PD_MSGTYPE_SOFT_RESET | PD_NUMOBJ(0); /* Transmit the soft reset */ ProtocolTransmit::pushMessage(softrst); - ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX); eventmask_t evt = waitForEvent( PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); /* If we got reset signaling, transition to default */ @@ -711,7 +719,8 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_send_not_supported() { /* Transmit the message */ ProtocolTransmit::pushMessage(not_supported); - ProtocolTransmit::notify( PDB_EVT_PRLTX_MSG_TX); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX); eventmask_t evt = waitForEvent( PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h index 8e4de84a..08f9543f 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h @@ -116,7 +116,7 @@ private: portMAX_DELAY); //Task resources static osThreadId TaskHandle; - static const size_t TaskStackSize = 1024 / 4; + static const size_t TaskStackSize = 2048 / 4; static uint32_t TaskBuffer[TaskStackSize]; static osStaticThreadDef_t TaskControlBlock; static union pd_msg tempMessage; diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp index 26117da5..fae4184e 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp @@ -39,7 +39,7 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_wait_phy() { /* If we got a reset event, reset */ if (evt & PDB_EVT_PRLRX_RESET) { - waitForEvent(PDB_EVT_PRLRX_RESET, 0); +// waitForEvent(PDB_EVT_PRLRX_RESET, 0); return PRLRxWaitPHY; } /* If we got an I_GCRCSENT event, read the message and decide what to do */ @@ -73,7 +73,8 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_reset() { _rx_messageid = -1; /* TX transitions to its reset state */ - ProtocolTransmit::notify( PDB_EVT_PRLTX_RESET); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_RESET); taskYIELD(); /* If we got a RESET signal, reset the machine */ @@ -84,7 +85,7 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_reset() { /* Go to the Check_MessageID state */ return PRLRxCheckMessageID; } - +volatile uint32_t rxCounter = 0; /* * PRL_Rx_Check_MessageID state */ @@ -99,9 +100,9 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_check_messageid( /* Otherwise, there's either no stored ID or this message has an ID we * haven't just seen. Transition to the Store_MessageID state. */ /*if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) { - return PRLRxWaitPHY; - } else*/ - + return PRLRxWaitPHY; + } else*/ + rxCounter++; { return PRLRxStoreMessageID; } @@ -113,7 +114,8 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_check_messageid( ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_store_messageid() { /* Tell ProtocolTX to discard the message being transmitted */ - ProtocolTransmit::notify( PDB_EVT_PRLTX_DISCARD); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_DISCARD); taskYIELD(); /* Update the stored MessageID */ @@ -122,7 +124,7 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_store_messageid( /* Pass the message to the policy engine. */ PolicyEngine::handleMessage(&tempMessage); - PolicyEngine::notify( PDB_EVT_PE_MSG_RX); + PolicyEngine::notify(PDB_EVT_PE_MSG_RX); /* Don't check if we got a RESET because we'd do nothing different. */ @@ -163,6 +165,9 @@ void ProtocolReceive::thread(const void *args) { } void ProtocolReceive::notify(uint32_t notification) { + if (notification == PDB_EVT_PRLRX_I_GCRCSENT) { +// asm("bkpt"); + } xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h index 920e80a2..579c5ee1 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h @@ -34,7 +34,7 @@ private: static void thread(const void *args); static osThreadId TaskHandle; - static const size_t TaskStackSize = 512 / 4; + static const size_t TaskStackSize = 1024 / 4; static uint32_t TaskBuffer[TaskStackSize]; static osStaticThreadDef_t TaskControlBlock; /* diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp index 43c8a945..9fef236b 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp @@ -59,18 +59,20 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_phy_reset() { */ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_message() { /* Wait for an event */ - eventmask_t evt = waitForEvent( - PDB_EVT_PRLTX_RESET | PDB_EVT_PRLTX_DISCARD | PDB_EVT_PRLTX_MSG_TX); + ProtocolTransmit::Notifications evt = waitForEvent( + (uint32_t) Notifications::PDB_EVT_PRLTX_RESET + | (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD + | (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX); - if (evt & PDB_EVT_PRLTX_RESET) { + if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) { return PRLTxPHYReset; } - if (evt & PDB_EVT_PRLTX_DISCARD) { + if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) { return PRLTxDiscardMessage; } /* If the policy engine is trying to send a message */ - if (evt & PDB_EVT_PRLTX_MSG_TX) { + if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX) { /* Get the message */ getMessage(); @@ -104,13 +106,14 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_reset() { */ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_message() { /* Make sure nobody wants us to reset */ - eventmask_t evt = waitForEvent( - PDB_EVT_PRLTX_RESET | PDB_EVT_PRLTX_DISCARD, 0); + ProtocolTransmit::Notifications evt = waitForEvent( + (uint32_t) Notifications::PDB_EVT_PRLTX_RESET + | (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD, 0); - if (evt & PDB_EVT_PRLTX_RESET) { + if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) { return PRLTxPHYReset; } - if (evt & PDB_EVT_PRLTX_DISCARD) { + if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) { return PRLTxDiscardMessage; } @@ -121,8 +124,9 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_mess /* PD 3.0 collision avoidance */ if (PolicyEngine::isPD3_0()) { /* If we're starting an AMS, wait for permission to transmit */ - evt = waitForEvent(PDB_EVT_PRLTX_START_AMS, 0); - if (evt & PDB_EVT_PRLTX_START_AMS) { + evt = waitForEvent((uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS, + 0); + if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS) { while (fusb_get_typec_current() != fusb_sink_tx_ok) { osDelay(1); } @@ -141,23 +145,25 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_mess ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_response() { /* Wait for an event. There is no need to run CRCReceiveTimer, since the * FUSB302B handles that as part of its retry mechanism. */ - eventmask_t evt = waitForEvent( - PDB_EVT_PRLTX_RESET | PDB_EVT_PRLTX_DISCARD | PDB_EVT_PRLTX_I_TXSENT - | PDB_EVT_PRLTX_I_RETRYFAIL); + ProtocolTransmit::Notifications evt = waitForEvent( + (uint32_t) Notifications::PDB_EVT_PRLTX_RESET + | (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD + | (uint32_t) Notifications::PDB_EVT_PRLTX_I_TXSENT + | (uint32_t) Notifications::PDB_EVT_PRLTX_I_RETRYFAIL); - if (evt & PDB_EVT_PRLTX_RESET) { + if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) { return PRLTxPHYReset; } - if (evt & PDB_EVT_PRLTX_DISCARD) { + if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) { return PRLTxDiscardMessage; } /* If the message was sent successfully */ - if (evt & PDB_EVT_PRLTX_I_TXSENT) { + if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_I_TXSENT) { return PRLTxMatchMessageID; } /* If the message failed to be sent */ - if (evt & PDB_EVT_PRLTX_I_RETRYFAIL) { + if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_I_RETRYFAIL) { return PRLTxTransmissionError; } @@ -253,16 +259,16 @@ void ProtocolTransmit::thread(const void *args) { } } -void ProtocolTransmit::notify(uint32_t notification) { - xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits); +void ProtocolTransmit::notify(ProtocolTransmit::Notifications notification) { + xTaskNotify(TaskHandle, (uint32_t )notification, eNotifyAction::eSetBits); } void ProtocolTransmit::init() { messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue); - osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PRL, 0, - TaskStackSize, TaskBuffer, &TaskControlBlock); + osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PE, 0, TaskStackSize, + TaskBuffer, &TaskControlBlock); TaskHandle = osThreadCreate(osThread(pd_txTask), NULL); } @@ -279,8 +285,9 @@ void ProtocolTransmit::getMessage() { xQueueReceive(messagesWaiting, &temp_msg, 1); } -uint32_t ProtocolTransmit::waitForEvent(uint32_t mask, uint32_t ticksToWait) { +ProtocolTransmit::Notifications ProtocolTransmit::waitForEvent(uint32_t mask, + uint32_t ticksToWait) { uint32_t pulNotificationValue; xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait); - return pulNotificationValue & mask; + return (Notifications) (pulNotificationValue & mask); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h index bab49336..69c1c564 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h @@ -24,24 +24,28 @@ #include /* Events for the Protocol TX thread */ -#define PDB_EVT_PRLTX_RESET EVENT_MASK(0) -#define PDB_EVT_PRLTX_I_TXSENT EVENT_MASK(1) -#define PDB_EVT_PRLTX_I_RETRYFAIL EVENT_MASK(2) -#define PDB_EVT_PRLTX_DISCARD EVENT_MASK(3) -#define PDB_EVT_PRLTX_MSG_TX EVENT_MASK(4) -#define PDB_EVT_PRLTX_START_AMS EVENT_MASK(5) class ProtocolTransmit { public: static void init(); //Push a message to the queue to be sent out the pd comms bus static void pushMessage(union pd_msg *msg); - static void notify(uint32_t notification); + + enum class Notifications { + + PDB_EVT_PRLTX_RESET = EVENT_MASK(0), // + PDB_EVT_PRLTX_I_TXSENT = EVENT_MASK(1), // + PDB_EVT_PRLTX_I_RETRYFAIL = EVENT_MASK(2), // + PDB_EVT_PRLTX_DISCARD = EVENT_MASK(3), // + PDB_EVT_PRLTX_MSG_TX = EVENT_MASK(4), // + PDB_EVT_PRLTX_START_AMS = EVENT_MASK(5), // + }; + static void notify(Notifications notification); private: static void thread(const void *args); static osThreadId TaskHandle; - static const size_t TaskStackSize = 512 / 4; + static const size_t TaskStackSize = 1024 / 4; static uint32_t TaskBuffer[TaskStackSize]; static osStaticThreadDef_t TaskControlBlock; /* @@ -83,8 +87,8 @@ private: //Reads a message off the queue into the temp message static void getMessage(); static union pd_msg temp_msg; - static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait = - portMAX_DELAY); + static Notifications waitForEvent(uint32_t mask, uint32_t ticksToWait = + portMAX_DELAY); }; diff --git a/workspace/TS100/Core/Drivers/OLED.cpp b/workspace/TS100/Core/Drivers/OLED.cpp index fc9867eb..0e6790e7 100644 --- a/workspace/TS100/Core/Drivers/OLED.cpp +++ b/workspace/TS100/Core/Drivers/OLED.cpp @@ -213,7 +213,7 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) { } void OLED::setRotation(bool leftHanded) { -#ifdef MODEL_TS80 +#if defined( MODEL_TS80) +defined( MODEL_TS80P) > 0 leftHanded = !leftHanded; #endif if (inLeftHandedMode == leftHanded) { diff --git a/workspace/TS100/Core/Drivers/TipThermoModel.cpp b/workspace/TS100/Core/Drivers/TipThermoModel.cpp index ac1c9389..c94e6284 100644 --- a/workspace/TS100/Core/Drivers/TipThermoModel.cpp +++ b/workspace/TS100/Core/Drivers/TipThermoModel.cpp @@ -27,12 +27,11 @@ * This was bought to my attention by */ - uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC) { // This takes the raw ADC samples, converts these to uV // Then divides this down by the gain to convert to the uV on the input to the op-amp (A+B terminals) // Then remove the calibration value that is stored as a tip offset - uint32_t vddRailmVX10 = 33000; //The vreg is +-2%, but we have no higher accuracy available + uint32_t vddRailmVX10 = 33000;//The vreg is +-2%, but we have no higher accuracy available // 4096 * 8 readings for full scale // Convert the input ADC reading back into mV times 10 format. uint32_t rawInputmVX10 = (rawADC * vddRailmVX10) / (4096 * 8); @@ -76,7 +75,7 @@ uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { tipuVDelta *= 10; tipuVDelta /= systemSettings.TipGain; -#ifdef MODEL_TS80 +#if defined( MODEL_TS80)+defined( MODEL_TS80P)>0 tipuVDelta /= OP_AMP_GAIN_STAGE_TS100 / OP_AMP_GAIN_STAGE_TS80; #endif diff --git a/workspace/TS100/Core/Inc/FreeRTOSConfig.h b/workspace/TS100/Core/Inc/FreeRTOSConfig.h index ae12d43d..820ca8b7 100644 --- a/workspace/TS100/Core/Inc/FreeRTOSConfig.h +++ b/workspace/TS100/Core/Inc/FreeRTOSConfig.h @@ -98,11 +98,11 @@ extern uint32_t SystemCoreClock; #define configUSE_IDLE_HOOK 1 #define configUSE_TICK_HOOK 0 #define configCPU_CLOCK_HZ ( SystemCoreClock ) -#define configTICK_RATE_HZ ((TickType_t)100) +#define configTICK_RATE_HZ ((TickType_t)1000) #define configMAX_PRIORITIES ( 6 ) #define configMINIMAL_STACK_SIZE ((uint16_t)256) #define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/ -#define configMAX_TASK_NAME_LEN ( 24 ) +#define configMAX_TASK_NAME_LEN ( 32 ) #define configUSE_16_BIT_TICKS 0 #define configUSE_MUTEXES 1 #define configQUEUE_REGISTRY_SIZE 8 diff --git a/workspace/TS100/Core/Inc/stm32f1xx_hal_conf.h b/workspace/TS100/Core/Inc/stm32f1xx_hal_conf.h index e1df8b6f..b3e68d1a 100644 --- a/workspace/TS100/Core/Inc/stm32f1xx_hal_conf.h +++ b/workspace/TS100/Core/Inc/stm32f1xx_hal_conf.h @@ -1,365 +1,364 @@ -/** - ****************************************************************************** - * @file stm32f1xx_hal_conf.h - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2017 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F1xx_HAL_CONF_H -#define __STM32F1xx_HAL_CONF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ - -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -/*#define HAL_CRYP_MODULE_ENABLED */ -/*#define HAL_CAN_MODULE_ENABLED */ -/*#define HAL_CEC_MODULE_ENABLED */ -/*#define HAL_CORTEX_MODULE_ENABLED */ -/*#define HAL_CRC_MODULE_ENABLED */ -/*#define HAL_DAC_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/*#define HAL_ETH_MODULE_ENABLED */ -/*#define HAL_FLASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/*#define HAL_I2S_MODULE_ENABLED */ -/*#define HAL_IRDA_MODULE_ENABLED */ -#define HAL_IWDG_MODULE_ENABLED -/*#define HAL_NOR_MODULE_ENABLED */ -/*#define HAL_NAND_MODULE_ENABLED */ -/*#define HAL_PCCARD_MODULE_ENABLED */ -/*#define HAL_PCD_MODULE_ENABLED */ -/*#define HAL_HCD_MODULE_ENABLED */ -/*#define HAL_PWR_MODULE_ENABLED */ -/*#define HAL_RCC_MODULE_ENABLED */ -/*#define HAL_RTC_MODULE_ENABLED */ -/*#define HAL_SD_MODULE_ENABLED */ -/*#define HAL_MMC_MODULE_ENABLED */ -/*#define HAL_SDRAM_MODULE_ENABLED */ -/*#define HAL_SMARTCARD_MODULE_ENABLED */ -/*#define HAL_SPI_MODULE_ENABLED */ -/*#define HAL_SRAM_MODULE_ENABLED */ -#define HAL_TIM_MODULE_ENABLED -/*#define HAL_UART_MODULE_ENABLED */ -/*#define HAL_USART_MODULE_ENABLED */ -/*#define HAL_WWDG_MODULE_ENABLED */ - -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_DMA_MODULE_ENABLED -#define HAL_FLASH_MODULE_ENABLED -#define HAL_GPIO_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED - -/* ########################## Oscillator Values adaptation ####################*/ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */ -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ - -/** - * @brief External Low Speed oscillator (LSE) value. - * This value is used by the UART, RTC HAL module to compute the system frequency - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0) /*!< tick interrupt priority (lowest by default) */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)8) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848_PHY_ADDRESS Address*/ -#define DP83848_PHY_ADDRESS 0x01U -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ -#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ - -#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f1xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f1xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f1xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f1xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f1xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CEC_MODULE_ENABLED - #include "stm32f1xx_hal_cec.h" -#endif /* HAL_CEC_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f1xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f1xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f1xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f1xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f1xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f1xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f1xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f1xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f1xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f1xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f1xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f1xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f1xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f1xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_MMC_MODULE_ENABLED - #include "stm32f1xx_hal_mmc.h" -#endif /* HAL_MMC_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f1xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f1xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f1xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f1xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f1xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f1xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f1xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f1xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f1xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f1xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0U) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F1xx_HAL_CONF_H */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/** + ****************************************************************************** + * @file stm32f1xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F1xx_HAL_CONF_H +#define __STM32F1xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ + +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_CAN_MODULE_ENABLED */ +/*#define HAL_CEC_MODULE_ENABLED */ +/*#define HAL_CORTEX_MODULE_ENABLED */ +/*#define HAL_CRC_MODULE_ENABLED */ +/*#define HAL_DAC_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED +/*#define HAL_ETH_MODULE_ENABLED */ +/*#define HAL_FLASH_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +/*#define HAL_I2S_MODULE_ENABLED */ +/*#define HAL_IRDA_MODULE_ENABLED */ +#define HAL_IWDG_MODULE_ENABLED +/*#define HAL_NOR_MODULE_ENABLED */ +/*#define HAL_NAND_MODULE_ENABLED */ +/*#define HAL_PCCARD_MODULE_ENABLED */ +/*#define HAL_PCD_MODULE_ENABLED */ +/*#define HAL_HCD_MODULE_ENABLED */ +/*#define HAL_PWR_MODULE_ENABLED */ +/*#define HAL_RCC_MODULE_ENABLED */ +/*#define HAL_RTC_MODULE_ENABLED */ +/*#define HAL_SD_MODULE_ENABLED */ +/*#define HAL_MMC_MODULE_ENABLED */ +/*#define HAL_SDRAM_MODULE_ENABLED */ +/*#define HAL_SMARTCARD_MODULE_ENABLED */ +/*#define HAL_SPI_MODULE_ENABLED */ +/*#define HAL_SRAM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED +/*#define HAL_UART_MODULE_ENABLED */ +/*#define HAL_USART_MODULE_ENABLED */ +/*#define HAL_WWDG_MODULE_ENABLED */ + +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0 +#define PREFETCH_ENABLE 1 + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1 */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2 +#define MAC_ADDR1 0 +#define MAC_ADDR2 0 +#define MAC_ADDR3 0 +#define MAC_ADDR4 0 +#define MAC_ADDR5 0 + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)8) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x000000FF) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) + +#define PHY_READ_TO ((uint32_t)0x0000FFFF) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f1xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f1xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f1xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f1xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f1xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f1xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f1xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f1xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f1xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f1xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f1xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f1xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f1xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f1xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f1xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f1xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f1xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f1xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f1xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f1xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f1xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f1xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f1xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f1xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f1xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f1xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f1xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f1xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f1xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f1xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f1xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F1xx_HAL_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/workspace/TS100/Core/Src/FreeRTOSHooks.c b/workspace/TS100/Core/Src/FreeRTOSHooks.c index 4807480a..2e08976e 100644 --- a/workspace/TS100/Core/Src/FreeRTOSHooks.c +++ b/workspace/TS100/Core/Src/FreeRTOSHooks.c @@ -37,6 +37,7 @@ void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCHAR *pcTaskName) { (void) pxTask; (void) pcTaskName; + asm("bkpt"); // We dont have a good way to handle a stack overflow at this point in time reboot(); } diff --git a/workspace/TS100/Core/Src/QC3.c b/workspace/TS100/Core/Src/QC3.c index 43cff776..826891c8 100644 --- a/workspace/TS100/Core/Src/QC3.c +++ b/workspace/TS100/Core/Src/QC3.c @@ -30,16 +30,16 @@ void QC_SeekContMode() { } void QC_SeekContPlus() { QC_SeekContMode(); - vTaskDelay(3); + osDelay(30); QC_Seek20V(); - vTaskDelay(1); + osDelay(10); QC_SeekContMode(); } void QC_SeekContNeg() { QC_SeekContMode(); - vTaskDelay(3); + osDelay(30); QC_Seek12V(); - vTaskDelay(1); + osDelay(10); QC_SeekContMode(); } uint8_t QCMode = 0; @@ -65,15 +65,15 @@ void seekQC(int16_t Vx10, uint16_t divisor) { if (steps > -2 && steps < 2) return; // dont bother with small steps while (steps < 0) { QC_SeekContNeg(); - vTaskDelay(3); + osDelay(30); steps++; } while (steps > 0) { QC_SeekContPlus(); - vTaskDelay(3); + osDelay(30); steps--; } - vTaskDelay(10); + osDelay(100); } #ifdef ENABLE_QC2 // Re-measure @@ -118,7 +118,7 @@ void startQC(uint16_t divisor) { // Delay 1.25 seconds uint8_t enteredQC = 0; for (uint16_t i = 0; i < 200 && enteredQC == 0; i++) { - vTaskDelay(1); // 10mS pause + osDelay(10); // 10mS pause if (i > 130) { if (QC_DM_PulledDown()) { enteredQC = 1; @@ -143,7 +143,7 @@ void startQC(uint16_t divisor) { QCMode = 3; // We have at least QC2, pray for 3 return; } - vTaskDelay(10); // 100mS + osDelay(100); // 100mS } QCMode = 5; QCTries++; diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index 16730c9e..658fb4b7 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -120,14 +120,14 @@ static void settings_enterAdvancedMenu(void); * */ const menuitem rootSettingsMenu[] { -/* - * Power Source - * Soldering Menu - * Power Saving Menu - * UI Menu - * Advanced Menu - * Exit - */ + /* + * Power Source + * Soldering Menu + * Power Saving Menu + * UI Menu + * Advanced Menu + * Exit + */ #ifdef MODEL_TS100 { (const char*) SettingsDescriptions[0], { settings_setInputVRange }, { settings_displayInputVRange } }, /*Voltage input*/ @@ -739,7 +739,7 @@ static void settings_setCalibrateVIN(void) { osDelay(40); // Cap to sensible values -#ifdef MODEL_TS80 +#if defined(MODEL_TS80)+defined(MODEL_TS80P)>0 if (systemSettings.voltageDiv < 500) { systemSettings.voltageDiv = 500; } else if (systemSettings.voltageDiv > 900) { diff --git a/workspace/TS100/Core/Src/main.cpp b/workspace/TS100/Core/Src/main.cpp index 78a7d5d9..23cd5648 100644 --- a/workspace/TS100/Core/Src/main.cpp +++ b/workspace/TS100/Core/Src/main.cpp @@ -43,7 +43,7 @@ int main(void) { OLED::setFont(0); // default to bigger font // Testing for which accelerometer is mounted resetWatchdog(); - usb_pd_available = usb_pd_detect(); + usb_pd_available = true;//usb_pd_detect(); resetWatchdog(); settingsWereReset = restoreSettings(); // load the settings from flash /*if (MMA8652FC::detect()) { @@ -68,10 +68,10 @@ int main(void) { GUITaskStackSize, GUITaskBuffer, &GUITaskControlBlock); GUITaskHandle = osThreadCreate(osThread(GUITask), NULL); - /* definition and creation of PIDTask */ - osThreadStaticDef(PIDTask, startPIDTask, osPriorityRealtime, 0, - PIDTaskStackSize, PIDTaskBuffer, &PIDTaskControlBlock); - PIDTaskHandle = osThreadCreate(osThread(PIDTask), NULL); +// /* definition and creation of PIDTask */ +// osThreadStaticDef(PIDTask, startPIDTask, osPriorityRealtime, 0, +// PIDTaskStackSize, PIDTaskBuffer, &PIDTaskControlBlock); +// PIDTaskHandle = osThreadCreate(osThread(PIDTask), NULL); osThreadStaticDef(MOVTask, startMOVTask, osPriorityNormal, 0, MOVTaskStackSize, MOVTaskBuffer, &MOVTaskControlBlock); diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 5ed33dc1..befbbef8 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -247,7 +247,7 @@ static void gui_solderingTempAdjust() { if (xTaskGetTickCount() - lastChange > 200) return; // exit if user just doesn't press anything for a bit -#ifdef MODEL_TS80 +#if defined (MODEL_TS80P)+defined(MODEL_TS80)>0 if (!OLED::getRotation()) { #else if (OLED::getRotation()) { @@ -272,7 +272,7 @@ static void gui_solderingTempAdjust() { OLED::drawSymbol(1); } OLED::print(SymbolSpace); -#ifdef MODEL_TS80 +#if defined (MODEL_TS80P)+defined(MODEL_TS80)>0 if (!OLED::getRotation()) { #else if (OLED::getRotation()) { @@ -770,7 +770,7 @@ void startGUITask(void const *argument __unused) { } else { OLED::setFont(0); -#ifdef MODEL_TS80 +#if defined (MODEL_TS80P)+defined(MODEL_TS80)>0 if (!OLED::getRotation()) { #else if (OLED::getRotation()) { @@ -791,7 +791,7 @@ void startGUITask(void const *argument __unused) { if (tempOnDisplay) { // draw temp over the start soldering button // Location changes on screen rotation -#ifdef MODEL_TS80 +#if defined (MODEL_TS80P)+defined(MODEL_TS80)>0 if (!OLED::getRotation()) { #else if (OLED::getRotation()) { diff --git a/workspace/TS100/LinkerScript.ld b/workspace/TS100/LinkerScript.ld index 8ca171b5..fe5d6a2b 100644 --- a/workspace/TS100/LinkerScript.ld +++ b/workspace/TS100/LinkerScript.ld @@ -14,9 +14,9 @@ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K /* LOCAL_BUILD*/ -/*ROM (rx) : ORIGIN = 0x08000000, LENGTH = 46K*/ +ROM (rx) : ORIGIN = 0x08000000, LENGTH = 46K /* production*/ -ROM (rx) : ORIGIN = 0x08004000, LENGTH = 46K +/*ROM (rx) : ORIGIN = 0x08004000, LENGTH = 46K*/ diff --git a/workspace/TS100/configuration.h b/workspace/TS100/configuration.h index 66688f12..6c299576 100644 --- a/workspace/TS100/configuration.h +++ b/workspace/TS100/configuration.h @@ -108,7 +108,6 @@ #endif #ifdef MODEL_TS80 -#define VOLTAGE_DIV_TS80P 768 // Default for TS80P with slightly different resistors #define VOLTAGE_DIV 780 // Default divider from schematic #define PID_POWER_LIMIT 24 // Sets the max pwm power limit #define CALIBRATION_OFFSET 900 // the adc offset in uV From 164c402d1ca9efc47f2b8c06ab453100b5fcf00d Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 22 Jul 2020 22:33:18 +1000 Subject: [PATCH 17/53] Update I2CBB.cpp --- workspace/TS100/Core/BSP/Miniware/I2CBB.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp index 27ce6811..88ec616d 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp @@ -13,7 +13,7 @@ #define SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET) #define SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0) #define SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0) -#define I2C_DELAY() {for(int xx=0;xx<1000;xx++){asm("nop");}} +#define I2C_DELAY() {for(int xx=0;xx<20;xx++){asm("nop");}} SemaphoreHandle_t I2CBB::I2CSemaphore = NULL; StaticSemaphore_t I2CBB::xSemaphoreBuffer; SemaphoreHandle_t I2CBB::I2CSemaphore2 = NULL; @@ -34,10 +34,11 @@ void I2CBB::init() { unlock(); unlock2(); //unstick bus - for (int i = 0; i < 8; i++) { - read_bit(); - } - stop(); +// start(); +// for (int i = 0; i < 8; i++) { +// read_bit(); +// } +// stop(); } bool I2CBB::probe(uint8_t address) { @@ -64,6 +65,9 @@ bool I2CBB::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, unlock(); return false; } + SCL_LOW(); + I2C_DELAY(); +// stop(); start(); ack = send(DevAddress | 1); if (!ack) { @@ -234,7 +238,7 @@ bool I2CBB::send(uint8_t value) { } SDA_HIGH(); - bool ack = read_bit() == 0; + bool ack = (read_bit() == 0); return ack; } From 6097216b246a0f8abfb7cf3dbc3805784def994f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 22 Jul 2020 22:39:20 +1000 Subject: [PATCH 18/53] Port unreliable but starter PD setup --- workspace/TS100/Core/BSP/Miniware/I2CBB.cpp | 2 +- workspace/TS100/Core/BSP/Miniware/Setup.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp index 88ec616d..57aca422 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp @@ -13,7 +13,7 @@ #define SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET) #define SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0) #define SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0) -#define I2C_DELAY() {for(int xx=0;xx<20;xx++){asm("nop");}} +#define I2C_DELAY() {for(int xx=0;xx<100;xx++){asm("nop");}} SemaphoreHandle_t I2CBB::I2CSemaphore = NULL; StaticSemaphore_t I2CBB::xSemaphoreBuffer; SemaphoreHandle_t I2CBB::I2CSemaphore2 = NULL; diff --git a/workspace/TS100/Core/BSP/Miniware/Setup.c b/workspace/TS100/Core/BSP/Miniware/Setup.c index ca1f82f5..b8df1cc0 100644 --- a/workspace/TS100/Core/BSP/Miniware/Setup.c +++ b/workspace/TS100/Core/BSP/Miniware/Setup.c @@ -43,7 +43,7 @@ void Setup_HAL() { MX_ADC2_Init(); MX_TIM3_Init(); MX_TIM2_Init(); -// MX_IWDG_Init(); + MX_IWDG_Init(); HAL_ADC_Start(&hadc2); HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*) ADCReadings, 64); // start DMA of normal readings HAL_ADCEx_InjectedStart(&hadc1); // enable injected readings From 1cebcdc42b0544565b31b50c765ae406c8048119 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 22 Jul 2020 22:39:35 +1000 Subject: [PATCH 19/53] Works on SRC only units.. mostly --- workspace/TS100/Core/BSP/BSP_PD.h | 16 +++++ workspace/TS100/Core/BSP/Miniware/BSP_PD.c | 20 +++++++ .../TS100/Core/Drivers/FUSB302/fusb302b.cpp | 2 +- .../TS100/Core/Drivers/FUSB302/fusbpd.cpp | 1 + .../TS100/Core/Drivers/FUSB302/hard_reset.h | 2 +- .../TS100/Core/Drivers/FUSB302/int_n.cpp | 39 ++++++++----- .../Core/Drivers/FUSB302/policy_engine.cpp | 43 +++++++++----- .../Core/Drivers/FUSB302/policy_engine.h | 2 + .../Drivers/FUSB302/policy_engine_user.cpp | 58 ++++++++++++------- .../Core/Drivers/FUSB302/protocol_rx.cpp | 27 +++++---- .../TS100/Core/Drivers/FUSB302/protocol_rx.h | 2 + .../Core/Drivers/FUSB302/protocol_tx.cpp | 31 +++++----- .../TS100/Core/Drivers/FUSB302/protocol_tx.h | 3 +- workspace/TS100/LinkerScript.ld | 2 +- 14 files changed, 163 insertions(+), 85 deletions(-) create mode 100644 workspace/TS100/Core/BSP/BSP_PD.h create mode 100644 workspace/TS100/Core/BSP/Miniware/BSP_PD.c diff --git a/workspace/TS100/Core/BSP/BSP_PD.h b/workspace/TS100/Core/BSP/BSP_PD.h new file mode 100644 index 00000000..c38f13c9 --- /dev/null +++ b/workspace/TS100/Core/BSP/BSP_PD.h @@ -0,0 +1,16 @@ +/* + * BSP_PD.h + * + * Created on: 21 Jul 2020 + * Author: Ralim + */ + +#ifndef USER_BSP_PD_H_ +#define USER_BSP_PD_H_ +#include "BSP.h" +/* + * An array of all of the desired voltages & minimum currents in preferred order + */ +extern const uint16_t USB_PD_Desired_Levels[]; +extern const uint8_t USB_PD_Desired_Levels_Len; +#endif /* USER_BSP_PD_H_ */ diff --git a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c new file mode 100644 index 00000000..031aa0f7 --- /dev/null +++ b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c @@ -0,0 +1,20 @@ +/* + * BSP_PD.c + * + * Created on: 21 Jul 2020 + * Author: Ralim + */ + +#include "BSP_PD.h" + +/* + * An array of all of the desired voltages & minimum currents in preferred order + */ +const uint16_t USB_PD_Desired_Levels[] = { +//mV desired input, mA minimum required current + 12000, 2500, //12V @ 2.5A + 9000, 2000, //9V @ 2A + 5000, 1100, //5V @ 1.1A + + }; +const uint8_t USB_PD_Desired_Levels_Len = 3; diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp index 9895e99e..50cff3b0 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#include "BSP.h" #include "fusb302b.h" #include "I2CBB.hpp" #include diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp index 03dc87b5..672f1746 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -22,6 +22,7 @@ uint8_t fusb302_detect() { void fusb302_start_processing() { /* Initialize the FUSB302B */ + resetWatchdog(); fusb_setup(); resetWatchdog(); /* Create the policy engine thread. */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h index d4442ed7..9466b33c 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h @@ -33,7 +33,7 @@ public: private: static void Thread(const void *arg); static osThreadId TaskHandle; - static const size_t TaskStackSize = 1536 / 4; + static const size_t TaskStackSize = 1536 / 2; static uint32_t TaskBuffer[TaskStackSize]; static osStaticThreadDef_t TaskControlBlock; static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait = diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index f137fa1e..21bdf5fd 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -33,40 +33,44 @@ uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize]; osStaticThreadDef_t InterruptHandler::TaskControlBlock; void InterruptHandler::init() { - osThreadStaticDef(Task, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize, + osThreadStaticDef(intTask, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize, TaskBuffer, &TaskControlBlock); - TaskHandle = osThreadCreate(osThread(Task), NULL); + TaskHandle = osThreadCreate(osThread(intTask), NULL); } void InterruptHandler::Thread(const void *arg) { (void) arg; union fusb_status status; volatile uint32_t events; + bool notifSent = false; while (true) { /* If the INT_N line is low */ - xTaskNotifyWait(0x00, 0x0F, NULL, 100); + if (!notifSent) { + if (xTaskNotifyWait(0x00, 0x0F, NULL, 25) == pdPASS) { + osDelay(1); + } + } + notifSent = false; /* Read the FUSB302B status and interrupt registers */ fusb_get_status(&status); - /* If the I_GCRCSENT flag is set, tell the Protocol RX thread */ - //This means a message was recieved with a good CRC - if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) { - ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT); - } - if ((status.status1 & FUSB_STATUS1_RX_EMPTY) == 0) { - ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT); - } - /* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX * thread */ - events = 0; - if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) { ProtocolTransmit::notify( ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_TXSENT); + notifSent = true; } if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) { ProtocolTransmit::notify( ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_RETRYFAIL); + notifSent = true; + } + + /* If the I_GCRCSENT flag is set, tell the Protocol RX thread */ + //This means a message was recieved with a good CRC + if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) { + ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT); + notifSent = true; } /* If the I_HARDRST or I_HARDSENT flag is set, tell the Hard Reset @@ -74,9 +78,11 @@ void InterruptHandler::Thread(const void *arg) { events = 0; if (status.interrupta & FUSB_INTERRUPTA_I_HARDRST) { -// events |= PDB_EVT_HARDRST_I_HARDRST; + events |= PDB_EVT_HARDRST_I_HARDRST; + notifSent = true; } else if (status.interrupta & FUSB_INTERRUPTA_I_HARDSENT) { events |= PDB_EVT_HARDRST_I_HARDSENT; + notifSent = true; } if (events) { ResetHandler::notify(events); @@ -86,6 +92,7 @@ void InterruptHandler::Thread(const void *arg) { if (status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP && status.status1 & FUSB_STATUS1_OVRTEMP) { PolicyEngine::notify(PDB_EVT_PE_I_OVRTEMP); + notifSent = true; } } } @@ -93,6 +100,6 @@ volatile uint8_t irqs = 0; void InterruptHandler::irqCallback() { irqs++; BaseType_t taskWoke = pdFALSE; - xTaskNotifyFromISR(TaskHandle, 0x0F, eNotifyAction::eSetBits, &taskWoke); + xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, &taskWoke); portYIELD_FROM_ISR(taskWoke); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp index da79efc8..0682f6eb 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -45,6 +45,8 @@ StaticQueue_t PolicyEngine::xStaticQueue; uint8_t PolicyEngine::ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)]; QueueHandle_t PolicyEngine::messagesWaiting; +EventGroupHandle_t PolicyEngine::xEventGroupHandle; +StaticEventGroup_t PolicyEngine::xCreatedEventGroup; void PolicyEngine::init() { messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue); @@ -52,10 +54,21 @@ void PolicyEngine::init() { osThreadStaticDef(Task, pe_task, PDB_PRIO_PE, 0, TaskStackSize, TaskBuffer, &TaskControlBlock); TaskHandle = osThreadCreate(osThread(Task), NULL); + xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup); } void PolicyEngine::notify(uint32_t notification) { - xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits); + notification = notification + & ( + PDB_EVT_PE_RESET | PDB_EVT_PE_MSG_RX | PDB_EVT_PE_TX_DONE + | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_HARD_SENT + | PDB_EVT_PE_I_OVRTEMP | PDB_EVT_PE_PPS_REQUEST); + if (notification) { + xEventGroupSetBits(xEventGroupHandle, notification); + } else { + asm("bkpt"); + } + } void PolicyEngine::pe_task(const void *arg) { @@ -181,13 +194,13 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_wait_cap() { if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_1_0) { /* If the other end is using at least version 3.0, we'll * use version 3.0. */ -// if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { -// hdr_template |= PD_SPECREV_3_0; -// /* Otherwise, use 2.0. Don't worry about the 1.0 case -// * because we don't have hardware for PD 1.0 signaling. */ -// } else { - hdr_template |= PD_SPECREV_2_0; -// } + if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { + hdr_template |= PD_SPECREV_3_0; + /* Otherwise, use 2.0. Don't worry about the 1.0 case + * because we don't have hardware for PD 1.0 signaling. */ + } else { + hdr_template |= PD_SPECREV_2_0; + } } return PESinkEvalCap; /* If the message was a Soft_Reset, do the soft reset procedure */ @@ -242,11 +255,11 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_eval_cap() { } PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { - waitForEvent( - PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET, 0); + /* Transmit the request */ ProtocolTransmit::pushMessage(&_last_dpm_request); -//Send indication that there is a message pending + waitForEvent(0xFFFF, 0); //clear pending + //Send indication that there is a message pending ProtocolTransmit::notify( ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX); eventmask_t evt = waitForEvent( @@ -257,7 +270,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { return PESinkTransitionDefault; } /* If the message transmission failed, send a hard reset */ - if ((evt & PDB_EVT_PE_TX_DONE) == 0) { + if ((evt & PDB_EVT_PE_TX_ERR) == PDB_EVT_PE_TX_ERR) { return PESinkHardReset; } @@ -794,9 +807,9 @@ bool PolicyEngine::heatingAllowed() { } uint32_t PolicyEngine::waitForEvent(uint32_t mask, uint32_t ticksToWait) { - uint32_t pulNotificationValue; - xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait); - return pulNotificationValue & mask; + return xEventGroupWaitBits(xEventGroupHandle, mask, mask, pdFALSE, + ticksToWait); + } bool PolicyEngine::isPD3_0() { diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h index 08f9543f..2eae3aca 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h @@ -112,6 +112,8 @@ private: static enum policy_engine_state pe_sink_chunk_received(); static enum policy_engine_state pe_sink_not_supported_received(); static enum policy_engine_state pe_sink_source_unresponsive(); + static EventGroupHandle_t xEventGroupHandle; + static StaticEventGroup_t xCreatedEventGroup; static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait = portMAX_DELAY); //Task resources diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp index 2099d210..26cc0a16 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp @@ -6,7 +6,7 @@ */ #include "pd.h" #include "policy_engine.h" - +#include "BSP_PD.h" /* The current draw when the output is disabled */ #define DPM_MIN_CURRENT PD_MA2PDI(50) /* @@ -55,32 +55,45 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability( /* Make sure we have configuration */ /* Look at the PDOs to see if one matches our desires */ - for (uint8_t i = 0; i < numobj; i++) { - /* If we have a fixed PDO, its V equals our desired V, and its I is - * at least our desired I */ - if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) { - //This is a fixed PDO entry - int voltage = PD_PDV2MV( - PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities->obj[i])); - int current = PD_PDO_SRC_FIXED_CURRENT_GET(capabilities->obj[i]); - if (voltage == 9000) { +//Look against USB_PD_Desired_Levels to select in order of preference + for (uint8_t desiredLevel = 0; desiredLevel < USB_PD_Desired_Levels_Len; + desiredLevel++) { + for (uint8_t i = 0; i < numobj; i++) { + /* If we have a fixed PDO, its V equals our desired V, and its I is + * at least our desired I */ + if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) { + //This is a fixed PDO entry + int voltage = PD_PDV2MV( + PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities->obj[i])); + int current = PD_PDO_SRC_FIXED_CURRENT_GET( + capabilities->obj[i]); + uint16_t desiredVoltage = USB_PD_Desired_Levels[(desiredLevel + * 2) + 0]; + uint16_t desiredminCurrent = USB_PD_Desired_Levels[(desiredLevel + * 2) + 1]; + //As pd stores current in 10mA increments, divide by 10 + desiredminCurrent /= 10; + if (voltage == desiredVoltage) { + if (current >= desiredminCurrent) { + /* We got what we wanted, so build a request for that */ + request->hdr = hdr_template | PD_MSGTYPE_REQUEST + | PD_NUMOBJ(1); - /* We got what we wanted, so build a request for that */ - request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); + /* GiveBack disabled */ + request->obj[0] = + PD_RDO_FV_MAX_CURRENT_SET( + current) | PD_RDO_FV_CURRENT_SET(current) + | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1); - /* GiveBack disabled */ - request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET( - current) | PD_RDO_FV_CURRENT_SET(current) - | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1); + request->obj[0] |= PD_RDO_USB_COMMS; - request->obj[0] |= PD_RDO_USB_COMMS; + /* Update requested voltage */ + _requested_voltage = voltage; - /* Update requested voltage */ - _requested_voltage = voltage; - - return true; + return true; + } + } } - } #if 0 /* If we have a PPS APDO, our desired V lies within its range, and * its I is at least our desired I */ @@ -110,6 +123,7 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability( // return true; } #endif + } } /* If there's a PDO in the voltage range, use it */ // int8_t i = dpm_get_range_fixed_pdo_index(caps, scfg); diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp index fae4184e..68a897df 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp @@ -35,11 +35,12 @@ uint8_t ProtocolReceive::_tx_messageidcounter; ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_wait_phy() { /* Wait for an event */ _rx_messageid = 0; - eventmask_t evt = waitForEvent(0xFFFFFFFF); + eventmask_t evt = waitForEvent( + PDB_EVT_PRLRX_RESET | PDB_EVT_PRLRX_I_GCRCSENT); /* If we got a reset event, reset */ if (evt & PDB_EVT_PRLRX_RESET) { -// waitForEvent(PDB_EVT_PRLRX_RESET, 0); + waitForEvent(PDB_EVT_PRLRX_RESET, 0); return PRLRxWaitPHY; } /* If we got an I_GCRCSENT event, read the message and decide what to do */ @@ -99,11 +100,10 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_check_messageid( /* Otherwise, there's either no stored ID or this message has an ID we * haven't just seen. Transition to the Store_MessageID state. */ - /*if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) { - return PRLRxWaitPHY; - } else*/ - rxCounter++; - { + if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) { + return PRLRxWaitPHY; + } else { + rxCounter++; return PRLRxStoreMessageID; } } @@ -131,9 +131,12 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_store_messageid( return PRLRxWaitPHY; } +EventGroupHandle_t ProtocolReceive::xEventGroupHandle; +StaticEventGroup_t ProtocolReceive::xCreatedEventGroup; void ProtocolReceive::init() { osThreadStaticDef(Task, thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, &TaskControlBlock); + xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup); TaskHandle = osThreadCreate(osThread(Task), NULL); } @@ -165,14 +168,10 @@ void ProtocolReceive::thread(const void *args) { } void ProtocolReceive::notify(uint32_t notification) { - if (notification == PDB_EVT_PRLRX_I_GCRCSENT) { -// asm("bkpt"); - } - xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits); + xEventGroupSetBits(xEventGroupHandle, notification); } uint32_t ProtocolReceive::waitForEvent(uint32_t mask, uint32_t ticksToWait) { - uint32_t pulNotificationValue; - xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait); - return pulNotificationValue & mask; + return xEventGroupWaitBits(xEventGroupHandle, mask, mask, + pdFALSE, ticksToWait); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h index 579c5ee1..274f506b 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h @@ -33,6 +33,8 @@ public: private: static void thread(const void *args); + static EventGroupHandle_t xEventGroupHandle; + static StaticEventGroup_t xCreatedEventGroup; static osThreadId TaskHandle; static const size_t TaskStackSize = 1024 / 4; static uint32_t TaskBuffer[TaskStackSize]; diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp index 9fef236b..28bac16c 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp @@ -64,15 +64,15 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_message() | (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD | (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX); - if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) { + if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) { return PRLTxPHYReset; } - if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) { + if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) { return PRLTxDiscardMessage; } /* If the policy engine is trying to send a message */ - if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX) { + if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX) { /* Get the message */ getMessage(); @@ -110,10 +110,10 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_mess (uint32_t) Notifications::PDB_EVT_PRLTX_RESET | (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD, 0); - if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) { + if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) { return PRLTxPHYReset; } - if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) { + if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) { return PRLTxDiscardMessage; } @@ -126,7 +126,8 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_mess /* If we're starting an AMS, wait for permission to transmit */ evt = waitForEvent((uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS, 0); - if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS) { + if ((uint32_t) evt + & (uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS) { while (fusb_get_typec_current() != fusb_sink_tx_ok) { osDelay(1); } @@ -151,19 +152,19 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_response( | (uint32_t) Notifications::PDB_EVT_PRLTX_I_TXSENT | (uint32_t) Notifications::PDB_EVT_PRLTX_I_RETRYFAIL); - if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) { + if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) { return PRLTxPHYReset; } - if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) { + if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) { return PRLTxDiscardMessage; } /* If the message was sent successfully */ - if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_I_TXSENT) { + if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_I_TXSENT) { return PRLTxMatchMessageID; } /* If the message failed to be sent */ - if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_I_RETRYFAIL) { + if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_I_RETRYFAIL) { return PRLTxTransmissionError; } @@ -259,8 +260,10 @@ void ProtocolTransmit::thread(const void *args) { } } +EventGroupHandle_t ProtocolTransmit::xEventGroupHandle; +StaticEventGroup_t ProtocolTransmit::xCreatedEventGroup; void ProtocolTransmit::notify(ProtocolTransmit::Notifications notification) { - xTaskNotify(TaskHandle, (uint32_t )notification, eNotifyAction::eSetBits); + xEventGroupSetBits(xEventGroupHandle, (uint32_t) notification); } void ProtocolTransmit::init() { @@ -270,6 +273,7 @@ void ProtocolTransmit::init() { osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PE, 0, TaskStackSize, TaskBuffer, &TaskControlBlock); TaskHandle = osThreadCreate(osThread(pd_txTask), NULL); + xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup); } void ProtocolTransmit::pushMessage(union pd_msg *msg) { @@ -287,7 +291,6 @@ void ProtocolTransmit::getMessage() { ProtocolTransmit::Notifications ProtocolTransmit::waitForEvent(uint32_t mask, uint32_t ticksToWait) { - uint32_t pulNotificationValue; - xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait); - return (Notifications) (pulNotificationValue & mask); + return (Notifications) xEventGroupWaitBits(xEventGroupHandle, mask, mask, + pdFALSE, ticksToWait); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h index 69c1c564..50bb278d 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h @@ -43,7 +43,8 @@ public: static void notify(Notifications notification); private: static void thread(const void *args); - + static EventGroupHandle_t xEventGroupHandle; + static StaticEventGroup_t xCreatedEventGroup; static osThreadId TaskHandle; static const size_t TaskStackSize = 1024 / 4; static uint32_t TaskBuffer[TaskStackSize]; diff --git a/workspace/TS100/LinkerScript.ld b/workspace/TS100/LinkerScript.ld index fe5d6a2b..70b01f6c 100644 --- a/workspace/TS100/LinkerScript.ld +++ b/workspace/TS100/LinkerScript.ld @@ -14,7 +14,7 @@ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K /* LOCAL_BUILD*/ -ROM (rx) : ORIGIN = 0x08000000, LENGTH = 46K +ROM (rx) : ORIGIN = 0x08000000, LENGTH = 48K /* production*/ /*ROM (rx) : ORIGIN = 0x08004000, LENGTH = 46K*/ From 4441a5ca930f4a1774530913de888544d57de0ff Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 22 Jul 2020 22:54:55 +1000 Subject: [PATCH 20/53] Handle NTC in TS80P --- workspace/TS100/Core/BSP/Miniware/BSP.cpp | 131 +++++++++++++++++++--- workspace/TS100/Core/Inc/FreeRTOSConfig.h | 2 +- 2 files changed, 117 insertions(+), 16 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/BSP.cpp b/workspace/TS100/Core/BSP/Miniware/BSP.cpp index df32c8e2..3b3eb2c2 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP.cpp +++ b/workspace/TS100/Core/BSP/Miniware/BSP.cpp @@ -16,8 +16,108 @@ history rawTempFilter = { { 0 }, 0, 0 }; void resetWatchdog() { HAL_IWDG_Refresh(&hiwdg); } - +#ifdef MODEL_TS80P +//Lookup table for the NTC +//Stored as ADCReading,Temp in degC +static const uint16_t NTCHandleLookup[] = { +//ADC Reading , Temp in C + 29189, 0, // + 29014, 1, // + 28832, 2, // + 28644, 3, // + 28450, 4, // + 28249, 5, // + 28042, 6, // + 27828, 7, // + 27607, 8, // + 27380, 9, // + 27146, 10, // + 26906, 11, // + 26660, 12, // + 26407, 13, // + 26147, 14, // + 25882, 15, // + 25610, 16, // + 25332, 17, // + 25049, 18, // + 24759, 19, // + 24465, 20, // + 24164, 21, // + 23859, 22, // + 23549, 23, // + 23234, 24, // + 22915, 25, // + 22591, 26, // + 22264, 27, // + 21933, 28, // + 21599, 29, // + 21261, 30, // + 20921, 31, // + 20579, 32, // + 20234, 33, // + 19888, 34, // + 19541, 35, // + 19192, 36, // + 18843, 37, // + 18493, 38, // + 18143, 39, // + 17793, 40, // + 17444, 41, // + 17096, 42, // + 16750, 43, // + 16404, 44, // + 16061, 45, // + 15719, 46, // + 15380, 47, // + 15044, 48, // + 14710, 49, // + 14380, 50, // + 14053, 51, // + 13729, 52, // + 13410, 53, // + 13094, 54, // + 12782, 55, // + 12475, 56, // + 12172, 57, // + 11874, 58, // + 11580, 59, // + 11292, 60, // + 11008, 61, // + 10729, 62, // + 10455, 63, // + 10187, 64, // + 9923, 65, // + 9665, 66, // + 9412, 67, // + 9164, 68, // + 8921, 69, // + 8684, 70, // + 8451, 71, // + 8225, 72, // + 8003, 73, // + 7786, 74, // + 7575, 75, // + 7368, 76, // + 7167, 77, // + 6970, 78, // + 6779, 79, // + 6592, 80, // + }; +#endif uint16_t getHandleTemperature() { +#ifdef MODEL_TS80P + //TS80P uses 100k NTC resistors instead + //NTCG104EF104FT1X from TDK + //For now not doing interpolation + int32_t result = getADC(0); + for (int i = 0; i < (sizeof(NTCHandleLookup) / (2 * sizeof(uint16_t))); + i++) { + if (result > NTCHandleLookup[(i * 2) + 0]) { + return NTCHandleLookup[(i * 2) + 1] * 10; + } + } + return 0; +#else // We return the current handle temperature in X10 C // TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for // example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) = @@ -32,14 +132,15 @@ uint16_t getHandleTemperature() { result *= 100; result /= 993; return result; +#endif } uint16_t getTipInstantTemperature() { uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits uint16_t readings[8]; - //Looking to reject the highest outlier readings. - //As on some hardware these samples can run into the op-amp recovery time - //Once this time is up the signal stabilises quickly, so no need to reject minimums +//Looking to reject the highest outlier readings. +//As on some hardware these samples can run into the op-amp recovery time +//Once this time is up the signal stabilises quickly, so no need to reject minimums readings[0] = hadc1.Instance->JDR1; readings[1] = hadc1.Instance->JDR2; readings[2] = hadc1.Instance->JDR3; @@ -66,10 +167,10 @@ uint16_t getTipRawTemp(uint8_t refresh) { } uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { - // ADC maximum is 32767 == 3.3V at input == 28.05V at VIN - // Therefore we can divide down from there - // Multiplying ADC max by 4 for additional calibration options, - // ideal term is 467 +// ADC maximum is 32767 == 3.3V at input == 28.05V at VIN +// Therefore we can divide down from there +// Multiplying ADC max by 4 for additional calibration options, +// ideal term is 467 #ifdef MODEL_TS100 #define BATTFILTERDEPTH 32 #else @@ -143,13 +244,13 @@ void unstick_I2C() { int timeout = 100; int timeout_cnt = 0; - // 1. Clear PE bit. +// 1. Clear PE bit. hi2c1.Instance->CR1 &= ~(0x0001); /**I2C1 GPIO Configuration PB6 ------> I2C1_SCL PB7 ------> I2C1_SDA */ - // 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR). +// 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR). GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; @@ -176,7 +277,7 @@ void unstick_I2C() { return; } - // 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain. +// 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain. GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; @@ -190,20 +291,20 @@ void unstick_I2C() { HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); - // 13. Set SWRST bit in I2Cx_CR1 register. +// 13. Set SWRST bit in I2Cx_CR1 register. hi2c1.Instance->CR1 |= 0x8000; asm("nop"); - // 14. Clear SWRST bit in I2Cx_CR1 register. +// 14. Clear SWRST bit in I2Cx_CR1 register. hi2c1.Instance->CR1 &= ~0x8000; asm("nop"); - // 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register +// 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register hi2c1.Instance->CR1 |= 0x0001; - // Call initialization function. +// Call initialization function. HAL_I2C_Init(&hi2c1); } diff --git a/workspace/TS100/Core/Inc/FreeRTOSConfig.h b/workspace/TS100/Core/Inc/FreeRTOSConfig.h index 820ca8b7..51a1f472 100644 --- a/workspace/TS100/Core/Inc/FreeRTOSConfig.h +++ b/workspace/TS100/Core/Inc/FreeRTOSConfig.h @@ -98,7 +98,7 @@ extern uint32_t SystemCoreClock; #define configUSE_IDLE_HOOK 1 #define configUSE_TICK_HOOK 0 #define configCPU_CLOCK_HZ ( SystemCoreClock ) -#define configTICK_RATE_HZ ((TickType_t)1000) +#define configTICK_RATE_HZ ((TickType_t)100) #define configMAX_PRIORITIES ( 6 ) #define configMINIMAL_STACK_SIZE ((uint16_t)256) #define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/ From 1f6dfe5da593029803344ca73ca238ec85cc7f3f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 22 Jul 2020 22:59:20 +1000 Subject: [PATCH 21/53] MVP --- workspace/TS100/Core/Src/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/workspace/TS100/Core/Src/main.cpp b/workspace/TS100/Core/Src/main.cpp index 23cd5648..ec190be6 100644 --- a/workspace/TS100/Core/Src/main.cpp +++ b/workspace/TS100/Core/Src/main.cpp @@ -68,10 +68,10 @@ int main(void) { GUITaskStackSize, GUITaskBuffer, &GUITaskControlBlock); GUITaskHandle = osThreadCreate(osThread(GUITask), NULL); -// /* definition and creation of PIDTask */ -// osThreadStaticDef(PIDTask, startPIDTask, osPriorityRealtime, 0, -// PIDTaskStackSize, PIDTaskBuffer, &PIDTaskControlBlock); -// PIDTaskHandle = osThreadCreate(osThread(PIDTask), NULL); + /* definition and creation of PIDTask */ + osThreadStaticDef(PIDTask, startPIDTask, osPriorityRealtime, 0, + PIDTaskStackSize, PIDTaskBuffer, &PIDTaskControlBlock); + PIDTaskHandle = osThreadCreate(osThread(PIDTask), NULL); osThreadStaticDef(MOVTask, startMOVTask, osPriorityNormal, 0, MOVTaskStackSize, MOVTaskBuffer, &MOVTaskControlBlock); From 9b0a071e9a0775236255adc26b3837b9a7a76fb2 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 22 Jul 2020 23:06:59 +1000 Subject: [PATCH 22/53] Cleaning up a bit for ease of integration --- workspace/TS100/Core/BSP/Miniware/I2CBB.cpp | 2 ++ workspace/TS100/Core/BSP/Miniware/I2CBB.hpp | 3 ++- .../TS100/Core/{Drivers/FUSB302 => BSP/Miniware}/fusb302b.cpp | 0 3 files changed, 4 insertions(+), 1 deletion(-) rename workspace/TS100/Core/{Drivers/FUSB302 => BSP/Miniware}/fusb302b.cpp (100%) diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp index 57aca422..14994c39 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp @@ -5,6 +5,7 @@ * Author: Ralim */ +#ifdef MODEL_TS80P #include #include "FreeRTOS.h" #define SCL_HIGH() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_SET) @@ -318,3 +319,4 @@ bool I2CBB::lock2() { } return a; } +#endif diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp b/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp index 213dd9c1..494bfe22 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp +++ b/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp @@ -7,6 +7,7 @@ #ifndef BSP_MINIWARE_I2CBB_HPP_ #define BSP_MINIWARE_I2CBB_HPP_ +#ifdef MODEL_TS80P #include "BSP.h" #include "Setup.h" #include "Pins.h" @@ -48,5 +49,5 @@ private: static uint8_t read_bit(); static void write_bit(uint8_t val); }; - +#endif #endif /* BSP_MINIWARE_I2CBB_HPP_ */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp similarity index 100% rename from workspace/TS100/Core/Drivers/FUSB302/fusb302b.cpp rename to workspace/TS100/Core/BSP/Miniware/fusb302b.cpp From b40a21470b0b5fddcea6b966722036b2fe51a67f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 22 Jul 2020 23:09:46 +1000 Subject: [PATCH 23/53] Update fusbpd.cpp --- workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp index 672f1746..5c821515 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -5,8 +5,10 @@ * Author: Ralim */ +#ifdef MODEL_TS80P #include #include +#include "BSP.h" #include "I2CBB.hpp" #include "fusb302b.h" #include "policy_engine.h" @@ -36,3 +38,4 @@ void fusb302_start_processing() { /* Create the INT_N thread. */ InterruptHandler::init(); } +#endif From ff65e6437b3be205330ef13b7ec11d348c79a54a Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 23 Jul 2020 22:45:00 +1000 Subject: [PATCH 24/53] Shrink flash usage _just_ enough --- workspace/TS100/Core/BSP/BSP.h | 2 +- workspace/TS100/Core/BSP/Miniware/BSP.cpp | 84 +++--- workspace/TS100/Core/BSP/Miniware/IRQ.cpp | 1 + workspace/TS100/Core/BSP/Miniware/Setup.c | 6 +- .../Src/stm32f1xx_hal_adc_ex.c | 52 ++-- .../Src/stm32f1xx_hal_rcc.c | 163 ------------ .../Src/stm32f1xx_hal_tim.c | 246 +++++++++--------- .../Core/BSP/Miniware/system_stm32f1xx.c | 2 +- .../TS100/Core/Drivers/FUSB302/hard_reset.h | 2 +- .../TS100/Core/Drivers/FUSB302/int_n.cpp | 6 +- .../Core/Drivers/FUSB302/policy_engine.cpp | 98 +------ .../Core/Drivers/FUSB302/policy_engine.h | 9 - .../Drivers/FUSB302/policy_engine_user.cpp | 22 +- workspace/TS100/Core/Drivers/Font.h | 12 - workspace/TS100/Core/Threads/GUIThread.cpp | 21 +- workspace/TS100/LinkerScript.ld | 4 +- 16 files changed, 213 insertions(+), 517 deletions(-) diff --git a/workspace/TS100/Core/BSP/BSP.h b/workspace/TS100/Core/BSP/BSP.h index 2cc0f522..19e8b15d 100644 --- a/workspace/TS100/Core/BSP/BSP.h +++ b/workspace/TS100/Core/BSP/BSP.h @@ -48,7 +48,7 @@ void reboot(); // Returns 1 if the logo was printed so that the unit waits for the timeout or button uint8_t showBootLogoIfavailable(); //delay wrapper for delay using the hardware timer (used before RTOS) -void delay_ms(uint16_t count); +void delay_ms(uint16_t count) ; //Used to allow knowledge of if usb_pd is being used uint8_t usb_pd_detect(); //Returns 0 when the irq line is pulled down diff --git a/workspace/TS100/Core/BSP/Miniware/BSP.cpp b/workspace/TS100/Core/BSP/Miniware/BSP.cpp index 3b3eb2c2..d256cdec 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP.cpp +++ b/workspace/TS100/Core/BSP/Miniware/BSP.cpp @@ -51,57 +51,37 @@ static const uint16_t NTCHandleLookup[] = { 22264, 27, // 21933, 28, // 21599, 29, // - 21261, 30, // - 20921, 31, // - 20579, 32, // - 20234, 33, // - 19888, 34, // - 19541, 35, // - 19192, 36, // - 18843, 37, // - 18493, 38, // - 18143, 39, // - 17793, 40, // - 17444, 41, // - 17096, 42, // - 16750, 43, // - 16404, 44, // - 16061, 45, // - 15719, 46, // - 15380, 47, // - 15044, 48, // - 14710, 49, // - 14380, 50, // - 14053, 51, // - 13729, 52, // - 13410, 53, // - 13094, 54, // - 12782, 55, // - 12475, 56, // - 12172, 57, // - 11874, 58, // - 11580, 59, // - 11292, 60, // - 11008, 61, // - 10729, 62, // - 10455, 63, // - 10187, 64, // - 9923, 65, // - 9665, 66, // - 9412, 67, // - 9164, 68, // - 8921, 69, // - 8684, 70, // - 8451, 71, // - 8225, 72, // - 8003, 73, // - 7786, 74, // - 7575, 75, // - 7368, 76, // - 7167, 77, // - 6970, 78, // - 6779, 79, // - 6592, 80, // +// 21261, 30, // +// 20921, 31, // +// 20579, 32, // +// 20234, 33, // +// 19888, 34, // +// 19541, 35, // +// 19192, 36, // +// 18843, 37, // +// 18493, 38, // +// 18143, 39, // +// 17793, 40, // +// 17444, 41, // +// 17096, 42, // +// 16750, 43, // +// 16404, 44, // +// 16061, 45, // +// 15719, 46, // +// 15380, 47, // +// 15044, 48, // +// 14710, 49, // +// 14380, 50, // +// 14053, 51, // +// 13729, 52, // +// 13410, 53, // +// 13094, 54, // +// 12782, 55, // +// 12475, 56, // +// 12172, 57, // +// 11874, 58, // +// 11580, 59, // +// 11292, 60, // }; #endif uint16_t getHandleTemperature() { @@ -110,7 +90,7 @@ uint16_t getHandleTemperature() { //NTCG104EF104FT1X from TDK //For now not doing interpolation int32_t result = getADC(0); - for (int i = 0; i < (sizeof(NTCHandleLookup) / (2 * sizeof(uint16_t))); + for (uint32_t i = 0; i < (sizeof(NTCHandleLookup) / (2 * sizeof(uint16_t))); i++) { if (result > NTCHandleLookup[(i * 2) + 0]) { return NTCHandleLookup[(i * 2) + 1] * 10; diff --git a/workspace/TS100/Core/BSP/Miniware/IRQ.cpp b/workspace/TS100/Core/BSP/Miniware/IRQ.cpp index 15d26b64..fe7b4b15 100644 --- a/workspace/TS100/Core/BSP/Miniware/IRQ.cpp +++ b/workspace/TS100/Core/BSP/Miniware/IRQ.cpp @@ -44,5 +44,6 @@ void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { } void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { + (void)GPIO_Pin; InterruptHandler::irqCallback(); } diff --git a/workspace/TS100/Core/BSP/Miniware/Setup.c b/workspace/TS100/Core/BSP/Miniware/Setup.c index b8df1cc0..2d7f2c15 100644 --- a/workspace/TS100/Core/BSP/Miniware/Setup.c +++ b/workspace/TS100/Core/BSP/Miniware/Setup.c @@ -33,9 +33,9 @@ static void MX_ADC2_Init(void); void Setup_HAL() { SystemClock_Config(); -// __HAL_AFIO_REMAP_SWJ_DISABLE() -// ; - __HAL_AFIO_REMAP_SWJ_NOJTAG(); + __HAL_AFIO_REMAP_SWJ_DISABLE() + ; +// __HAL_AFIO_REMAP_SWJ_NOJTAG(); MX_GPIO_Init(); MX_DMA_Init(); MX_I2C1_Init(); diff --git a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c index 2d539a22..5619d38a 100644 --- a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c +++ b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c @@ -1041,32 +1041,32 @@ HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef* hadc, ADC_I /* conversions is forced to 0x00 for alignment over all STM32 devices. */ /* - if scan mode is enabled, injected channels sequence length is set to */ /* parameter "InjectedNbrOfConversion". */ - if (hadc->Init.ScanConvMode == ADC_SCAN_DISABLE) - { - if (sConfigInjected->InjectedRank == ADC_INJECTED_RANK_1) - { - /* Clear the old SQx bits for all injected ranks */ - MODIFY_REG(hadc->Instance->JSQR , - ADC_JSQR_JL | - ADC_JSQR_JSQ4 | - ADC_JSQR_JSQ3 | - ADC_JSQR_JSQ2 | - ADC_JSQR_JSQ1 , - ADC_JSQR_RK_JL(sConfigInjected->InjectedChannel, - ADC_INJECTED_RANK_1, - 0x01U)); - } - /* If another injected rank than rank1 was intended to be set, and could */ - /* not due to ScanConvMode disabled, error is reported. */ - else - { - /* Update ADC state machine to error */ - SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG); - - tmp_hal_status = HAL_ERROR; - } - } - else +// if (hadc->Init.ScanConvMode == ADC_SCAN_DISABLE) +// { +// if (sConfigInjected->InjectedRank == ADC_INJECTED_RANK_1) +// { +// /* Clear the old SQx bits for all injected ranks */ +// MODIFY_REG(hadc->Instance->JSQR , +// ADC_JSQR_JL | +// ADC_JSQR_JSQ4 | +// ADC_JSQR_JSQ3 | +// ADC_JSQR_JSQ2 | +// ADC_JSQR_JSQ1 , +// ADC_JSQR_RK_JL(sConfigInjected->InjectedChannel, +// ADC_INJECTED_RANK_1, +// 0x01U)); +// } +// /* If another injected rank than rank1 was intended to be set, and could */ +// /* not due to ScanConvMode disabled, error is reported. */ +// else +// { +// /* Update ADC state machine to error */ +// SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG); +// +// tmp_hal_status = HAL_ERROR; +// } +// } +// else { /* Since injected channels rank conv. order depends on total number of */ /* injected conversions, selected rank must be below or equal to total */ diff --git a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c index e146d9b6..240c5d11 100644 --- a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c +++ b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c @@ -369,57 +369,6 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType)); /*------------------------------- HSE Configuration ------------------------*/ - if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE) - { - /* Check the parameters */ - assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState)); - - /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */ - if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_HSE) - || ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE))) - { - if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF)) - { - return HAL_ERROR; - } - } - else - { - /* Set the new HSE configuration ---------------------------------------*/ - __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState); - - - /* Check the HSE State */ - if(RCC_OscInitStruct->HSEState != RCC_HSE_OFF) - { - /* Get Start Tick */ - tickstart = HAL_GetTick(); - - /* Wait till HSE is ready */ - while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET) - { - if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } - } - else - { - /* Get Start Tick */ - tickstart = HAL_GetTick(); - - /* Wait till HSE is disabled */ - while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET) - { - if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } - } - } - } /*----------------------------- HSI Configuration --------------------------*/ if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) { @@ -486,121 +435,9 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) } } /*------------------------------ LSI Configuration -------------------------*/ - if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) - { - /* Check the parameters */ - assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState)); - /* Check the LSI State */ - if(RCC_OscInitStruct->LSIState != RCC_LSI_OFF) - { - /* Enable the Internal Low Speed oscillator (LSI). */ - __HAL_RCC_LSI_ENABLE(); - - /* Get Start Tick */ - tickstart = HAL_GetTick(); - - /* Wait till LSI is ready */ - while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == RESET) - { - if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } - /* To have a fully stabilized clock in the specified range, a software delay of 1ms - should be added.*/ - RCC_Delay(1); - } - else - { - /* Disable the Internal Low Speed oscillator (LSI). */ - __HAL_RCC_LSI_DISABLE(); - - /* Get Start Tick */ - tickstart = HAL_GetTick(); - - /* Wait till LSI is disabled */ - while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) != RESET) - { - if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } - } - } /*------------------------------ LSE Configuration -------------------------*/ - if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) - { - FlagStatus pwrclkchanged = RESET; - /* Check the parameters */ - assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState)); - - /* Update LSE configuration in Backup Domain control register */ - /* Requires to enable write access to Backup Domain of necessary */ - if(__HAL_RCC_PWR_IS_CLK_DISABLED()) - { - __HAL_RCC_PWR_CLK_ENABLE(); - pwrclkchanged = SET; - } - - if(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP)) - { - /* Enable write access to Backup domain */ - SET_BIT(PWR->CR, PWR_CR_DBP); - - /* Wait for Backup domain Write protection disable */ - tickstart = HAL_GetTick(); - - while(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP)) - { - if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } - } - - /* Set the new LSE configuration -----------------------------------------*/ - __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState); - /* Check the LSE State */ - if(RCC_OscInitStruct->LSEState != RCC_LSE_OFF) - { - /* Get Start Tick */ - tickstart = HAL_GetTick(); - - /* Wait till LSE is ready */ - while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET) - { - if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } - } - else - { - /* Get Start Tick */ - tickstart = HAL_GetTick(); - - /* Wait till LSE is disabled */ - while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) != RESET) - { - if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } - } - - /* Require to disable power clock if necessary */ - if(pwrclkchanged == SET) - { - __HAL_RCC_PWR_CLK_DISABLE(); - } - } #if defined(RCC_CR_PLL2ON) /*-------------------------------- PLL2 Configuration -----------------------*/ diff --git a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c index 9a42f0ed..89c7f948 100644 --- a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c +++ b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c @@ -3968,129 +3968,129 @@ HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockCo } break; - case TIM_CLOCKSOURCE_ETRMODE1: - { - /* Check whether or not the timer instance supports external trigger input mode 1 (ETRF)*/ - assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance)); - - /* Check ETR input conditioning related parameters */ - assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); - assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); - assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); - - /* Configure the ETR Clock source */ - TIM_ETR_SetConfig(htim->Instance, - sClockSourceConfig->ClockPrescaler, - sClockSourceConfig->ClockPolarity, - sClockSourceConfig->ClockFilter); - /* Get the TIMx SMCR register value */ - tmpsmcr = htim->Instance->SMCR; - /* Reset the SMS and TS Bits */ - tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS); - /* Select the External clock mode1 and the ETRF trigger */ - tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1); - /* Write to TIMx SMCR */ - htim->Instance->SMCR = tmpsmcr; - } - break; - - case TIM_CLOCKSOURCE_ETRMODE2: - { - /* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/ - assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance)); - - /* Check ETR input conditioning related parameters */ - assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); - assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); - assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); - - /* Configure the ETR Clock source */ - TIM_ETR_SetConfig(htim->Instance, - sClockSourceConfig->ClockPrescaler, - sClockSourceConfig->ClockPolarity, - sClockSourceConfig->ClockFilter); - /* Enable the External clock mode2 */ - htim->Instance->SMCR |= TIM_SMCR_ECE; - } - break; - - case TIM_CLOCKSOURCE_TI1: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); - - /* Check TI1 input conditioning related parameters */ - assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); - assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); - - TIM_TI1_ConfigInputStage(htim->Instance, - sClockSourceConfig->ClockPolarity, - sClockSourceConfig->ClockFilter); - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1); - } - break; - case TIM_CLOCKSOURCE_TI2: - { - /* Check whether or not the timer instance supports external clock mode 1 (ETRF)*/ - assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); - - /* Check TI2 input conditioning related parameters */ - assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); - assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); - - TIM_TI2_ConfigInputStage(htim->Instance, - sClockSourceConfig->ClockPolarity, - sClockSourceConfig->ClockFilter); - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2); - } - break; - case TIM_CLOCKSOURCE_TI1ED: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); - - /* Check TI1 input conditioning related parameters */ - assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); - assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); - - TIM_TI1_ConfigInputStage(htim->Instance, - sClockSourceConfig->ClockPolarity, - sClockSourceConfig->ClockFilter); - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED); - } - break; - case TIM_CLOCKSOURCE_ITR0: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); - - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR0); - } - break; - case TIM_CLOCKSOURCE_ITR1: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); - - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR1); - } - break; - case TIM_CLOCKSOURCE_ITR2: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); - - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR2); - } - break; - case TIM_CLOCKSOURCE_ITR3: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); - - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR3); - } - break; +// case TIM_CLOCKSOURCE_ETRMODE1: +// { +// /* Check whether or not the timer instance supports external trigger input mode 1 (ETRF)*/ +// assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance)); +// +// /* Check ETR input conditioning related parameters */ +// assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); +// assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); +// assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); +// +// /* Configure the ETR Clock source */ +// TIM_ETR_SetConfig(htim->Instance, +// sClockSourceConfig->ClockPrescaler, +// sClockSourceConfig->ClockPolarity, +// sClockSourceConfig->ClockFilter); +// /* Get the TIMx SMCR register value */ +// tmpsmcr = htim->Instance->SMCR; +// /* Reset the SMS and TS Bits */ +// tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS); +// /* Select the External clock mode1 and the ETRF trigger */ +// tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1); +// /* Write to TIMx SMCR */ +// htim->Instance->SMCR = tmpsmcr; +// } +// break; +// +// case TIM_CLOCKSOURCE_ETRMODE2: +// { +// /* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/ +// assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance)); +// +// /* Check ETR input conditioning related parameters */ +// assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); +// assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); +// assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); +// +// /* Configure the ETR Clock source */ +// TIM_ETR_SetConfig(htim->Instance, +// sClockSourceConfig->ClockPrescaler, +// sClockSourceConfig->ClockPolarity, +// sClockSourceConfig->ClockFilter); +// /* Enable the External clock mode2 */ +// htim->Instance->SMCR |= TIM_SMCR_ECE; +// } +// break; +// +// case TIM_CLOCKSOURCE_TI1: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); +// +// /* Check TI1 input conditioning related parameters */ +// assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); +// assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); +// +// TIM_TI1_ConfigInputStage(htim->Instance, +// sClockSourceConfig->ClockPolarity, +// sClockSourceConfig->ClockFilter); +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1); +// } +// break; +// case TIM_CLOCKSOURCE_TI2: +// { +// /* Check whether or not the timer instance supports external clock mode 1 (ETRF)*/ +// assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); +// +// /* Check TI2 input conditioning related parameters */ +// assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); +// assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); +// +// TIM_TI2_ConfigInputStage(htim->Instance, +// sClockSourceConfig->ClockPolarity, +// sClockSourceConfig->ClockFilter); +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2); +// } +// break; +// case TIM_CLOCKSOURCE_TI1ED: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); +// +// /* Check TI1 input conditioning related parameters */ +// assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); +// assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); +// +// TIM_TI1_ConfigInputStage(htim->Instance, +// sClockSourceConfig->ClockPolarity, +// sClockSourceConfig->ClockFilter); +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED); +// } +// break; +// case TIM_CLOCKSOURCE_ITR0: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); +// +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR0); +// } +// break; +// case TIM_CLOCKSOURCE_ITR1: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); +// +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR1); +// } +// break; +// case TIM_CLOCKSOURCE_ITR2: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); +// +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR2); +// } +// break; +// case TIM_CLOCKSOURCE_ITR3: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); +// +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR3); +// } +// break; default: break; diff --git a/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c b/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c index 6af48671..fabf4234 100644 --- a/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c +++ b/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c @@ -11,7 +11,7 @@ #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) /* #define DATA_IN_ExtSRAM */ #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ -#define LOCAL_BUILD +//#define LOCAL_BUILD #ifndef LOCAL_BUILD #define VECT_TAB_OFFSET 0x00004000U /*!< Vector Table base offset field. This value must be a multiple of 0x200. */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h index 9466b33c..c28292f1 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h @@ -33,7 +33,7 @@ public: private: static void Thread(const void *arg); static osThreadId TaskHandle; - static const size_t TaskStackSize = 1536 / 2; + static const size_t TaskStackSize = 1536 / 3; static uint32_t TaskBuffer[TaskStackSize]; static osStaticThreadDef_t TaskControlBlock; static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait = diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index 21bdf5fd..5e745161 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -46,9 +46,7 @@ void InterruptHandler::Thread(const void *arg) { while (true) { /* If the INT_N line is low */ if (!notifSent) { - if (xTaskNotifyWait(0x00, 0x0F, NULL, 25) == pdPASS) { - osDelay(1); - } + xTaskNotifyWait(0x00, 0x0F, NULL, 25); } notifSent = false; /* Read the FUSB302B status and interrupt registers */ @@ -96,9 +94,7 @@ void InterruptHandler::Thread(const void *arg) { } } } -volatile uint8_t irqs = 0; void InterruptHandler::irqCallback() { - irqs++; BaseType_t taskWoke = pdFALSE; xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, &taskWoke); portYIELD_FROM_ISR(taskWoke); diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp index 0682f6eb..797f2353 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -23,14 +23,12 @@ #include "hard_reset.h" #include "fusb302b.h" bool PolicyEngine::pdNegotiationComplete; -bool PolicyEngine::pdHasEnteredLowPower; int PolicyEngine::current_voltage_mv; int PolicyEngine::_requested_voltage; bool PolicyEngine::_unconstrained_power; union pd_msg PolicyEngine::currentMessage; uint16_t PolicyEngine::hdr_template; bool PolicyEngine::_explicit_contract; -bool PolicyEngine::_min_power; int8_t PolicyEngine::_hard_reset_counter; int8_t PolicyEngine::_old_tcc_match; uint8_t PolicyEngine::_pps_index; @@ -58,17 +56,7 @@ void PolicyEngine::init() { } void PolicyEngine::notify(uint32_t notification) { - notification = notification - & ( - PDB_EVT_PE_RESET | PDB_EVT_PE_MSG_RX | PDB_EVT_PE_TX_DONE - | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_HARD_SENT - | PDB_EVT_PE_I_OVRTEMP | PDB_EVT_PE_PPS_REQUEST); - if (notification) { - xEventGroupSetBits(xEventGroupHandle, notification); - } else { - asm("bkpt"); - } - + xEventGroupSetBits(xEventGroupHandle, notification); } void PolicyEngine::pe_task(const void *arg) { @@ -310,7 +298,6 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { pdbs_dpm_transition_standby(); } - _min_power = false; return PESinkTransitionSink; /* If the message was a Soft_Reset, do the soft reset procedure */ } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET @@ -325,10 +312,6 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { return PESinkWaitCap; /* If we do have an explicit contract, go to the ready state */ } else { - /* If we got here from a Wait message, we Should run - * SinkRequestTimer in the Ready state. */ - _min_power = (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_WAIT); - return PESinkReady; } } else { @@ -361,9 +344,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_transition_sink() { _explicit_contract = true; /* Set the output appropriately */ - if (!_min_power) { - pdbs_dpm_transition_requested(); - } + pdbs_dpm_transition_requested(); return PESinkReady; /* If there was a protocol error, send a hard reset */ @@ -384,18 +365,9 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_ready() { eventmask_t evt; /* Wait for an event */ - if (_min_power) { - evt = waitForEvent( - PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET | PDB_EVT_PE_I_OVRTEMP - | PDB_EVT_PE_GET_SOURCE_CAP | PDB_EVT_PE_NEW_POWER - | PDB_EVT_PE_PPS_REQUEST, - PD_T_SINK_REQUEST); - } else { - evt = waitForEvent( - PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET | PDB_EVT_PE_I_OVRTEMP - | PDB_EVT_PE_GET_SOURCE_CAP | PDB_EVT_PE_NEW_POWER - | PDB_EVT_PE_PPS_REQUEST); - } + evt = waitForEvent( + PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET | PDB_EVT_PE_I_OVRTEMP + | PDB_EVT_PE_PPS_REQUEST); /* If we got reset signaling, transition to default */ if (evt & PDB_EVT_PE_RESET) { @@ -407,25 +379,6 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_ready() { return PESinkHardReset; } - /* If the DPM wants us to, send a Get_Source_Cap message */ - if (evt & PDB_EVT_PE_GET_SOURCE_CAP) { - /* Tell the protocol layer we're starting an AMS */ - ProtocolTransmit::notify( - ProtocolTransmit::Notifications::PDB_EVT_PRLTX_START_AMS); - return PESinkGetSourceCap; - } - - /* If the DPM wants new power, let it figure out what power it wants - * exactly. This isn't exactly the transition from the spec (that would be - * SelectCap, not EvalCap), but this works better with the particular - * design of this firmware. */ - if (evt & PDB_EVT_PE_NEW_POWER) { - /* Tell the protocol layer we're starting an AMS */ - ProtocolTransmit::notify( - ProtocolTransmit::Notifications::PDB_EVT_PRLTX_START_AMS); - return PESinkEvalCap; - } - /* If SinkPPSPeriodicTimer ran out, send a new request */ if (evt & PDB_EVT_PE_PPS_REQUEST) { /* Tell the protocol layer we're starting an AMS */ @@ -434,12 +387,6 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_ready() { return PESinkSelectCap; } - /* If no event was received, the timer ran out. */ - if (evt == 0) { - /* Repeat our Request message */ - return PESinkSelectCap; - } - /* If we received a message */ if (evt & PDB_EVT_PE_MSG_RX) { if (messageWaiting()) { @@ -488,16 +435,9 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_ready() { /* Handle GotoMin messages */ } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_GOTOMIN && PD_NUMOBJ_GET(&tempMessage) == 0) { - if (pdbs_dpm_giveback_enabled()) { - /* Transition to the minimum current level */ - pdbs_dpm_transition_min(); - _min_power = true; - return PESinkTransitionSink; - } else { - /* GiveBack is not supported */ + /* GiveBack is not supported */ + return PESinkSendNotSupported; - return PESinkSendNotSupported; - } /* Evaluate new Source_Capabilities */ } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOURCE_CAPABILITIES @@ -770,22 +710,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_not_supported_received() } PolicyEngine::policy_engine_state PolicyEngine::pe_sink_source_unresponsive() { - /* If the DPM can evaluate the Type-C Current advertisement */ - //TS80P doesnt -// if (cfg->dpm.evaluate_typec_current != NULL) { -// /* Make the DPM evaluate the Type-C Current advertisement */ -// int tcc_match = cfg->dpm.evaluate_typec_current(cfg, -// fusb_get_typec_current(&cfg->fusb)); -// -// /* If the last two readings are the same, set the output */ -// if (_old_tcc_match == tcc_match) { -// cfg->dpm.transition_typec(cfg); -// } -// -// /* Remember whether or not the last measurement succeeded */ -// _old_tcc_match = tcc_match; -// } - /* Wait tPDDebounce between measurements */ +//Sit and chill, as PD is not working osDelay(PD_T_PD_DEBOUNCE); return PESinkSourceUnresponsive; @@ -799,13 +724,6 @@ bool PolicyEngine::pdHasNegotiated() { return pdNegotiationComplete; } -bool PolicyEngine::heatingAllowed() { - if (pdHasNegotiated()) - return !pdHasEnteredLowPower; - //Not pd -- pass through - return true; -} - uint32_t PolicyEngine::waitForEvent(uint32_t mask, uint32_t ticksToWait) { return xEventGroupWaitBits(xEventGroupHandle, mask, mask, pdFALSE, ticksToWait); diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h index 2eae3aca..259b4df5 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h @@ -24,10 +24,6 @@ * Events for the Policy Engine thread, used internally + sent by user code * */ -/* Tell the PE to send a Get_Source_Cap message */ -#define PDB_EVT_PE_GET_SOURCE_CAP EVENT_MASK(7) -/* Tell the PE that new power is required */ -#define PDB_EVT_PE_NEW_POWER EVENT_MASK(8) #define PDB_EVT_PE_RESET EVENT_MASK(0) #define PDB_EVT_PE_MSG_RX EVENT_MASK(1) @@ -51,11 +47,8 @@ public: static void PPSTimerCallBack(); //Has pd negotiation completed static bool pdHasNegotiated(); - //Used in case the USB-C PD source requests minimum power - static bool heatingAllowed(); private: static bool pdNegotiationComplete; - static bool pdHasEnteredLowPower; static int current_voltage_mv; //The current voltage PD is expecting static int _requested_voltage; //The voltage the unit wanted to requests static bool _unconstrained_power; // If the source is unconstrained @@ -65,8 +58,6 @@ private: static uint16_t hdr_template; /* Whether or not we have an explicit contract */ static bool _explicit_contract; - /* Whether or not we're receiving minimum power */ - static bool _min_power; /* The number of hard resets we've sent */ static int8_t _hard_reset_counter; /* The result of the last Type-C Current match comparison */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp index 26cc0a16..c82ebecc 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp @@ -253,17 +253,12 @@ void PolicyEngine::pdbs_dpm_get_sink_capability(union pd_msg *cap) { cap->hdr = hdr_template | PD_MSGTYPE_SINK_CAPABILITIES | PD_NUMOBJ(numobj); } -bool PolicyEngine::pdbs_dpm_giveback_enabled() { - return false; -//We do not support giveback -} - bool PolicyEngine::pdbs_dpm_evaluate_typec_current( enum fusb_typec_current tcc) { -//This is for evaluating 5V static current advertised by resistors + //This is for evaluating 5V static current advertised by resistors /* We don't control the voltage anymore; it will always be 5 V. */ current_voltage_mv = _requested_voltage = 5000; -//For the soldering iron we accept this as a fallback, but it sucks + //For the soldering iron we accept this as a fallback, but it sucks return true; } @@ -278,27 +273,19 @@ void PolicyEngine::pdbs_dpm_transition_default() { current_voltage_mv = 5000; /* Turn the output off */ pdNegotiationComplete = false; - pdHasEnteredLowPower = true; } void PolicyEngine::pdbs_dpm_transition_min() { - pdHasEnteredLowPower = true; } void PolicyEngine::pdbs_dpm_transition_standby() { /* If the voltage is changing, enter Sink Standby */ - if (_requested_voltage != current_voltage_mv) { - /* For the PD Buddy Sink, entering Sink Standby is equivalent to - * turning the output off. However, we don't want to change the LED - * state for standby mode. */ - pdHasEnteredLowPower = true; - } + } void PolicyEngine::pdbs_dpm_transition_requested() { /* Cast the dpm_data to the right type */ pdNegotiationComplete = true; - pdHasEnteredLowPower = false; } void PolicyEngine::handleMessage(union pd_msg *msg) { @@ -314,8 +301,7 @@ void PolicyEngine::readMessage() { } void PolicyEngine::pdbs_dpm_transition_typec() { -//This means PD failed, so we either have a dump 5V only type C or a QC charger +//This means PD failed, so we either have a dumb 5V only type C or a QC charger //For now; treat this as failed neg pdNegotiationComplete = false; - pdHasEnteredLowPower = false; } diff --git a/workspace/TS100/Core/Drivers/Font.h b/workspace/TS100/Core/Drivers/Font.h index 761b2723..50932504 100644 --- a/workspace/TS100/Core/Drivers/Font.h +++ b/workspace/TS100/Core/Drivers/Font.h @@ -126,18 +126,6 @@ const uint8_t idleScreenBG[] = { 0x8A,0x84,0x82,0x81,0x80,0x80,0x80,0x40,0x40,0x20,0x18,0x07 }; -const uint8_t idleScreenBGF[] = { - //width = 84 - //height = 16 - 0xE0,0x18,0x04,0x02,0x02,0x01,0x41,0x81,0x01,0x01,0x65,0x99,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, - 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x04,0x18,0xE0,0x00,0x00,0xE0,0x18,0x04,0x02,0x02, - 0x01,0x01,0x41,0x61,0x61,0x61,0xE1,0xC1,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xC1, - 0xE1,0x61,0x61,0x61,0x41,0x01,0x02,0x02,0x04,0x18,0xE0,0x00, - 0x07,0x18,0x20,0x40,0x40,0x80,0x80,0x80,0x81,0x82,0x84,0x8A,0x92,0x82,0x82,0x82,0x80,0x82,0x80,0x82,0x82,0x82,0x87,0x87, - 0x85,0x87,0x85,0x87,0x87,0x85,0x85,0x85,0x85,0x87,0x82,0x80,0x40,0x40,0x20,0x18,0x07,0x00,0x00,0x07,0x18,0x20,0x40,0x40, - 0x80,0x80,0x82,0x86,0x86,0x86,0x87,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83, - 0x87,0x86,0x86,0x86,0x82,0x80,0x40,0x40,0x20,0x18,0x07,0x00 -}; /* * 16x16 icons diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index befbbef8..92cdc377 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -636,13 +636,22 @@ void showDebugMenu(void) { GUIDelay(); } } - +uint8_t idleScreenBGF[sizeof(idleScreenBG)]; /* StartGUITask function */ void startGUITask(void const *argument __unused) { uint8_t tempWarningState = 0; bool buttonLockout = false; bool tempOnDisplay = false; + { + //Generate the flipped screen into ram for later use +//flipped is generated by flipping each row + for(int row=0;row<2;row++){ + for (int x =0;x<84;x++){ + idleScreenBGF[(row*84)+x] =idleScreenBG[(row*84)+(83-x)]; + } + } + } getTipRawTemp(1); // reset filter OLED::setRotation(systemSettings.OrientationMode & 1); uint32_t ticks = xTaskGetTickCount(); @@ -665,16 +674,6 @@ void startGUITask(void const *argument __unused) { OLED::refresh(); waitForButtonPressOrTimeout(1000); } - - if (usb_pd_available) { - OLED::clearScreen(); - OLED::setFont(1); - OLED::setCursor(0, 0); - OLED::print(InputVoltageString); - OLED::refresh(); - waitForButtonPressOrTimeout(1000); - } - if (systemSettings.autoStartMode) { // jump directly to the autostart mode if (systemSettings.autoStartMode == 1) { diff --git a/workspace/TS100/LinkerScript.ld b/workspace/TS100/LinkerScript.ld index 70b01f6c..75be14f8 100644 --- a/workspace/TS100/LinkerScript.ld +++ b/workspace/TS100/LinkerScript.ld @@ -14,9 +14,9 @@ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K /* LOCAL_BUILD*/ -ROM (rx) : ORIGIN = 0x08000000, LENGTH = 48K +/*ROM (rx) : ORIGIN = 0x08000000, LENGTH = 48K*/ /* production*/ -/*ROM (rx) : ORIGIN = 0x08004000, LENGTH = 46K*/ + ROM (rx) : ORIGIN = 0x08004000, LENGTH = 46K From f36e78f6644c37246f2456b7ae2daefc93e79eda Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 23 Jul 2020 22:49:05 +1000 Subject: [PATCH 25/53] . --- workspace/TS100/Core/Drivers/FUSB302/hard_reset.h | 2 +- workspace/TS100/Core/Drivers/FUSB302/int_n.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h index c28292f1..9466b33c 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h @@ -33,7 +33,7 @@ public: private: static void Thread(const void *arg); static osThreadId TaskHandle; - static const size_t TaskStackSize = 1536 / 3; + static const size_t TaskStackSize = 1536 / 2; static uint32_t TaskBuffer[TaskStackSize]; static osStaticThreadDef_t TaskControlBlock; static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait = diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index 5e745161..e3e7d980 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -46,7 +46,9 @@ void InterruptHandler::Thread(const void *arg) { while (true) { /* If the INT_N line is low */ if (!notifSent) { - xTaskNotifyWait(0x00, 0x0F, NULL, 25); + if (xTaskNotifyWait(0x00, 0x0F, NULL, 25) == pdPASS) { + osDelay(1); + } } notifSent = false; /* Read the FUSB302B status and interrupt registers */ From e6d1249c912677c9d488bc1d54a7e32bc2c305ed Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 25 Jul 2020 22:28:38 +1000 Subject: [PATCH 26/53] Cleanup model selection --- workspace/TS100/Core/BSP/BSP.h | 2 +- workspace/TS100/Core/BSP/Miniware/BSP.cpp | 8 +- workspace/TS100/Core/BSP/Miniware/BSP_PD.c | 4 +- .../TS100/Core/BSP/Miniware/Model_Config.h | 44 ++++++++++ workspace/TS100/Core/BSP/Miniware/Pins.h | 7 +- workspace/TS100/Core/BSP/Miniware/Power.cpp | 11 +-- workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp | 6 +- .../TS100/Core/BSP/Miniware/Software_I2C.h | 27 +++++++ .../TS100/Core/BSP/Miniware/UnitSettings.h | 18 ----- .../TS100/Core/BSP/Miniware/fusb302b.cpp | 8 ++ workspace/TS100/Core/BSP/Miniware/preRTOS.cpp | 6 +- .../TS100/Core/Drivers/FUSB302/fusbpd.cpp | 9 +-- .../Core/{BSP/Miniware => Drivers}/I2CBB.cpp | 81 +++++++++---------- .../Core/{BSP/Miniware => Drivers}/I2CBB.hpp | 10 +-- workspace/TS100/Core/Drivers/OLED.cpp | 6 +- workspace/TS100/Core/Threads/GUIThread.cpp | 23 +++--- workspace/TS100/configuration.h | 1 + 17 files changed, 165 insertions(+), 106 deletions(-) create mode 100644 workspace/TS100/Core/BSP/Miniware/Model_Config.h create mode 100644 workspace/TS100/Core/BSP/Miniware/Software_I2C.h delete mode 100644 workspace/TS100/Core/BSP/Miniware/UnitSettings.h rename workspace/TS100/Core/{BSP/Miniware => Drivers}/I2CBB.cpp (76%) rename workspace/TS100/Core/{BSP/Miniware => Drivers}/I2CBB.hpp (89%) diff --git a/workspace/TS100/Core/BSP/BSP.h b/workspace/TS100/Core/BSP/BSP.h index 19e8b15d..c4fdb144 100644 --- a/workspace/TS100/Core/BSP/BSP.h +++ b/workspace/TS100/Core/BSP/BSP.h @@ -2,7 +2,7 @@ #include "BSP_Power.h" #include "BSP_QC.h" #include "Defines.h" -#include "UnitSettings.h" +#include "Model_Config.h" #include "stdint.h" /* * BSP.h -- Board Support diff --git a/workspace/TS100/Core/BSP/Miniware/BSP.cpp b/workspace/TS100/Core/BSP/Miniware/BSP.cpp index d256cdec..c48f90a5 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP.cpp +++ b/workspace/TS100/Core/BSP/Miniware/BSP.cpp @@ -7,6 +7,7 @@ #include "Pins.h" #include "main.hpp" #include "history.hpp" +#include "Model_Config.h" #include "I2C_Wrapper.hpp" volatile uint16_t PWMSafetyTimer = 0; volatile uint8_t pendingPWM = 0; @@ -16,7 +17,7 @@ history rawTempFilter = { { 0 }, 0, 0 }; void resetWatchdog() { HAL_IWDG_Refresh(&hiwdg); } -#ifdef MODEL_TS80P +#ifdef TEMP_NTC //Lookup table for the NTC //Stored as ADCReading,Temp in degC static const uint16_t NTCHandleLookup[] = { @@ -85,7 +86,7 @@ static const uint16_t NTCHandleLookup[] = { }; #endif uint16_t getHandleTemperature() { -#ifdef MODEL_TS80P +#ifdef TEMP_NTC //TS80P uses 100k NTC resistors instead //NTCG104EF104FT1X from TDK //For now not doing interpolation @@ -97,7 +98,8 @@ uint16_t getHandleTemperature() { } } return 0; -#else +#endif +#ifdef TEMP_TMP36 // We return the current handle temperature in X10 C // TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for // example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) = diff --git a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c index 031aa0f7..e2989be8 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c +++ b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c @@ -6,7 +6,8 @@ */ #include "BSP_PD.h" - +#include "Model_Config.h" +#ifdef POW_PD /* * An array of all of the desired voltages & minimum currents in preferred order */ @@ -18,3 +19,4 @@ const uint16_t USB_PD_Desired_Levels[] = { }; const uint8_t USB_PD_Desired_Levels_Len = 3; +#endif diff --git a/workspace/TS100/Core/BSP/Miniware/Model_Config.h b/workspace/TS100/Core/BSP/Miniware/Model_Config.h new file mode 100644 index 00000000..6cb69a94 --- /dev/null +++ b/workspace/TS100/Core/BSP/Miniware/Model_Config.h @@ -0,0 +1,44 @@ +/* + * Model_Config.h + * + * Created on: 25 Jul 2020 + * Author: Ralim + */ + +#ifndef BSP_MINIWARE_MODEL_CONFIG_H_ +#define BSP_MINIWARE_MODEL_CONFIG_H_ +/* + * Lookup for mapping features <-> Models + */ + +#if defined(MODEL_TS100) + defined(MODEL_TS80)+defined(MODEL_TS80P) > 1 +#error "Multiple models defined!" +#elif defined(MODEL_TS100) + defined(MODEL_TS80)+ defined(MODEL_TS80P) == 0 +#error "No model defined!" +#endif + +#ifdef MODEL_TS100 +#define ACCEL_MMA +#define ACCEL_LIS +#define TEMP_TMP36 +#endif + +#ifdef MODEL_TS80 +#define ACCEL_LIS +#define POW_QC +#define TEMP_TMP36 +#define LIS_ORI_FLIP +#define OLED_FLIP +#endif + +#ifdef MODEL_TS80P +#define ACCEL_LIS +#define POW_PD +#define POW_QC +#define TEMP_NTC +#define I2C_SOFT +#define LIS_ORI_FLIP +#define OLED_FLIP +#endif + +#endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */ diff --git a/workspace/TS100/Core/BSP/Miniware/Pins.h b/workspace/TS100/Core/BSP/Miniware/Pins.h index e932d9eb..59d26a07 100644 --- a/workspace/TS100/Core/BSP/Miniware/Pins.h +++ b/workspace/TS100/Core/BSP/Miniware/Pins.h @@ -7,12 +7,7 @@ #ifndef BSP_MINIWARE_PINS_H_ #define BSP_MINIWARE_PINS_H_ - -#if defined(MODEL_TS100) + defined(MODEL_TS80)+defined(MODEL_TS80P) > 1 -#error "Multiple models defined!" -#elif defined(MODEL_TS100) + defined(MODEL_TS80)+ defined(MODEL_TS80P) == 0 -#error "No model defined!" -#endif +#include "Model_Config.h" #ifdef MODEL_TS100 diff --git a/workspace/TS100/Core/BSP/Miniware/Power.cpp b/workspace/TS100/Core/BSP/Miniware/Power.cpp index 8340fa7f..9b989fc4 100644 --- a/workspace/TS100/Core/BSP/Miniware/Power.cpp +++ b/workspace/TS100/Core/BSP/Miniware/Power.cpp @@ -4,12 +4,13 @@ #include "Settings.h" #include "Pins.h" #include "fusbpd.h" +#include "Model_Config.h" #include "int_n.h" bool FUSB302_present = false; void power_probe() { -// If TS80 probe for QC +// If TS80(p) probe for QC // If TS100 - noop -#if defined(MODEL_TS80)+defined(MODEL_TS80P)>0 +#ifdef POW_QC startQC(systemSettings.voltageDiv); seekQC((systemSettings.cutoutSetting) ? 120 : 90, @@ -19,12 +20,12 @@ void power_probe() { } void power_check() { -#if defined(MODEL_TS80)+defined(MODEL_TS80P)>0 +#ifdef POW_QC QC_resync(); #endif } uint8_t usb_pd_detect() { -#ifdef MODEL_TS80P +#ifdef POW_PD FUSB302_present = fusb302_detect(); return FUSB302_present; @@ -32,7 +33,7 @@ uint8_t usb_pd_detect() { return false; } uint8_t pd_irq_read() { -#ifdef MODEL_TS80P +#ifdef POW_PD return HAL_GPIO_ReadPin(INT_PD_GPIO_Port, INT_PD_Pin) == GPIO_PIN_SET ? 1 : 0; #endif diff --git a/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp b/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp index 5d5f3b10..a4bba7db 100644 --- a/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp +++ b/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp @@ -9,6 +9,8 @@ #include "QC3.h" #include "Settings.h" #include "stm32f1xx_hal.h" +#include "Model_Config.h" +#ifdef POW_QC void QC_DPlusZero_Six() { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // pull down D+ } @@ -65,9 +67,9 @@ void QC_Post_Probe_En() { } uint8_t QC_DM_PulledDown() { return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == GPIO_PIN_RESET ? 1 : 0; } - +#endif void QC_resync() { -#if defined(MODEL_TS80) + defined(MODEL_TS80P) >0 +#ifdef POW_QC seekQC((systemSettings.cutoutSetting) ? 120 : 90, systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much #endif diff --git a/workspace/TS100/Core/BSP/Miniware/Software_I2C.h b/workspace/TS100/Core/BSP/Miniware/Software_I2C.h new file mode 100644 index 00000000..73242ff4 --- /dev/null +++ b/workspace/TS100/Core/BSP/Miniware/Software_I2C.h @@ -0,0 +1,27 @@ +/* + * Software_I2C.h + * + * Created on: 25 Jul 2020 + * Author: Ralim + */ + +#ifndef BSP_MINIWARE_SOFTWARE_I2C_H_ +#define BSP_MINIWARE_SOFTWARE_I2C_H_ +#include "Model_Config.h" +#include "BSP.h" +#include "stm32f1xx_hal.h" +#ifdef I2C_SOFT + +#define SOFT_SCL_HIGH() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_SET) +#define SOFT_SCL_LOW() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_RESET) +#define SOFT_SDA_HIGH() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_SET) +#define SOFT_SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET) +#define SOFT_SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0) +#define SOFT_SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0) +#define SOFT_I2C_DELAY() {for(int xx=0;xx<100;xx++){asm("nop");}} + +#endif + + + +#endif /* BSP_MINIWARE_SOFTWARE_I2C_H_ */ diff --git a/workspace/TS100/Core/BSP/Miniware/UnitSettings.h b/workspace/TS100/Core/BSP/Miniware/UnitSettings.h deleted file mode 100644 index 46a1b78c..00000000 --- a/workspace/TS100/Core/BSP/Miniware/UnitSettings.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * UnitSettings.h - * - * Created on: 29 May 2020 - * Author: Ralim - */ - -#ifndef BSP_MINIWARE_UNITSETTINGS_H_ -#define BSP_MINIWARE_UNITSETTINGS_H_ -//On the TS80, the LIS accel is mounted backwards -#if defined(MODEL_TS80)+defined(MODEL_TS80P)>0 -#define LIS_ORI_FLIP -#endif - - - - -#endif /* BSP_MINIWARE_UNITSETTINGS_H_ */ diff --git a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp index 50cff3b0..68615bed 100644 --- a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp @@ -14,6 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "Model_Config.h" +#ifdef POW_PD #include "BSP.h" #include "fusb302b.h" #include "I2CBB.hpp" @@ -272,3 +274,9 @@ bool fusb_read_id() { return false; return true; } +uint8_t fusb302_detect() { + //Probe the I2C bus for its address + return I2CBB::probe(FUSB302B_ADDR); +} + +#endif diff --git a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp index f342f8a7..d192e23a 100644 --- a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp +++ b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp @@ -11,6 +11,7 @@ #include "Pins.h" #include "I2CBB.hpp" #include "fusbpd.h" +#include "Model_Config.h" void preRToSInit() { /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ @@ -20,8 +21,11 @@ void preRToSInit() { HAL_Delay(50); HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET); HAL_Delay(50); -#ifdef MODEL_TS80P +#ifdef I2C_SOFT I2CBB::init(); + +#endif +#ifdef POW_PD //Spawn all of the USB-C processors fusb302_start_processing(); #endif diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp index 5c821515..f6bb58e1 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -4,8 +4,8 @@ * Created on: 13 Jun 2020 * Author: Ralim */ - -#ifdef MODEL_TS80P +#include "Model_Config.h" +#ifdef POW_PD #include #include #include "BSP.h" @@ -17,10 +17,7 @@ #include "int_n.h" #include "hard_reset.h" -uint8_t fusb302_detect() { - //Probe the I2C bus for its address - return I2CBB::probe(FUSB302B_ADDR); -} + void fusb302_start_processing() { /* Initialize the FUSB302B */ diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp b/workspace/TS100/Core/Drivers/I2CBB.cpp similarity index 76% rename from workspace/TS100/Core/BSP/Miniware/I2CBB.cpp rename to workspace/TS100/Core/Drivers/I2CBB.cpp index 14994c39..77410676 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.cpp +++ b/workspace/TS100/Core/Drivers/I2CBB.cpp @@ -4,17 +4,10 @@ * Created on: 12 Jun 2020 * Author: Ralim */ - -#ifdef MODEL_TS80P +#include "Model_Config.h" +#ifdef I2C_SOFT #include #include "FreeRTOS.h" -#define SCL_HIGH() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_SET) -#define SCL_LOW() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_RESET) -#define SDA_HIGH() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_SET) -#define SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET) -#define SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0) -#define SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0) -#define I2C_DELAY() {for(int xx=0;xx<100;xx++){asm("nop");}} SemaphoreHandle_t I2CBB::I2CSemaphore = NULL; StaticSemaphore_t I2CBB::xSemaphoreBuffer; SemaphoreHandle_t I2CBB::I2CSemaphore2 = NULL; @@ -28,8 +21,8 @@ void I2CBB::init() { GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(SDA2_GPIO_Port, &GPIO_InitStruct); - SDA_HIGH(); - SCL_HIGH(); + SOFT_SDA_HIGH(); + SOFT_SCL_HIGH(); I2CSemaphore = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer); I2CSemaphore2 = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer2); unlock(); @@ -66,8 +59,8 @@ bool I2CBB::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, unlock(); return false; } - SCL_LOW(); - I2C_DELAY(); + SOFT_SCL_LOW(); + SOFT_I2C_DELAY(); // stop(); start(); ack = send(DevAddress | 1); @@ -107,7 +100,7 @@ bool I2CBB::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, } while (Size) { resetWatchdog(); - bool ack = send(pData[0]); + ack = send(pData[0]); if (!ack) { stop(); asm("bkpt"); @@ -133,7 +126,7 @@ void I2CBB::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { return; } while (Size) { - bool ack = send(pData[0]); + ack = send(pData[0]); if (!ack) { stop(); unlock(); @@ -181,7 +174,7 @@ void I2CBB::TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, return; } while (Size_tx) { - bool ack = send(pData_tx[0]); + ack = send(pData_tx[0]); if (!ack) { stop(); unlock(); @@ -211,24 +204,24 @@ void I2CBB::TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, void I2CBB::start() { /* I2C Start condition, data line goes low when clock is high */ - SCL_HIGH(); - SDA_HIGH(); - I2C_DELAY(); - SDA_LOW(); - I2C_DELAY(); - SCL_LOW(); - I2C_DELAY(); - SDA_HIGH(); + SOFT_SCL_HIGH(); + SOFT_SDA_HIGH(); + SOFT_I2C_DELAY(); + SOFT_SDA_LOW(); + SOFT_I2C_DELAY(); + SOFT_SCL_LOW(); + SOFT_I2C_DELAY(); + SOFT_SDA_HIGH(); } void I2CBB::stop() { /* I2C Stop condition, clock goes high when data is low */ - SDA_LOW(); - I2C_DELAY(); - SCL_HIGH(); - I2C_DELAY(); - SDA_HIGH(); - I2C_DELAY(); + SOFT_SDA_LOW(); + SOFT_I2C_DELAY(); + SOFT_SCL_HIGH(); + SOFT_I2C_DELAY(); + SOFT_SDA_HIGH(); + SOFT_I2C_DELAY(); } bool I2CBB::send(uint8_t value) { @@ -238,7 +231,7 @@ bool I2CBB::send(uint8_t value) { value <<= 1; } - SDA_HIGH(); + SOFT_SDA_HIGH(); bool ack = (read_bit() == 0); return ack; } @@ -252,7 +245,7 @@ uint8_t I2CBB::read(bool ack) { B |= read_bit(); } - SDA_HIGH(); + SOFT_SDA_HIGH(); if (ack) write_bit(0); else @@ -263,17 +256,17 @@ uint8_t I2CBB::read(bool ack) { uint8_t I2CBB::read_bit() { uint8_t b; - SDA_HIGH(); - I2C_DELAY(); - SCL_HIGH(); - I2C_DELAY(); + SOFT_SDA_HIGH(); + SOFT_I2C_DELAY(); + SOFT_SCL_HIGH(); + SOFT_I2C_DELAY(); - if (SDA_READ()) + if (SOFT_SDA_READ()) b = 1; else b = 0; - SCL_LOW(); + SOFT_SCL_LOW(); return b; } @@ -294,15 +287,15 @@ bool I2CBB::lock() { void I2CBB::write_bit(uint8_t val) { if (val) { - SDA_HIGH(); + SOFT_SDA_HIGH(); } else { - SDA_LOW(); + SOFT_SDA_LOW(); } - I2C_DELAY(); - SCL_HIGH(); - I2C_DELAY(); - SCL_LOW(); + SOFT_I2C_DELAY(); + SOFT_SCL_HIGH(); + SOFT_I2C_DELAY(); + SOFT_SCL_LOW(); } void I2CBB::unlock2() { diff --git a/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp b/workspace/TS100/Core/Drivers/I2CBB.hpp similarity index 89% rename from workspace/TS100/Core/BSP/Miniware/I2CBB.hpp rename to workspace/TS100/Core/Drivers/I2CBB.hpp index 494bfe22..6d733c90 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2CBB.hpp +++ b/workspace/TS100/Core/Drivers/I2CBB.hpp @@ -7,17 +7,15 @@ #ifndef BSP_MINIWARE_I2CBB_HPP_ #define BSP_MINIWARE_I2CBB_HPP_ -#ifdef MODEL_TS80P +#include "Model_Config.h" +#ifdef I2C_SOFT #include "BSP.h" #include "Setup.h" #include "Pins.h" #include "FreeRTOS.h" #include "semphr.h" -/* - * Simple static I2C bit-bang class used on the TS80P - * SCL = PA5 - * SDA = PA1 - */ +#include "Software_I2C.h" + class I2CBB { public: static void init(); diff --git a/workspace/TS100/Core/Drivers/OLED.cpp b/workspace/TS100/Core/Drivers/OLED.cpp index 0e6790e7..a99fe344 100644 --- a/workspace/TS100/Core/Drivers/OLED.cpp +++ b/workspace/TS100/Core/Drivers/OLED.cpp @@ -191,9 +191,9 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) { offset = progress; memmove(&firstStripPtr[oldStart], &firstStripPtr[oldPrevious], - OLED_WIDTH - progress); + OLED_WIDTH - progress); memmove(&secondStripPtr[oldStart], &secondStripPtr[oldPrevious], - OLED_WIDTH - progress); + OLED_WIDTH - progress); memmove(&firstStripPtr[newStart], &firstBackStripPtr[newEnd], progress); memmove(&secondStripPtr[newStart], &secondBackStripPtr[newEnd], @@ -213,7 +213,7 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) { } void OLED::setRotation(bool leftHanded) { -#if defined( MODEL_TS80) +defined( MODEL_TS80P) > 0 +#ifdef OLED_FLIP leftHanded = !leftHanded; #endif if (inLeftHandedMode == leftHanded) { diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 92cdc377..04b5f7bd 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -59,11 +59,13 @@ void gui_drawTipTemp(bool symbol) { // Draw tip temp handling unit conversion & tolerance near setpoint uint16_t Temp = 0; #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) + if (systemSettings.temperatureInF){ Temp = TipThermoModel::getTipInF(); - else + }else #endif - Temp = TipThermoModel::getTipInC(); + { + Temp = TipThermoModel::getTipInC(); + } OLED::printNumber(Temp, 3); // Draw the tip temp out finally if (symbol) { @@ -247,7 +249,7 @@ static void gui_solderingTempAdjust() { if (xTaskGetTickCount() - lastChange > 200) return; // exit if user just doesn't press anything for a bit -#if defined (MODEL_TS80P)+defined(MODEL_TS80)>0 +#ifdef OLED_FLIP if (!OLED::getRotation()) { #else if (OLED::getRotation()) { @@ -272,7 +274,7 @@ static void gui_solderingTempAdjust() { OLED::drawSymbol(1); } OLED::print(SymbolSpace); -#if defined (MODEL_TS80P)+defined(MODEL_TS80)>0 +#ifdef OLED_FLIP if (!OLED::getRotation()) { #else if (OLED::getRotation()) { @@ -646,9 +648,10 @@ void startGUITask(void const *argument __unused) { { //Generate the flipped screen into ram for later use //flipped is generated by flipping each row - for(int row=0;row<2;row++){ - for (int x =0;x<84;x++){ - idleScreenBGF[(row*84)+x] =idleScreenBG[(row*84)+(83-x)]; + for (int row = 0; row < 2; row++) { + for (int x = 0; x < 84; x++) { + idleScreenBGF[(row * 84) + x] = idleScreenBG[(row * 84) + + (83 - x)]; } } } @@ -769,7 +772,7 @@ void startGUITask(void const *argument __unused) { } else { OLED::setFont(0); -#if defined (MODEL_TS80P)+defined(MODEL_TS80)>0 +#ifdef OLED_FLIP if (!OLED::getRotation()) { #else if (OLED::getRotation()) { @@ -790,7 +793,7 @@ void startGUITask(void const *argument __unused) { if (tempOnDisplay) { // draw temp over the start soldering button // Location changes on screen rotation -#if defined (MODEL_TS80P)+defined(MODEL_TS80)>0 +#ifdef OLED_FLIP if (!OLED::getRotation()) { #else if (OLED::getRotation()) { diff --git a/workspace/TS100/configuration.h b/workspace/TS100/configuration.h index 6c299576..c115a443 100644 --- a/workspace/TS100/configuration.h +++ b/workspace/TS100/configuration.h @@ -1,4 +1,5 @@ #pragma once +#include "Model_Config.h" /** * Configuration.h * Define here your default pre settings for TS80 or TS100 From 23ce11a68f8974401411ae05b4d27f2a57798909 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 19:59:28 +1000 Subject: [PATCH 27/53] Listen for SOP packets too to keep in sync (discard at software layer) --- .../TS100/Core/BSP/Miniware/fusb302b.cpp | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp index 68615bed..1c592722 100644 --- a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp @@ -73,7 +73,9 @@ static bool fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) { } void fusb_send_message(const union pd_msg *msg) { - + if (!I2CBB::lock2()) { + asm("bkpt"); + } /* Token sequences for the FUSB302B */ static uint8_t sop_seq[5] = { FUSB_FIFO_TX_SOP1, @@ -94,9 +96,7 @@ void fusb_send_message(const union pd_msg *msg) { /* Set the number of bytes to be transmitted in the packet */ sop_seq[4] = FUSB_FIFO_TX_PACKSYM | msg_len; - if (!I2CBB::lock2()) { - asm("bkpt"); - } + /* Write all three parts of the message to the TX FIFO */ fusb_write_buf( FUSB_FIFOS, 5, sop_seq); fusb_write_buf( FUSB_FIFOS, msg_len, msg->bytes); @@ -116,12 +116,13 @@ uint8_t fusb_read_message(union pd_msg *msg) { /* If this isn't an SOP message, return error. * Because of our configuration, we should be able to assume this means the * buffer is empty, and not try to read past a non-SOP message. */ - if ((fusb_read_byte( FUSB_FIFOS) & FUSB_FIFO_RX_TOKEN_BITS) - != FUSB_FIFO_RX_SOP) { - - I2CBB::unlock2(); - return 1; - } + fusb_read_byte( FUSB_FIFOS); +// if ((fusb_read_byte( FUSB_FIFOS) & FUSB_FIFO_RX_TOKEN_BITS) +// != FUSB_FIFO_RX_SOP) { +// +// I2CBB::unlock2(); +// return 1; +// } /* Read the message header into msg */ fusb_read_buf( FUSB_FIFOS, 2, msg->bytes); /* Get the number of data objects */ @@ -184,7 +185,8 @@ void fusb_setup() { //set defaults fusb_write_byte( FUSB_CONTROL2, 0x00); /* Flush the RX buffer */ - fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); + fusb_write_byte( FUSB_CONTROL1, + FUSB_CONTROL1_RX_FLUSH | FUSB_CONTROL1_ENSOP2 | FUSB_CONTROL1_ENSOP1); resetWatchdog(); /* Measure CC1 */ @@ -258,9 +260,10 @@ void fusb_reset() { /* Flush the TX buffer */ fusb_write_byte( FUSB_CONTROL0, 0x44); /* Flush the RX buffer */ - fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); + fusb_write_byte( FUSB_CONTROL1, + FUSB_CONTROL1_RX_FLUSH | FUSB_CONTROL1_ENSOP2 | FUSB_CONTROL1_ENSOP1); /* Reset the PD logic */ - fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); +// fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { I2CBB::unlock2(); } From c9a8794fb912f062db3ab0519d5c6b9505c8a8cc Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 20:01:56 +1000 Subject: [PATCH 28/53] Policy handle already pending message --- .../TS100/Core/Drivers/FUSB302/hard_reset.cpp | 4 +- .../Core/Drivers/FUSB302/policy_engine.cpp | 80 ++++++++++--------- 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp index 7b28e1d9..07426f95 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp @@ -97,9 +97,9 @@ ResetHandler::hardrst_state ResetHandler::hardrst_complete() { } void ResetHandler::init() { - osThreadStaticDef(Task, Thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, + osThreadStaticDef(rstHand, Thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, &TaskControlBlock); - TaskHandle = osThreadCreate(osThread(Task), NULL); + TaskHandle = osThreadCreate(osThread(rstHand), NULL); } void ResetHandler::notify(uint32_t notification) { diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp index 797f2353..aa567102 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -17,7 +17,7 @@ #include "policy_engine.h" #include - +#include "int_n.h" #include #include "protocol_tx.h" #include "hard_reset.h" @@ -49,9 +49,9 @@ void PolicyEngine::init() { messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue); //Create static thread at PDB_PRIO_PE priority - osThreadStaticDef(Task, pe_task, PDB_PRIO_PE, 0, TaskStackSize, TaskBuffer, - &TaskControlBlock); - TaskHandle = osThreadCreate(osThread(Task), NULL); + osThreadStaticDef(PolEng, pe_task, PDB_PRIO_PE, 0, TaskStackSize, + TaskBuffer, &TaskControlBlock); + TaskHandle = osThreadCreate(osThread(PolEng), NULL); xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup); } @@ -73,6 +73,7 @@ void PolicyEngine::pe_task(const void *arg) { for (;;) { //Loop based on state switch (state) { + case PESinkStartup: state = pe_sink_startup(); break; @@ -155,9 +156,15 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_discovery() { PolicyEngine::policy_engine_state PolicyEngine::pe_sink_wait_cap() { /* Fetch a message from the protocol layer */ - eventmask_t evt = waitForEvent( - PDB_EVT_PE_MSG_RX | PDB_EVT_PE_I_OVRTEMP | PDB_EVT_PE_RESET, - PD_T_TYPEC_SINK_WAIT_CAP); + eventmask_t evt = 0; + if (readMessage()) { + evt = PDB_EVT_PE_MSG_RX_PEND; + } else { + evt = waitForEvent( + PDB_EVT_PE_MSG_RX | PDB_EVT_PE_I_OVRTEMP | PDB_EVT_PE_RESET, + //Wait for cap timeout + PD_T_TYPEC_SINK_WAIT_CAP); + } /* If we timed out waiting for Source_Capabilities, send a hard reset */ if (evt == 0) { return PESinkHardReset; @@ -172,36 +179,36 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_wait_cap() { } /* If we got a message */ - if (evt & PDB_EVT_PE_MSG_RX) { + if (evt & (PDB_EVT_PE_MSG_RX | PDB_EVT_PE_MSG_RX_PEND)) { /* Get the message */ - readMessage(); - /* If we got a Source_Capabilities message, read it. */ - if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOURCE_CAPABILITIES - && PD_NUMOBJ_GET(&tempMessage) > 0) { - /* First, determine what PD revision we're using */ - if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_1_0) { - /* If the other end is using at least version 3.0, we'll - * use version 3.0. */ - if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { - hdr_template |= PD_SPECREV_3_0; - /* Otherwise, use 2.0. Don't worry about the 1.0 case - * because we don't have hardware for PD 1.0 signaling. */ - } else { - hdr_template |= PD_SPECREV_2_0; + while ((evt & PDB_EVT_PE_MSG_RX_PEND) || readMessage() == true) { + /* If we got a Source_Capabilities message, read it. */ + if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOURCE_CAPABILITIES + && PD_NUMOBJ_GET(&tempMessage) > 0) { + /* First, determine what PD revision we're using */ + if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_1_0) { + /* If the other end is using at least version 3.0, we'll + * use version 3.0. */ +// if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { +// hdr_template |= PD_SPECREV_3_0; +// /* Otherwise, use 2.0. Don't worry about the 1.0 case +// * because we don't have hardware for PD 1.0 signaling. */ +// } else { + hdr_template |= PD_SPECREV_2_0; +// } } + return PESinkEvalCap; + /* If the message was a Soft_Reset, do the soft reset procedure */ } - return PESinkEvalCap; - /* If the message was a Soft_Reset, do the soft reset procedure */ - } else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET - && PD_NUMOBJ_GET(&tempMessage) == 0) { - - return PESinkSoftReset; - /* If we got an unexpected message, reset */ - } else { - /* Free the received message */ - return PESinkHardReset; - +// else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET +// && PD_NUMOBJ_GET(&tempMessage) == 0) { +// +// return PESinkSoftReset; } +// /* If we got an unexpected message, reset */ + evt = 0; } + return PESinkSoftReset; //unknown message == soft reset + } /* If we failed to get a message, send a hard reset */ @@ -245,16 +252,15 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_eval_cap() { PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { /* Transmit the request */ - ProtocolTransmit::pushMessage(&_last_dpm_request); waitForEvent(0xFFFF, 0); //clear pending + ProtocolTransmit::pushMessage(&_last_dpm_request); //Send indication that there is a message pending ProtocolTransmit::notify( ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX); eventmask_t evt = waitForEvent( - PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); - /* Don't free the request; we might need it again */ + PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET, 1000); /* If we got reset signaling, transition to default */ - if (evt & PDB_EVT_PE_RESET) { + if (evt & PDB_EVT_PE_RESET || evt == 0) { return PESinkTransitionDefault; } /* If the message transmission failed, send a hard reset */ From 8eacf50a5bcb5bd006b31e11a17323be3181ba20 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 20:02:32 +1000 Subject: [PATCH 29/53] mask stacked reset if another message recieved at the same time --- .../TS100/Core/Drivers/FUSB302/int_n.cpp | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index e3e7d980..44fbc793 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -45,10 +45,9 @@ void InterruptHandler::Thread(const void *arg) { bool notifSent = false; while (true) { /* If the INT_N line is low */ - if (!notifSent) { - if (xTaskNotifyWait(0x00, 0x0F, NULL, 25) == pdPASS) { - osDelay(1); - } + if (xTaskNotifyWait(0x00, 0x0F, NULL, 200) == pdPASS) { + //delay slightly so we catch the crc with better timing + osDelay(2); } notifSent = false; /* Read the FUSB302B status and interrupt registers */ @@ -76,16 +75,18 @@ void InterruptHandler::Thread(const void *arg) { /* If the I_HARDRST or I_HARDSENT flag is set, tell the Hard Reset * thread */ - events = 0; - if (status.interrupta & FUSB_INTERRUPTA_I_HARDRST) { - events |= PDB_EVT_HARDRST_I_HARDRST; - notifSent = true; - } else if (status.interrupta & FUSB_INTERRUPTA_I_HARDSENT) { - events |= PDB_EVT_HARDRST_I_HARDSENT; - notifSent = true; - } - if (events) { - ResetHandler::notify(events); + if (notifSent == false) { + events = 0; + if (status.interrupta & FUSB_INTERRUPTA_I_HARDRST) { + events |= PDB_EVT_HARDRST_I_HARDRST; + notifSent = true; + } else if (status.interrupta & FUSB_INTERRUPTA_I_HARDSENT) { + events |= PDB_EVT_HARDRST_I_HARDSENT; + notifSent = true; + } + if (events) { + ResetHandler::notify(events); + } } /* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy * Engine thread */ From dd340d3a2b437a757d5586d0fc43f6655338f16b Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 20:05:47 +1000 Subject: [PATCH 30/53] Port from test env cleanups --- .../Drivers/FUSB302/policy_engine_user.cpp | 6 +- .../Core/Drivers/FUSB302/protocol_rx.cpp | 32 +++++++---- .../Core/Drivers/FUSB302/protocol_tx.cpp | 56 ++++++++----------- 3 files changed, 46 insertions(+), 48 deletions(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp index c82ebecc..a79b124f 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp @@ -296,12 +296,12 @@ bool PolicyEngine::messageWaiting() { return uxQueueMessagesWaiting(messagesWaiting) > 0; } -void PolicyEngine::readMessage() { - xQueueReceive(messagesWaiting, &tempMessage, 1); +bool PolicyEngine::readMessage() { + return xQueueReceive(messagesWaiting, &tempMessage, 1) == pdTRUE; } void PolicyEngine::pdbs_dpm_transition_typec() { -//This means PD failed, so we either have a dumb 5V only type C or a QC charger +//This means PD failed, so we either have a dump 5V only type C or a QC charger //For now; treat this as failed neg pdNegotiationComplete = false; } diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp index 68a897df..d3c06706 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp @@ -18,7 +18,7 @@ #include "protocol_rx.h" #include - +#include "string.h" #include #include "policy_engine.h" #include "protocol_tx.h" @@ -36,7 +36,7 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_wait_phy() { /* Wait for an event */ _rx_messageid = 0; eventmask_t evt = waitForEvent( - PDB_EVT_PRLRX_RESET | PDB_EVT_PRLRX_I_GCRCSENT); + PDB_EVT_PRLRX_RESET | PDB_EVT_PRLRX_I_GCRCSENT | PDB_EVT_PRLRX_I_RXPEND); /* If we got a reset event, reset */ if (evt & PDB_EVT_PRLRX_RESET) { @@ -48,6 +48,7 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_wait_phy() { /* Get a buffer to read the message into. Guaranteed to not fail * because we have a big enough pool and are careful. */ union pd_msg *_rx_message = &tempMessage; + memset(&tempMessage, 0, sizeof(tempMessage)); /* Read the message */ fusb_read_message(_rx_message); /* If it's a Soft_Reset, go to the soft reset state */ @@ -58,6 +59,12 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_wait_phy() { /* Otherwise, check the message ID */ return PRLRxCheckMessageID; } + } else if (evt & PDB_EVT_PRLRX_I_RXPEND) { + //There is an RX message pending that is not a Good CRC + union pd_msg *_rx_message = &tempMessage; + /* Read the message */ + fusb_read_message(_rx_message); + return PRLRxWaitPHY; } return PRLRxWaitPHY; @@ -92,17 +99,18 @@ volatile uint32_t rxCounter = 0; */ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_check_messageid() { /* If we got a RESET signal, reset the machine */ - if (waitForEvent(PDB_EVT_PRLRX_RESET, 0) == PDB_EVT_PRLRX_RESET) { - return PRLRxWaitPHY; - } +// if (waitForEvent(PDB_EVT_PRLRX_RESET, 0) == PDB_EVT_PRLRX_RESET) { +// return PRLRxWaitPHY; +// } /* If the message has the stored ID, we've seen this message before. Free * it and don't pass it to the policy engine. */ /* Otherwise, there's either no stored ID or this message has an ID we * haven't just seen. Transition to the Store_MessageID state. */ - if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) { - return PRLRxWaitPHY; - } else { +// if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) { +// return PRLRxWaitPHY; +// } else + { rxCounter++; return PRLRxStoreMessageID; } @@ -125,7 +133,7 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_store_messageid( PolicyEngine::handleMessage(&tempMessage); PolicyEngine::notify(PDB_EVT_PE_MSG_RX); - + taskYIELD(); /* Don't check if we got a RESET because we'd do nothing different. */ return PRLRxWaitPHY; @@ -134,10 +142,10 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_store_messageid( EventGroupHandle_t ProtocolReceive::xEventGroupHandle; StaticEventGroup_t ProtocolReceive::xCreatedEventGroup; void ProtocolReceive::init() { - osThreadStaticDef(Task, thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, - &TaskControlBlock); + osThreadStaticDef(protRX, thread, PDB_PRIO_PRL, 0, TaskStackSize, + TaskBuffer, &TaskControlBlock); xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup); - TaskHandle = osThreadCreate(osThread(Task), NULL); + TaskHandle = osThreadCreate(osThread(protRX), NULL); } void ProtocolReceive::thread(const void *args) { diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp index 28bac16c..1382aae4 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp @@ -26,7 +26,7 @@ osThreadId ProtocolTransmit::TaskHandle; uint32_t ProtocolTransmit::TaskBuffer[ProtocolTransmit::TaskStackSize]; osStaticThreadDef_t ProtocolTransmit::TaskControlBlock; StaticQueue_t ProtocolTransmit::xStaticQueue; - +bool ProtocolTransmit::messageSending = false; uint8_t ProtocolTransmit::ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)]; QueueHandle_t ProtocolTransmit::messagesWaiting; @@ -67,9 +67,6 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_message() if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) { return PRLTxPHYReset; } - if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) { - return PRLTxDiscardMessage; - } /* If the policy engine is trying to send a message */ if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX) { @@ -87,7 +84,7 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_message() } /* Silence the compiler warning */ - return PRLTxDiscardMessage; + return PRLTxWaitMessage; } ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_reset() { @@ -105,35 +102,24 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_reset() { * PRL_Tx_Construct_Message state */ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_message() { - /* Make sure nobody wants us to reset */ - ProtocolTransmit::Notifications evt = waitForEvent( - (uint32_t) Notifications::PDB_EVT_PRLTX_RESET - | (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD, 0); - - if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) { - return PRLTxPHYReset; - } - if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) { - return PRLTxDiscardMessage; - } - + ProtocolTransmit::Notifications evt; /* Set the correct MessageID in the message */ temp_msg.hdr &= ~PD_HDR_MESSAGEID; temp_msg.hdr |= (_tx_messageidcounter % 8) << PD_HDR_MESSAGEID_SHIFT; /* PD 3.0 collision avoidance */ - if (PolicyEngine::isPD3_0()) { - /* If we're starting an AMS, wait for permission to transmit */ - evt = waitForEvent((uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS, - 0); - if ((uint32_t) evt - & (uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS) { - while (fusb_get_typec_current() != fusb_sink_tx_ok) { - osDelay(1); - } - } - } - +// if (PolicyEngine::isPD3_0()) { +// /* If we're starting an AMS, wait for permission to transmit */ +// evt = waitForEvent((uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS, +// 0); +// if ((uint32_t) evt +// & (uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS) { +// while (fusb_get_typec_current() != fusb_sink_tx_ok) { +// osDelay(1); +// } +// } +// } + messageSending = true; /* Send the message to the PHY */ fusb_send_message(&temp_msg); @@ -202,6 +188,7 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_transmission_e } ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_message_sent() { + messageSending = false; /* Increment MessageIDCounter */ _tx_messageidcounter = (_tx_messageidcounter + 1) % 8; @@ -213,11 +200,14 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_message_sent() ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_discard_message() { /* If we were working on sending a message, increment MessageIDCounter */ - _tx_messageidcounter = (_tx_messageidcounter + 1) % 8; + if (messageSending) { + _tx_messageidcounter = (_tx_messageidcounter + 1) % 8; - return PRLTxPHYReset; + return PRLTxPHYReset; + } else { + return PRLTxWaitMessage; + } } - void ProtocolTransmit::thread(const void *args) { (void) args; ProtocolTransmit::protocol_tx_state state = PRLTxPHYReset; @@ -270,7 +260,7 @@ void ProtocolTransmit::init() { messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue); - osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PE, 0, TaskStackSize, + osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, &TaskControlBlock); TaskHandle = osThreadCreate(osThread(pd_txTask), NULL); xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup); From d35b2bf115eec0317b19fdaa250bd24aa62067a1 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 20:05:58 +1000 Subject: [PATCH 31/53] Update protocol_rx.cpp --- workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp index d3c06706..3e7304cf 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp @@ -124,7 +124,6 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_store_messageid( ProtocolTransmit::notify( ProtocolTransmit::Notifications::PDB_EVT_PRLTX_DISCARD); - taskYIELD(); /* Update the stored MessageID */ _rx_messageid = PD_MESSAGEID_GET(&tempMessage); From 9832b972485225c9313d096b18b360ab2e15e3ce Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 20:10:34 +1000 Subject: [PATCH 32/53] Header updates to match --- workspace/TS100/Core/Drivers/FUSB302/policy_engine.h | 3 ++- workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h | 1 + workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h index 259b4df5..833d368f 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h @@ -32,6 +32,7 @@ #define PDB_EVT_PE_HARD_SENT EVENT_MASK(4) #define PDB_EVT_PE_I_OVRTEMP EVENT_MASK(5) #define PDB_EVT_PE_PPS_REQUEST EVENT_MASK(6) +#define PDB_EVT_PE_MSG_RX_PEND EVENT_MASK(7) /* Never SEND THIS DIRECTLY*/ class PolicyEngine { public: @@ -123,7 +124,7 @@ private: static QueueHandle_t messagesWaiting; static bool messageWaiting(); //Read a pending message into the temp message - static void readMessage(); + static bool readMessage(); static void start_pps_timer(); static void stop_pps_timer(); diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h index 274f506b..cdfce1f0 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h @@ -25,6 +25,7 @@ /* Events for the Protocol RX thread */ #define PDB_EVT_PRLRX_RESET EVENT_MASK(0) #define PDB_EVT_PRLRX_I_GCRCSENT EVENT_MASK(1) +#define PDB_EVT_PRLRX_I_RXPEND EVENT_MASK(2) class ProtocolReceive { public: diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h index 50bb278d..b593feae 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h @@ -49,6 +49,7 @@ private: static const size_t TaskStackSize = 1024 / 4; static uint32_t TaskBuffer[TaskStackSize]; static osStaticThreadDef_t TaskControlBlock; + static bool messageSending; /* * Protocol TX machine states * From 8f395e22949a07b9fdbd6044e9f819afcd001729 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 20:28:36 +1000 Subject: [PATCH 33/53] Update protocol_tx.cpp --- workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp index 1382aae4..7f63a09f 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp @@ -102,7 +102,6 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_reset() { * PRL_Tx_Construct_Message state */ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_message() { - ProtocolTransmit::Notifications evt; /* Set the correct MessageID in the message */ temp_msg.hdr &= ~PD_HDR_MESSAGEID; temp_msg.hdr |= (_tx_messageidcounter % 8) << PD_HDR_MESSAGEID_SHIFT; From 0b2311e0013b6f071f290b6c88d59f5c40644d3e Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 21:20:36 +1000 Subject: [PATCH 34/53] Update config and clean up debugging calls --- .../TS100/Core/BSP/Miniware/fusb302b.cpp | 35 ++++++++----------- .../TS100/Core/BSP/Miniware/postRTOS.cpp | 6 +++- workspace/TS100/Core/BSP/Miniware/preRTOS.cpp | 5 +-- .../TS100/Core/Drivers/FUSB302/fusbpd.cpp | 1 + workspace/TS100/Core/Src/gui.cpp | 4 +++ workspace/TS100/configuration.h | 8 ++--- 6 files changed, 29 insertions(+), 30 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp index 1c592722..70a2c495 100644 --- a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp @@ -32,7 +32,7 @@ static uint8_t fusb_read_byte(uint8_t addr) { uint8_t data[1]; if (!I2CBB::Mem_Read(FUSB302B_ADDR, addr, (uint8_t*) data, 1)) { - asm("bkpt"); + return 0; } return data[0]; } @@ -74,7 +74,7 @@ static bool fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) { void fusb_send_message(const union pd_msg *msg) { if (!I2CBB::lock2()) { - asm("bkpt"); + return; } /* Token sequences for the FUSB302B */ static uint8_t sop_seq[5] = { @@ -113,16 +113,9 @@ uint8_t fusb_read_message(union pd_msg *msg) { static uint8_t garbage[4]; uint8_t numobj; - /* If this isn't an SOP message, return error. - * Because of our configuration, we should be able to assume this means the - * buffer is empty, and not try to read past a non-SOP message. */ + // Read the header. If its not a SOP we dont actually want it at all + // But on some revisions of the fusb if you dont both pick them up and read them out of the fifo, it gets stuck fusb_read_byte( FUSB_FIFOS); -// if ((fusb_read_byte( FUSB_FIFOS) & FUSB_FIFO_RX_TOKEN_BITS) -// != FUSB_FIFO_RX_SOP) { -// -// I2CBB::unlock2(); -// return 1; -// } /* Read the message header into msg */ fusb_read_buf( FUSB_FIFOS, 2, msg->bytes); /* Get the number of data objects */ @@ -141,7 +134,7 @@ uint8_t fusb_read_message(union pd_msg *msg) { void fusb_send_hardrst() { if (!I2CBB::lock2()) { - asm("bkpt"); + return; } /* Send a hard reset */ fusb_write_byte( FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET); @@ -161,14 +154,14 @@ void fusb_setup() { if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { if (!I2CBB::lock2()) { - asm("bkpt"); + return; } } /* Fully reset the FUSB302B */ fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES); - delay_ms(2); + osDelay(2); if (!fusb_read_id()) { - asm("bkpt"); + return; } /* Turn on all power */ fusb_write_byte( FUSB_POWER, 0x0F); @@ -192,7 +185,7 @@ void fusb_setup() { /* Measure CC1 */ fusb_write_byte( FUSB_SWITCHES0, 0x07); resetWatchdog(); - delay_ms(1); + osDelay(1); resetWatchdog(); uint8_t cc1 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; resetWatchdog(); @@ -201,7 +194,7 @@ void fusb_setup() { resetWatchdog(); fusb_write_byte( FUSB_SWITCHES0, 0x0B); resetWatchdog(); - delay_ms(1); + osDelay(1); resetWatchdog(); uint8_t cc2 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; @@ -214,16 +207,16 @@ void fusb_setup() { fusb_write_byte( FUSB_SWITCHES0, 0x0B); } resetWatchdog(); - fusb_reset(); if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { I2CBB::unlock2(); } + fusb_reset(); } void fusb_get_status(union fusb_status *status) { if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { if (!I2CBB::lock2()) { - asm("bkpt"); + return; } } @@ -238,7 +231,7 @@ void fusb_get_status(union fusb_status *status) { enum fusb_typec_current fusb_get_typec_current() { if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { if (!I2CBB::lock2()) { - asm("bkpt"); + return fusb_tcc_none; } } /* Read the BC_LVL into a variable */ @@ -253,7 +246,7 @@ enum fusb_typec_current fusb_get_typec_current() { void fusb_reset() { if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { if (!I2CBB::lock2()) { - asm("bkpt"); + return; } } diff --git a/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp b/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp index 7255f201..fa55ab11 100644 --- a/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp +++ b/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp @@ -8,8 +8,12 @@ #include "stdlib.h" #include "task.h" #include "I2C_Wrapper.hpp" - +#include "fusbpd.h" void postRToSInit() { // Any after RTos setup FRToSI2C::FRToSInit(); +#ifdef POW_PD + //Spawn all of the USB-C processors + fusb302_start_processing(); +#endif } diff --git a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp index d192e23a..6b0614b9 100644 --- a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp +++ b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp @@ -25,8 +25,5 @@ void preRToSInit() { I2CBB::init(); #endif -#ifdef POW_PD - //Spawn all of the USB-C processors - fusb302_start_processing(); -#endif + } diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp index f6bb58e1..5101f7e9 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -23,6 +23,7 @@ void fusb302_start_processing() { /* Initialize the FUSB302B */ resetWatchdog(); fusb_setup(); + osDelay(50); resetWatchdog(); /* Create the policy engine thread. */ PolicyEngine::init(); diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index c28ea2aa..6bc74c0a 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -728,6 +728,10 @@ static void settings_setCalibrateVIN(void) { case BUTTON_F_LONG: case BUTTON_B_LONG: saveSettings(); + OLED::setCursor(0, 0); + OLED::printNumber(systemSettings.voltageDiv, 3); + OLED::refresh(); + waitForButtonPressOrTimeout(100); return; break; case BUTTON_NONE: diff --git a/workspace/TS100/configuration.h b/workspace/TS100/configuration.h index c115a443..57bdc23e 100644 --- a/workspace/TS100/configuration.h +++ b/workspace/TS100/configuration.h @@ -119,11 +119,11 @@ #endif #ifdef MODEL_TS80P -#define VOLTAGE_DIV 768 // Default for TS80P with slightly different resistors -#define PID_POWER_LIMIT 30 // Sets the max pwm power limit +#define VOLTAGE_DIV 650 // Default for TS80P with slightly different resistors +#define PID_POWER_LIMIT 35 // Sets the max pwm power limit #define CALIBRATION_OFFSET 900 // the adc offset in uV -#define POWER_LIMIT 24 // 24 watts default power limit -#define MAX_POWER_LIMIT 30 // +#define POWER_LIMIT 30 // 30 watts default power limit +#define MAX_POWER_LIMIT 35 // #define POWER_LIMIT_STEPS 2 #define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80 #endif From add65ead9c29546f31f8266d9238e6642507adc9 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 21:26:05 +1000 Subject: [PATCH 35/53] Drop timer support as not used --- workspace/TS100/Core/BSP/Miniware/fusb302b.cpp | 4 ++-- workspace/TS100/Core/Inc/FreeRTOSConfig.h | 2 +- workspace/TS100/Core/Src/FreeRTOSHooks.c | 9 --------- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp index 70a2c495..78533cce 100644 --- a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp @@ -185,7 +185,7 @@ void fusb_setup() { /* Measure CC1 */ fusb_write_byte( FUSB_SWITCHES0, 0x07); resetWatchdog(); - osDelay(1); + osDelay(10); resetWatchdog(); uint8_t cc1 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; resetWatchdog(); @@ -194,7 +194,7 @@ void fusb_setup() { resetWatchdog(); fusb_write_byte( FUSB_SWITCHES0, 0x0B); resetWatchdog(); - osDelay(1); + osDelay(10); resetWatchdog(); uint8_t cc2 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; diff --git a/workspace/TS100/Core/Inc/FreeRTOSConfig.h b/workspace/TS100/Core/Inc/FreeRTOSConfig.h index 51a1f472..73303039 100644 --- a/workspace/TS100/Core/Inc/FreeRTOSConfig.h +++ b/workspace/TS100/Core/Inc/FreeRTOSConfig.h @@ -106,7 +106,7 @@ extern uint32_t SystemCoreClock; #define configUSE_16_BIT_TICKS 0 #define configUSE_MUTEXES 1 #define configQUEUE_REGISTRY_SIZE 8 -#define configUSE_TIMERS 1 /* Required for PD 10ms callback for PPS mode*/ +#define configUSE_TIMERS 0 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configCHECK_FOR_STACK_OVERFLOW 2 /*Bump this to 2 during development and bug hunting*/ diff --git a/workspace/TS100/Core/Src/FreeRTOSHooks.c b/workspace/TS100/Core/Src/FreeRTOSHooks.c index 2e08976e..f7c56c6a 100644 --- a/workspace/TS100/Core/Src/FreeRTOSHooks.c +++ b/workspace/TS100/Core/Src/FreeRTOSHooks.c @@ -22,16 +22,7 @@ void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* place for user code */ } -static StaticTask_t xTimerTaskTCBBuffer; -static StackType_t xTimerStack[configTIMER_TASK_STACK_DEPTH]; -void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, - StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) { - *ppxTimerTaskTCBBuffer = &xTimerTaskTCBBuffer; - *ppxTimerTaskStackBuffer = &xTimerStack[0]; - *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; - /* place for user code */ -} void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCHAR *pcTaskName) { From 1e19fc80f4117563f9d2235a91027103beb62125 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 21:26:26 +1000 Subject: [PATCH 36/53] Add ts80p to auto build --- workspace/TS100/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/TS100/build.sh b/workspace/TS100/build.sh index 2fd28523..068d7f20 100755 --- a/workspace/TS100/build.sh +++ b/workspace/TS100/build.sh @@ -6,7 +6,7 @@ TRANSLATION_SCRIPT="make_translation.py" # AVAILABLE_LANGUAGES will be calculating according to json files in $TRANSLATION_DIR AVAILABLE_LANGUAGES=() BUILD_LANGUAGES=() -AVAILABLE_MODELS=("TS100" "TS80") +AVAILABLE_MODELS=("TS100" "TS80" "TS80P") BUILD_MODELS=() usage() { From 7b41e2fcca31ace59ee7a62a7d3d3a4ac4d1dfd9 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 21:28:27 +1000 Subject: [PATCH 37/53] Lower min spec to ~27W for 12v neg --- workspace/TS100/Core/BSP/Miniware/BSP_PD.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c index e2989be8..1677467a 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c +++ b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c @@ -13,7 +13,7 @@ */ const uint16_t USB_PD_Desired_Levels[] = { //mV desired input, mA minimum required current - 12000, 2500, //12V @ 2.5A + 12000, 2000, //12V @ 2.5A 9000, 2000, //9V @ 2A 5000, 1100, //5V @ 1.1A From be57c4f58af2577ca870435c12a33a75d9eaa88d Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 21:43:42 +1000 Subject: [PATCH 38/53] Update BSP_PD.c --- workspace/TS100/Core/BSP/Miniware/BSP_PD.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c index 1677467a..fba573d7 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c +++ b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c @@ -13,7 +13,7 @@ */ const uint16_t USB_PD_Desired_Levels[] = { //mV desired input, mA minimum required current - 12000, 2000, //12V @ 2.5A + 12000, 2000, //12V @ 2A 9000, 2000, //9V @ 2A 5000, 1100, //5V @ 1.1A From b6ee4207dd90efc9ddf7181c0d3170c04daedcac Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 21:56:50 +1000 Subject: [PATCH 39/53] Dont need to soft reset if timing gives SOP' without SOP following Easier to wait again and let timeout handle reset --- .../Core/Drivers/FUSB302/policy_engine.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp index aa567102..5084f1ea 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -189,25 +189,20 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_wait_cap() { if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_1_0) { /* If the other end is using at least version 3.0, we'll * use version 3.0. */ -// if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { -// hdr_template |= PD_SPECREV_3_0; -// /* Otherwise, use 2.0. Don't worry about the 1.0 case -// * because we don't have hardware for PD 1.0 signaling. */ -// } else { + if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { + hdr_template |= PD_SPECREV_3_0; + /* Otherwise, use 2.0. Don't worry about the 1.0 case + * because we don't have hardware for PD 1.0 signaling. */ + } else { hdr_template |= PD_SPECREV_2_0; -// } + } } return PESinkEvalCap; /* If the message was a Soft_Reset, do the soft reset procedure */ } -// else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET -// && PD_NUMOBJ_GET(&tempMessage) == 0) { -// -// return PESinkSoftReset; } -// /* If we got an unexpected message, reset */ evt = 0; } - return PESinkSoftReset; //unknown message == soft reset + return PESinkWaitCap; //unknown message == soft reset } From d68eb95f50b407fa21f958d8b612ce2fc723a206 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 28 Jul 2020 22:27:14 +1000 Subject: [PATCH 40/53] Cleanup more unrequired logic --- .../TS100/Core/BSP/Miniware/Software_I2C.h | 2 +- .../TS100/Core/BSP/Miniware/fusb302b.cpp | 14 ++---------- .../Core/Drivers/FUSB302/policy_engine.cpp | 22 +++++++++---------- workspace/TS100/Core/Drivers/I2CBB.cpp | 7 +----- 4 files changed, 15 insertions(+), 30 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/Software_I2C.h b/workspace/TS100/Core/BSP/Miniware/Software_I2C.h index 73242ff4..9fc62d5d 100644 --- a/workspace/TS100/Core/BSP/Miniware/Software_I2C.h +++ b/workspace/TS100/Core/BSP/Miniware/Software_I2C.h @@ -18,7 +18,7 @@ #define SOFT_SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET) #define SOFT_SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0) #define SOFT_SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0) -#define SOFT_I2C_DELAY() {for(int xx=0;xx<100;xx++){asm("nop");}} +#define SOFT_I2C_DELAY() {for(int xx=0;xx<40;xx++){asm("nop");}} #endif diff --git a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp index 78533cce..0a3fbd2d 100644 --- a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp @@ -149,7 +149,7 @@ void fusb_setup() { GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - HAL_NVIC_SetPriority(EXTI9_5_IRQn, 10, 0); + HAL_NVIC_SetPriority(EXTI9_5_IRQn, 12, 0); HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { @@ -157,12 +157,10 @@ void fusb_setup() { return; } } - /* Fully reset the FUSB302B */ - fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES); - osDelay(2); if (!fusb_read_id()) { return; } + /* Turn on all power */ fusb_write_byte( FUSB_POWER, 0x0F); @@ -181,21 +179,14 @@ void fusb_setup() { fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH | FUSB_CONTROL1_ENSOP2 | FUSB_CONTROL1_ENSOP1); - resetWatchdog(); /* Measure CC1 */ fusb_write_byte( FUSB_SWITCHES0, 0x07); - resetWatchdog(); osDelay(10); - resetWatchdog(); uint8_t cc1 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; - resetWatchdog(); /* Measure CC2 */ - resetWatchdog(); fusb_write_byte( FUSB_SWITCHES0, 0x0B); - resetWatchdog(); osDelay(10); - resetWatchdog(); uint8_t cc2 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; /* Select the correct CC line for BMC signaling; also enable AUTO_CRC */ @@ -206,7 +197,6 @@ void fusb_setup() { fusb_write_byte( FUSB_SWITCHES1, 0x26); fusb_write_byte( FUSB_SWITCHES0, 0x0B); } - resetWatchdog(); if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { I2CBB::unlock2(); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp index 5084f1ea..a9da67bb 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -171,7 +171,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_wait_cap() { } /* If we got reset signaling, transition to default */ if (evt & PDB_EVT_PE_RESET) { - return PESinkTransitionDefault; + return PESinkWaitCap; } /* If we're too hot, we shouldn't negotiate power yet */ if (evt & PDB_EVT_PE_I_OVRTEMP) { @@ -187,22 +187,22 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_wait_cap() { && PD_NUMOBJ_GET(&tempMessage) > 0) { /* First, determine what PD revision we're using */ if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_1_0) { - /* If the other end is using at least version 3.0, we'll - * use version 3.0. */ - if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { - hdr_template |= PD_SPECREV_3_0; - /* Otherwise, use 2.0. Don't worry about the 1.0 case - * because we don't have hardware for PD 1.0 signaling. */ - } else { - hdr_template |= PD_SPECREV_2_0; - } +// /* If the other end is using at least version 3.0, we'll +// * use version 3.0. */ +// if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { +// hdr_template |= PD_SPECREV_3_0; +// /* Otherwise, use 2.0. Don't worry about the 1.0 case +// * because we don't have hardware for PD 1.0 signaling. */ +// } else { + hdr_template |= PD_SPECREV_2_0; +// } } return PESinkEvalCap; /* If the message was a Soft_Reset, do the soft reset procedure */ } evt = 0; } - return PESinkWaitCap; //unknown message == soft reset + return PESinkWaitCap; //wait for more messages? } diff --git a/workspace/TS100/Core/Drivers/I2CBB.cpp b/workspace/TS100/Core/Drivers/I2CBB.cpp index 77410676..b878db58 100644 --- a/workspace/TS100/Core/Drivers/I2CBB.cpp +++ b/workspace/TS100/Core/Drivers/I2CBB.cpp @@ -27,12 +27,7 @@ void I2CBB::init() { I2CSemaphore2 = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer2); unlock(); unlock2(); - //unstick bus -// start(); -// for (int i = 0; i < 8; i++) { -// read_bit(); -// } -// stop(); + } bool I2CBB::probe(uint8_t address) { From a59d008d07f575330ab1c648e363d58b99429260 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 29 Jul 2020 22:52:20 +1000 Subject: [PATCH 41/53] Hold off QC until PD is done --- workspace/TS100/Core/BSP/Miniware/Power.cpp | 31 +++++++++------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/Power.cpp b/workspace/TS100/Core/BSP/Miniware/Power.cpp index 9b989fc4..23b02783 100644 --- a/workspace/TS100/Core/BSP/Miniware/Power.cpp +++ b/workspace/TS100/Core/BSP/Miniware/Power.cpp @@ -5,21 +5,22 @@ #include "Pins.h" #include "fusbpd.h" #include "Model_Config.h" +#include "policy_engine.h" #include "int_n.h" bool FUSB302_present = false; -void power_probe() { -// If TS80(p) probe for QC -// If TS100 - noop -#ifdef POW_QC - - startQC(systemSettings.voltageDiv); - seekQC((systemSettings.cutoutSetting) ? 120 : 90, - systemSettings.voltageDiv); // this will move the QC output to the preferred voltage to start with - -#endif -} void power_check() { +#ifdef POW_PD + if (FUSB302_present) { + //Cant start QC until either PD works or fails + if (PolicyEngine::setupCompleteOrTimedOut() == false) { + return; + } + if (PolicyEngine::pdHasNegotiated()) { + return; + } + } +#endif #ifdef POW_QC QC_resync(); #endif @@ -32,10 +33,4 @@ uint8_t usb_pd_detect() { #endif return false; } -uint8_t pd_irq_read() { -#ifdef POW_PD - return HAL_GPIO_ReadPin(INT_PD_GPIO_Port, INT_PD_Pin) == GPIO_PIN_SET ? - 1 : 0; -#endif - return 0; -} + From a39185315d0e94664a8f903fa0549ec1157dfc9a Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 29 Jul 2020 22:52:36 +1000 Subject: [PATCH 42/53] Allow query PD for status and remove more cruft from PPS --- .../TS100/Core/Drivers/FUSB302/int_n.cpp | 3 +- workspace/TS100/Core/Drivers/FUSB302/pd.h | 16 ++-- .../Core/Drivers/FUSB302/policy_engine.cpp | 37 +-------- .../Core/Drivers/FUSB302/policy_engine.h | 18 +++-- .../Drivers/FUSB302/policy_engine_user.cpp | 80 ++----------------- 5 files changed, 29 insertions(+), 125 deletions(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index 44fbc793..4e3dad92 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -45,7 +45,8 @@ void InterruptHandler::Thread(const void *arg) { bool notifSent = false; while (true) { /* If the INT_N line is low */ - if (xTaskNotifyWait(0x00, 0x0F, NULL, 200) == pdPASS) { + if (xTaskNotifyWait(0x00, 0x0F, NULL, + PolicyEngine::setupCompleteOrTimedOut() ? 1000 : 200) == pdPASS) { //delay slightly so we catch the crc with better timing osDelay(2); } diff --git a/workspace/TS100/Core/Drivers/FUSB302/pd.h b/workspace/TS100/Core/Drivers/FUSB302/pd.h index 11c8f80f..be1f8453 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/pd.h +++ b/workspace/TS100/Core/Drivers/FUSB302/pd.h @@ -273,18 +273,18 @@ * Where a range is specified, the middle of the range (rounded down to the * nearest millisecond) is used. */ -#define PD_T_CHUNKING_NOT_SUPPORTED (450) -#define PD_T_HARD_RESET_COMPLETE (400) -#define PD_T_PS_TRANSITION (5000) -#define PD_T_SENDER_RESPONSE (2700) -#define PD_T_SINK_REQUEST (1000) -#define PD_T_TYPEC_SINK_WAIT_CAP (5000) -#define PD_T_PD_DEBOUNCE (2000) +#define PD_T_CHUNKING_NOT_SUPPORTED (45) +#define PD_T_HARD_RESET_COMPLETE (40) +#define PD_T_PS_TRANSITION (500) +#define PD_T_SENDER_RESPONSE (270) +#define PD_T_SINK_REQUEST (100) +#define PD_T_TYPEC_SINK_WAIT_CAP (45) +#define PD_T_PD_DEBOUNCE (20) /* * Counter maximums */ -#define PD_N_HARD_RESET_COUNT 20 +#define PD_N_HARD_RESET_COUNT 2 /* * Value parameters diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp index a9da67bb..d015dd2a 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -263,19 +263,6 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { return PESinkHardReset; } - /* If we're using PD 3.0 */ - if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_3_0) { - /* If the request was for a PPS APDO, start SinkPPSPeriodicTimer */ - if (PD_RDO_OBJPOS_GET(&_last_dpm_request) >= _pps_index) { - start_pps_timer(); - /* Otherwise, stop SinkPPSPeriodicTimer */ - } else { - stop_pps_timer(); - } - } - /* This will use a virtual timer to send an event flag to this thread after - * PD_T_PPS_REQUEST */ - /* Wait for a response */ evt = waitForEvent(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET, PD_T_SENDER_RESPONSE); @@ -367,8 +354,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_ready() { /* Wait for an event */ evt = waitForEvent( - PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET | PDB_EVT_PE_I_OVRTEMP - | PDB_EVT_PE_PPS_REQUEST); + PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET | PDB_EVT_PE_I_OVRTEMP); /* If we got reset signaling, transition to default */ if (evt & PDB_EVT_PE_RESET) { @@ -380,14 +366,6 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_ready() { return PESinkHardReset; } - /* If SinkPPSPeriodicTimer ran out, send a new request */ - if (evt & PDB_EVT_PE_PPS_REQUEST) { - /* Tell the protocol layer we're starting an AMS */ - ProtocolTransmit::notify( - ProtocolTransmit::Notifications::PDB_EVT_PRLTX_START_AMS); - return PESinkSelectCap; - } - /* If we received a message */ if (evt & PDB_EVT_PE_MSG_RX) { if (messageWaiting()) { @@ -717,14 +695,6 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_source_unresponsive() { return PESinkSourceUnresponsive; } -void PolicyEngine::PPSTimerCallBack() { - notify(PDB_EVT_PE_PPS_REQUEST); -} - -bool PolicyEngine::pdHasNegotiated() { - return pdNegotiationComplete; -} - uint32_t PolicyEngine::waitForEvent(uint32_t mask, uint32_t ticksToWait) { return xEventGroupWaitBits(xEventGroupHandle, mask, mask, pdFALSE, ticksToWait); @@ -735,8 +705,3 @@ bool PolicyEngine::isPD3_0() { return (hdr_template & PD_HDR_SPECREV) == PD_SPECREV_3_0; } -void PolicyEngine::start_pps_timer() { -} - -void PolicyEngine::stop_pps_timer() { -} diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h index 833d368f..4aef4b0e 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h @@ -31,7 +31,6 @@ #define PDB_EVT_PE_TX_ERR EVENT_MASK(3) #define PDB_EVT_PE_HARD_SENT EVENT_MASK(4) #define PDB_EVT_PE_I_OVRTEMP EVENT_MASK(5) -#define PDB_EVT_PE_PPS_REQUEST EVENT_MASK(6) #define PDB_EVT_PE_MSG_RX_PEND EVENT_MASK(7) /* Never SEND THIS DIRECTLY*/ class PolicyEngine { @@ -44,10 +43,19 @@ public: static void notify(uint32_t notification); //Returns true if headers indicate PD3.0 compliant static bool isPD3_0(); - - static void PPSTimerCallBack(); + static bool setupCompleteOrTimedOut() { + if (pdNegotiationComplete) + return true; + if (state == policy_engine_state::PESinkSourceUnresponsive) + return true; + if (state == policy_engine_state::PESinkReady) + return true; + return false; + } //Has pd negotiation completed - static bool pdHasNegotiated(); + static bool pdHasNegotiated() { + return pdNegotiationComplete; + } private: static bool pdNegotiationComplete; static int current_voltage_mv; //The current voltage PD is expecting @@ -125,8 +133,6 @@ private: static bool messageWaiting(); //Read a pending message into the temp message static bool readMessage(); - static void start_pps_timer(); - static void stop_pps_timer(); // These callbacks are called to implement the logic for the iron to select the desired voltage diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp index a79b124f..8464e06d 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp @@ -84,7 +84,7 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability( PD_RDO_FV_MAX_CURRENT_SET( current) | PD_RDO_FV_CURRENT_SET(current) | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1); - + //We support usb comms (ish) request->obj[0] |= PD_RDO_USB_COMMS; /* Update requested voltage */ @@ -94,69 +94,10 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability( } } } -#if 0 - /* If we have a PPS APDO, our desired V lies within its range, and - * its I is at least our desired I */ - if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED - && (capabilities->obj[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS) { - int min_mv = PD_PAV2MV( - PD_APDO_PPS_MIN_VOLTAGE_GET(capabilities->obj[i])); - int max_mv = PD_PAV2MV( - PD_APDO_PPS_MAX_VOLTAGE_GET(capabilities->obj[i])); - int current = PD_CA2PAI( - PD_APDO_PPS_CURRENT_GET(capabilities->obj[i])); - /* We got what we wanted, so build a request for that */ -// -// request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); -// -// /* Build a request */ -// request->obj[0] = -// PD_RDO_PROG_CURRENT_SET( -// PD_CA2PAI(current)) | PD_RDO_PROG_VOLTAGE_SET(PD_MV2PRV(voltage)) -// | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1); -// -// request->obj[0] |= PD_RDO_USB_COMMS; -// -// /* Update requested voltage */ -// _requested_voltage = PD_PRV2MV(PD_MV2PRV(voltage)); -// -// return true; - } -#endif + } } - /* If there's a PDO in the voltage range, use it */ -// int8_t i = dpm_get_range_fixed_pdo_index(caps, scfg); -// if (i >= 0) { -// /* We got what we wanted, so build a request for that */ -// request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); -// /* Get the current we need at this voltage */ -// current = dpm_get_current(scfg, -// PD_PDV2MV(PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i]))); -// if (scfg->flags & PDBS_CONFIG_FLAGS_GIVEBACK) { -// /* GiveBack enabled */ -// request->obj[0] = -// PD_RDO_FV_MIN_CURRENT_SET( -// DPM_MIN_CURRENT) | PD_RDO_FV_CURRENT_SET(current) | PD_RDO_NO_USB_SUSPEND -// | PD_RDO_GIVEBACK | PD_RDO_OBJPOS_SET(i + 1); -// } else { -// /* GiveBack disabled */ -// request->obj[0] = -// PD_RDO_FV_MAX_CURRENT_SET( -// current) | PD_RDO_FV_CURRENT_SET(current) | PD_RDO_NO_USB_SUSPEND -// | PD_RDO_OBJPOS_SET(i + 1); -// } -// if (usb_comms) { -// request->obj[0] |= PD_RDO_USB_COMMS; -// } -// -// /* Update requested voltage */ -// _requested_voltage = PD_PDV2MV( -// PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i])); -// -// _capability_match = true; -// return true; -// } + /* Nothing matched (or no configuration), so get 5 V at low current */ request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); request->obj[0] = @@ -168,7 +109,6 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability( if (pdNegotiationComplete) { request->obj[0] |= PD_RDO_CAP_MISMATCH; } - /* If we can do USB communications, tell the power supply */ request->obj[0] |= PD_RDO_USB_COMMS; /* Update requested voltage */ @@ -191,8 +131,8 @@ void PolicyEngine::pdbs_dpm_get_sink_capability(union pd_msg *cap) { PD_MV2PDV(5000)) | PD_PDO_SNK_FIXED_CURRENT_SET(DPM_MIN_CURRENT); /* Get the current we want */ - uint16_t current = 100; // In centi-amps - uint16_t voltage = 9000; // in mv + uint16_t current = USB_PD_Desired_Levels[1] / 10; // In centi-amps + uint16_t voltage = USB_PD_Desired_Levels[0]; // in mv /* Add a PDO for the desired power. */ cap->obj[numobj++] = PD_PDO_TYPE_FIXED | PD_PDO_SNK_FIXED_VOLTAGE_SET( @@ -233,15 +173,6 @@ void PolicyEngine::pdbs_dpm_get_sink_capability(union pd_msg *cap) { } } - /* If we're using PD 3.0, add a PPS APDO for our desired voltage */ - if (isPD3_0()) { - cap->obj[numobj++] = - PD_PDO_TYPE_AUGMENTED | PD_APDO_TYPE_PPS - | PD_APDO_PPS_MAX_VOLTAGE_SET( - PD_MV2PAV(voltage)) | PD_APDO_PPS_MIN_VOLTAGE_SET(PD_MV2PAV(voltage)) - | PD_APDO_PPS_CURRENT_SET(PD_CA2PAI(current)); - } - /* Set the unconstrained power flag. */ if (_unconstrained_power) { cap->obj[0] |= PD_PDO_SNK_FIXED_UNCONSTRAINED; @@ -259,6 +190,7 @@ bool PolicyEngine::pdbs_dpm_evaluate_typec_current( /* We don't control the voltage anymore; it will always be 5 V. */ current_voltage_mv = _requested_voltage = 5000; //For the soldering iron we accept this as a fallback, but it sucks + pdNegotiationComplete = false; return true; } From 93911583996329c69bb3c2968b376c3cde3980f7 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 29 Jul 2020 22:53:08 +1000 Subject: [PATCH 43/53] Re enable accel, fix accel flags & cleanup qc --- workspace/TS100/Core/BSP/BSP.h | 3 +- workspace/TS100/Core/BSP/BSP_Power.h | 3 - workspace/TS100/Core/Src/QC3.c | 200 +++++++++++---------- workspace/TS100/Core/Src/main.cpp | 24 ++- workspace/TS100/Core/Threads/MOVThread.cpp | 12 +- 5 files changed, 128 insertions(+), 114 deletions(-) diff --git a/workspace/TS100/Core/BSP/BSP.h b/workspace/TS100/Core/BSP/BSP.h index c4fdb144..f1765c0f 100644 --- a/workspace/TS100/Core/BSP/BSP.h +++ b/workspace/TS100/Core/BSP/BSP.h @@ -51,8 +51,7 @@ uint8_t showBootLogoIfavailable(); void delay_ms(uint16_t count) ; //Used to allow knowledge of if usb_pd is being used uint8_t usb_pd_detect(); -//Returns 0 when the irq line is pulled down -uint8_t pd_irq_read(); + #ifdef __cplusplus } #endif diff --git a/workspace/TS100/Core/BSP/BSP_Power.h b/workspace/TS100/Core/BSP/BSP_Power.h index 1ce7f2bf..5b277a21 100644 --- a/workspace/TS100/Core/BSP/BSP_Power.h +++ b/workspace/TS100/Core/BSP/BSP_Power.h @@ -12,9 +12,6 @@ extern "C" { #endif -// Called once at startup, after RToS -// This can handle negotiations for QC/PD etc -void power_probe(); // Called periodically in the movement handling thread // Can be used to check any details for the power system diff --git a/workspace/TS100/Core/Src/QC3.c b/workspace/TS100/Core/Src/QC3.c index 826891c8..0c880a5e 100644 --- a/workspace/TS100/Core/Src/QC3.c +++ b/workspace/TS100/Core/Src/QC3.c @@ -13,68 +13,72 @@ #include "stdint.h" void QC_Seek9V() { - QC_DNegZero_Six(); - QC_DPlusThree_Three(); + QC_DNegZero_Six(); + QC_DPlusThree_Three(); } void QC_Seek12V() { - QC_DNegZero_Six(); - QC_DPlusZero_Six(); + QC_DNegZero_Six(); + QC_DPlusZero_Six(); } void QC_Seek20V() { - QC_DNegThree_Three(); - QC_DPlusThree_Three(); + QC_DNegThree_Three(); + QC_DPlusThree_Three(); } void QC_SeekContMode() { - QC_DNegThree_Three(); - QC_DPlusZero_Six(); + QC_DNegThree_Three(); + QC_DPlusZero_Six(); } void QC_SeekContPlus() { - QC_SeekContMode(); - osDelay(30); - QC_Seek20V(); - osDelay(10); - QC_SeekContMode(); + QC_SeekContMode(); + osDelay(30); + QC_Seek20V(); + osDelay(10); + QC_SeekContMode(); } void QC_SeekContNeg() { - QC_SeekContMode(); - osDelay(30); - QC_Seek12V(); - osDelay(10); - QC_SeekContMode(); + QC_SeekContMode(); + osDelay(30); + QC_Seek12V(); + osDelay(10); + QC_SeekContMode(); } uint8_t QCMode = 0; uint8_t QCTries = 0; void seekQC(int16_t Vx10, uint16_t divisor) { - if (QCMode == 5) startQC(divisor); - if (QCMode == 0) return; // NOT connected to a QC Charger + if (QCMode == 0) + startQC(divisor); - if (Vx10 < 45) return; - if (xTaskGetTickCount() < 100) return; - if (Vx10 > 130) Vx10 = 130; // Cap max value at 13V - // Seek the QC to the Voltage given if this adapter supports continuous mode - // try and step towards the wanted value + if (Vx10 < 45) + return; + if (xTaskGetTickCount() < 100) + return; + if (Vx10 > 130) + Vx10 = 130; // Cap max value at 13V + // Seek the QC to the Voltage given if this adapter supports continuous mode + // try and step towards the wanted value - // 1. Measure current voltage - int16_t vStart = getInputVoltageX10(divisor, 1); - int difference = Vx10 - vStart; + // 1. Measure current voltage + int16_t vStart = getInputVoltageX10(divisor, 1); + int difference = Vx10 - vStart; - // 2. calculate ideal steps (0.2V changes) + // 2. calculate ideal steps (0.2V changes) - int steps = difference / 2; - if (QCMode == 3) { - if (steps > -2 && steps < 2) return; // dont bother with small steps - while (steps < 0) { - QC_SeekContNeg(); - osDelay(30); - steps++; - } - while (steps > 0) { - QC_SeekContPlus(); - osDelay(30); - steps--; - } - osDelay(100); - } + int steps = difference / 2; + if (QCMode == 3) { + if (steps > -2 && steps < 2) + return; // dont bother with small steps + while (steps < 0) { + QC_SeekContNeg(); + osDelay(30); + steps++; + } + while (steps > 0) { + QC_SeekContPlus(); + osDelay(30); + steps--; + } + osDelay(100); + } #ifdef ENABLE_QC2 // Re-measure /* Disabled due to nothing to test and code space of around 1k*/ @@ -99,59 +103,61 @@ void seekQC(int16_t Vx10, uint16_t divisor) { } // Must be called after FreeRToS Starts void startQC(uint16_t divisor) { - // Pre check that the input could be >5V already, and if so, dont both - // negotiating as someone is feeding in hv - uint16_t vin = getInputVoltageX10(divisor, 1); - if (vin > 100) { - QCMode = 1; // Already at 12V, user has probably over-ridden this - return; - } - QC_Init_GPIO(); + // Pre check that the input could be >5V already, and if so, dont both + // negotiating as someone is feeding in hv + uint16_t vin = getInputVoltageX10(divisor, 1); + if (vin > 100) { + QCMode = 1; // Already at 12V, user has probably over-ridden this + return; + } + if (QCTries > 10) { + return; + } + QC_Init_GPIO(); - // Tries to negotiate QC for 9V - // This is a multiple step process. - // 1. Set around 0.6V on D+ for 1.25 Seconds or so - // 2. After this It should un-short D+->D- and instead add a 20k pulldown on - // D- - QC_DPlusZero_Six(); + // Tries to negotiate QC for 9V + // This is a multiple step process. + // 1. Set around 0.6V on D+ for 1.25 Seconds or so + // 2. After this It should un-short D+->D- and instead add a 20k pulldown on + // D- + QC_DPlusZero_Six(); + + // Delay 1.25 seconds + uint8_t enteredQC = 0; + for (uint16_t i = 0; i < 200 && enteredQC == 0; i++) { + osDelay(10); // 10mS pause + if (i > 130) { + if (QC_DM_PulledDown()) { + enteredQC = 1; + } + if (i == 140) { + // For some marginal QC chargers, we try adding a pulldown + QC_DM_PullDown(); + } + } + } + QC_DM_No_PullDown(); + if (enteredQC) { + // We have a QC capable charger + QC_Seek9V(); + QC_Post_Probe_En(); + QC_Seek9V(); + // Wait for frontend ADC to stabilise + QCMode = 4; + for (uint8_t i = 0; i < 10; i++) { + if (getInputVoltageX10(divisor, 1) > 80) { + // yay we have at least QC2.0 or QC3.0 + QCMode = 3; // We have at least QC2, pray for 3 + return; + } + osDelay(100); // 100mS + } + QCMode = 0; + QCTries++; + + } else { + // no QC + QCMode = 0; + } - // Delay 1.25 seconds - uint8_t enteredQC = 0; - for (uint16_t i = 0; i < 200 && enteredQC == 0; i++) { - osDelay(10); // 10mS pause - if (i > 130) { - if (QC_DM_PulledDown()) { - enteredQC = 1; - } - if (i == 140) { - // For some marginal QC chargers, we try adding a pulldown - QC_DM_PullDown(); - } - } - } - QC_DM_No_PullDown(); - if (enteredQC) { - // We have a QC capable charger - QC_Seek9V(); - QC_Post_Probe_En(); - QC_Seek9V(); - // Wait for frontend ADC to stabilise - QCMode = 4; - for (uint8_t i = 0; i < 10; i++) { - if (getInputVoltageX10(divisor, 1) > 80) { - // yay we have at least QC2.0 or QC3.0 - QCMode = 3; // We have at least QC2, pray for 3 - return; - } - osDelay(100); // 100mS - } - QCMode = 5; - QCTries++; - if (QCTries > 10) // 10 goes to get it going - QCMode = 0; - } else { - // no QC - QCMode = 0; - } - if (QCTries > 10) QCMode = 0; } diff --git a/workspace/TS100/Core/Src/main.cpp b/workspace/TS100/Core/Src/main.cpp index ec190be6..89d2bc45 100644 --- a/workspace/TS100/Core/Src/main.cpp +++ b/workspace/TS100/Core/Src/main.cpp @@ -43,17 +43,23 @@ int main(void) { OLED::setFont(0); // default to bigger font // Testing for which accelerometer is mounted resetWatchdog(); - usb_pd_available = true;//usb_pd_detect(); + usb_pd_available = usb_pd_detect(); resetWatchdog(); settingsWereReset = restoreSettings(); // load the settings from flash - /*if (MMA8652FC::detect()) { - PCBVersion = 1; - MMA8652FC::initalize(); // this sets up the I2C registers - } else if (LIS2DH12::detect()) { - PCBVersion = 2; - // Setup the ST Accelerometer - LIS2DH12::initalize(); // startup the accelerometer - } else*/{ +#ifdef ACCEL_MMA + if (MMA8652FC::detect()) { + PCBVersion = 1; + MMA8652FC::initalize(); // this sets up the I2C registers + } else +#endif +#ifdef ACCEL_LIS + if (LIS2DH12::detect()) { + PCBVersion = 2; + // Setup the ST Accelerometer + LIS2DH12::initalize(); // startup the accelerometer + } else +#endif + { PCBVersion = 3; systemSettings.SleepTime = 0; systemSettings.ShutdownTime = 0; // No accel -> disable sleep diff --git a/workspace/TS100/Core/Threads/MOVThread.cpp b/workspace/TS100/Core/Threads/MOVThread.cpp index 5d236ba1..4ca5e54b 100644 --- a/workspace/TS100/Core/Threads/MOVThread.cpp +++ b/workspace/TS100/Core/Threads/MOVThread.cpp @@ -25,7 +25,6 @@ uint32_t lastMovementTime = 0; void startMOVTask(void const *argument __unused) { OLED::setRotation(systemSettings.OrientationMode & 1); postRToSInit(); - power_probe(); lastMovementTime = 0; int16_t datax[MOVFilter] = { 0 }; int16_t datay[MOVFilter] = { 0 }; @@ -39,13 +38,20 @@ void startMOVTask(void const *argument __unused) { for (;;) { int32_t threshold = 1500 + (9 * 200); threshold -= systemSettings.sensitivity * 200; // 200 is the step size - +#ifdef ACCEL_LIS if (PCBVersion == 2) { LIS2DH12::getAxisReadings(tx, ty, tz); rotation = LIS2DH12::getOrientation(); - } else if (PCBVersion == 1) { + } else +#endif +#ifdef ACCEL_MMA + if (PCBVersion == 1) { MMA8652FC::getAxisReadings(tx, ty, tz); rotation = MMA8652FC::getOrientation(); + }else +#endif + { + //do nothing :( } if (systemSettings.OrientationMode == 2) { if (rotation != ORIENTATION_FLAT) { From e2c5e51fe19b2e4416e758590fbf71732dad6758 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 1 Aug 2020 21:16:23 +1000 Subject: [PATCH 44/53] Refactor to 1khz RToS --- workspace/TS100/Core/Drivers/Buttons.cpp | 2 +- workspace/TS100/Core/Drivers/OLED.cpp | 2 +- workspace/TS100/Core/Inc/FreeRTOSConfig.h | 2 +- workspace/TS100/Core/Inc/gui.hpp | 4 +-- workspace/TS100/Core/Src/QC3.c | 2 +- workspace/TS100/Core/Src/gui.cpp | 12 ++++---- workspace/TS100/Core/Threads/GUIThread.cpp | 35 ++++++++-------------- workspace/TS100/Core/Threads/PIDThread.cpp | 4 +-- 8 files changed, 27 insertions(+), 36 deletions(-) diff --git a/workspace/TS100/Core/Drivers/Buttons.cpp b/workspace/TS100/Core/Drivers/Buttons.cpp index beca08b1..8aa47833 100644 --- a/workspace/TS100/Core/Drivers/Buttons.cpp +++ b/workspace/TS100/Core/Drivers/Buttons.cpp @@ -24,7 +24,7 @@ ButtonState getButtonState() { */ static uint8_t previousState = 0; static uint32_t previousStateChange = 0; - const uint16_t timeout = 40; + const uint16_t timeout = 400; uint8_t currentState; currentState = (getButtonA()) << 0; currentState |= (getButtonB()) << 1; diff --git a/workspace/TS100/Core/Drivers/OLED.cpp b/workspace/TS100/Core/Drivers/OLED.cpp index a99fe344..7d5eb0b2 100644 --- a/workspace/TS100/Core/Drivers/OLED.cpp +++ b/workspace/TS100/Core/Drivers/OLED.cpp @@ -171,7 +171,7 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) { while (duration <= totalDuration) { duration = xTaskGetTickCount() - start; - uint8_t progress = duration * 100 / totalDuration; + uint8_t progress = duration * 1000 / totalDuration; progress = easeInOutTiming(progress); progress = lerp(0, OLED_WIDTH, progress); if (progress > OLED_WIDTH) { diff --git a/workspace/TS100/Core/Inc/FreeRTOSConfig.h b/workspace/TS100/Core/Inc/FreeRTOSConfig.h index 73303039..e2c1c4c7 100644 --- a/workspace/TS100/Core/Inc/FreeRTOSConfig.h +++ b/workspace/TS100/Core/Inc/FreeRTOSConfig.h @@ -98,7 +98,7 @@ extern uint32_t SystemCoreClock; #define configUSE_IDLE_HOOK 1 #define configUSE_TICK_HOOK 0 #define configCPU_CLOCK_HZ ( SystemCoreClock ) -#define configTICK_RATE_HZ ((TickType_t)100) +#define configTICK_RATE_HZ ((TickType_t)1000) #define configMAX_PRIORITIES ( 6 ) #define configMINIMAL_STACK_SIZE ((uint16_t)256) #define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/ diff --git a/workspace/TS100/Core/Inc/gui.hpp b/workspace/TS100/Core/Inc/gui.hpp index f05d59fb..1b7827d3 100644 --- a/workspace/TS100/Core/Inc/gui.hpp +++ b/workspace/TS100/Core/Inc/gui.hpp @@ -12,8 +12,8 @@ #include "BSP.h" #define PRESS_ACCEL_STEP 3 -#define PRESS_ACCEL_INTERVAL_MIN 10 -#define PRESS_ACCEL_INTERVAL_MAX 30 +#define PRESS_ACCEL_INTERVAL_MIN 100 +#define PRESS_ACCEL_INTERVAL_MAX 300 //GUI holds the menu structure and all its methods for the menu itself diff --git a/workspace/TS100/Core/Src/QC3.c b/workspace/TS100/Core/Src/QC3.c index 0c880a5e..473c14b2 100644 --- a/workspace/TS100/Core/Src/QC3.c +++ b/workspace/TS100/Core/Src/QC3.c @@ -50,7 +50,7 @@ void seekQC(int16_t Vx10, uint16_t divisor) { if (Vx10 < 45) return; - if (xTaskGetTickCount() < 100) + if (xTaskGetTickCount() < 1000) return; if (Vx10 > 130) Vx10 = 130; // Cap max value at 13V diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index 6bc74c0a..eaf71811 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -291,7 +291,7 @@ static int userConfirmation(const char *message) { for (;;) { int16_t messageOffset = ((xTaskGetTickCount() - messageStart) - / (systemSettings.descriptionScrollSpeed == 1 ? 1 : 2)); + / (systemSettings.descriptionScrollSpeed == 1 ? 10 : 20)); messageOffset %= messageWidth; // Roll around at the end if (lastOffset != messageOffset) { @@ -646,7 +646,7 @@ static void settings_setResetSettings(void) { OLED::print(ResetOKMessage); OLED::refresh(); - waitForButtonPressOrTimeout(200); // 2 second timeout + waitForButtonPressOrTimeout(2000); // 2 second timeout } } @@ -731,7 +731,7 @@ static void settings_setCalibrateVIN(void) { OLED::setCursor(0, 0); OLED::printNumber(systemSettings.voltageDiv, 3); OLED::refresh(); - waitForButtonPressOrTimeout(100); + waitForButtonPressOrTimeout(1000); return; break; case BUTTON_NONE: @@ -933,7 +933,7 @@ void gui_Menu(const menuitem *menu) { OLED::setCursor(0, 0); // If the user has hesitated for >=3 seconds, show the long text // Otherwise "draw" the option - if ((xTaskGetTickCount() - lastButtonTime < 300) + if ((xTaskGetTickCount() - lastButtonTime < 3000) || menu[currentScreen].description == NULL) { OLED::clearScreen(); menu[currentScreen].draw.func(); @@ -952,7 +952,7 @@ void gui_Menu(const menuitem *menu) { int16_t descriptionOffset = ((xTaskGetTickCount() - descriptionStart) / (systemSettings.descriptionScrollSpeed == 1 ? - 1 : 2)); + 10 : 20)); descriptionOffset %= descriptionWidth; // Roll around at the end if (lastOffset != descriptionOffset) { OLED::clearScreen(); @@ -1040,7 +1040,7 @@ void gui_Menu(const menuitem *menu) { osDelay(40); lcdRefresh = false; } - if ((xTaskGetTickCount() - lastButtonTime) > (100 * 30)) { + if ((xTaskGetTickCount() - lastButtonTime) > (1000 * 30)) { // If user has not pressed any buttons in 30 seconds, exit back a menu layer // This will trickle the user back to the main screen eventually earlyExit = true; diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 04b5f7bd..afeceeeb 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -246,7 +246,7 @@ static void gui_solderingTempAdjust() { systemSettings.SolderingTemp = 10; } - if (xTaskGetTickCount() - lastChange > 200) + if (xTaskGetTickCount() - lastChange > 2000) return; // exit if user just doesn't press anything for a bit #ifdef OLED_FLIP @@ -299,9 +299,10 @@ static int gui_SolderingSleepingMode(bool stayOff) { ButtonState buttons = getButtonState(); if (buttons) return 0; - if ((xTaskGetTickCount() > 100) - && ((accelInit && (xTaskGetTickCount() - lastMovementTime < 100)) - || (xTaskGetTickCount() - lastButtonTime < 100))) + if ((xTaskGetTickCount() > 1000) + && ((accelInit + && (xTaskGetTickCount() - lastMovementTime < 1000)) + || (xTaskGetTickCount() - lastButtonTime < 1000))) return 0; // user moved or pressed a button, go back to soldering #ifdef MODEL_TS100 if (checkVoltageForExit()) @@ -366,7 +367,7 @@ static int gui_SolderingSleepingMode(bool stayOff) { if (systemSettings.ShutdownTime) // only allow shutdown exit if time > 0 if (lastMovementTime) if (((uint32_t) (xTaskGetTickCount() - lastMovementTime)) - > (uint32_t) (systemSettings.ShutdownTime * 60 * 100)) { + > (uint32_t) (systemSettings.ShutdownTime * 60 * 1000)) { // shutdown currentTempTargetDegC = 0; return 1; // we want to exit soldering mode @@ -386,11 +387,11 @@ static void display_countdown(int sleepThres) { lastButtonTime < lastMovementTime ? lastMovementTime : lastButtonTime; int downCount = sleepThres - xTaskGetTickCount() + lastEventTime; - if (downCount > 9900) { - OLED::printNumber(downCount / 6000 + 1, 2); + if (downCount > 99000) { + OLED::printNumber(downCount / 60000 + 1, 2); OLED::print(SymbolMinutes); } else { - OLED::printNumber(downCount / 100 + 1, 2); + OLED::printNumber(downCount / 1000 + 1, 2); OLED::print(SymbolSeconds); } } @@ -413,9 +414,9 @@ static void gui_solderingMode(uint8_t jumpToSleep) { uint32_t sleepThres = 0; if (systemSettings.SleepTime < 6) - sleepThres = systemSettings.SleepTime * 10 * 100; + sleepThres = systemSettings.SleepTime * 10 * 1000; else - sleepThres = (systemSettings.SleepTime - 5) * 60 * 100; + sleepThres = (systemSettings.SleepTime - 5) * 60 * 1000; if (jumpToSleep) { if (gui_SolderingSleepingMode(jumpToSleep == 2)) { lastButtonTime = xTaskGetTickCount(); @@ -473,9 +474,6 @@ static void gui_solderingMode(uint8_t jumpToSleep) { OLED::setCursor(0, 8); OLED::print(SleepingTipAdvancedString); - // OLED::printNumber( - // TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0)), 5); // Draw the tip temp out finally - gui_drawTipTemp(true); OLED::print(SymbolSpace); printVoltage(); @@ -543,13 +541,6 @@ static void gui_solderingMode(uint8_t jumpToSleep) { lastButtonTime = xTaskGetTickCount(); return; } -#else - // on the TS80 we only want to check for over voltage to prevent tip damage - /*if (getInputVoltageX10(systemSettings.voltageDiv, 1) > 150) { - lastButtonTime = xTaskGetTickCount(); - currentlyActiveTemperatureTarget = 0; - return; // Over voltage - }*/ #endif if (systemSettings.sensitivity && systemSettings.SleepTime) @@ -658,7 +649,7 @@ void startGUITask(void const *argument __unused) { getTipRawTemp(1); // reset filter OLED::setRotation(systemSettings.OrientationMode & 1); uint32_t ticks = xTaskGetTickCount(); - ticks += 400; // 4 seconds from now + ticks += 4000; // 4 seconds from now while (xTaskGetTickCount() < ticks) { if (showBootLogoIfavailable() == false) ticks = xTaskGetTickCount(); @@ -675,7 +666,7 @@ void startGUITask(void const *argument __unused) { OLED::setCursor(0, 0); OLED::print(SettingsResetMessage); OLED::refresh(); - waitForButtonPressOrTimeout(1000); + waitForButtonPressOrTimeout(10000); } if (systemSettings.autoStartMode) { // jump directly to the autostart mode diff --git a/workspace/TS100/Core/Threads/PIDThread.cpp b/workspace/TS100/Core/Threads/PIDThread.cpp index 844e3617..b0e523dc 100644 --- a/workspace/TS100/Core/Threads/PIDThread.cpp +++ b/workspace/TS100/Core/Threads/PIDThread.cpp @@ -14,8 +14,8 @@ #include "FreeRTOS.h" #include "task.h" #include "Settings.h" -static TickType_t powerPulseRate = 1000; -static TickType_t powerPulseDuration = 50; +static TickType_t powerPulseRate = 10000; +static TickType_t powerPulseDuration = 250; TaskHandle_t pidTaskNotification = NULL; uint32_t currentTempTargetDegC = 0; // Current temperature target in C From d47c28b7601eff10daf2feee5a6f514d68ee8a71 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 2 Aug 2020 16:17:41 +1000 Subject: [PATCH 45/53] Use mutex for priority inversion prevention --- workspace/TS100/Core/Drivers/I2CBB.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/workspace/TS100/Core/Drivers/I2CBB.cpp b/workspace/TS100/Core/Drivers/I2CBB.cpp index b878db58..c21a3a97 100644 --- a/workspace/TS100/Core/Drivers/I2CBB.cpp +++ b/workspace/TS100/Core/Drivers/I2CBB.cpp @@ -17,14 +17,19 @@ void I2CBB::init() { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; - GPIO_InitStruct.Pin = SDA2_Pin | SCL2_Pin; + GPIO_InitStruct.Pin = SDA2_Pin ; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(SDA2_GPIO_Port, &GPIO_InitStruct); + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + GPIO_InitStruct.Pin = SCL2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(SCL2_GPIO_Port, &GPIO_InitStruct); SOFT_SDA_HIGH(); SOFT_SCL_HIGH(); - I2CSemaphore = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer); - I2CSemaphore2 = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer2); + I2CSemaphore = xSemaphoreCreateMutexStatic (&xSemaphoreBuffer); + I2CSemaphore2 = xSemaphoreCreateMutexStatic (&xSemaphoreBuffer2); unlock(); unlock2(); @@ -274,9 +279,6 @@ bool I2CBB::lock() { asm("bkpt"); } bool a = xSemaphoreTake(I2CSemaphore, (TickType_t) 100) == pdTRUE; - if (!a) { - asm("bkpt"); - } return a; } @@ -302,9 +304,7 @@ bool I2CBB::lock2() { asm("bkpt"); } bool a = xSemaphoreTake(I2CSemaphore2, (TickType_t) 500) == pdTRUE; - if (!a) { - asm("bkpt"); - } + return a; } #endif From 0d03650726d9b8e613a2870d52d07f7be6d5340e Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 2 Aug 2020 16:17:51 +1000 Subject: [PATCH 46/53] Correct timings --- workspace/TS100/Core/Drivers/FUSB302/pd.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/pd.h b/workspace/TS100/Core/Drivers/FUSB302/pd.h index be1f8453..c3fd1a0e 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/pd.h +++ b/workspace/TS100/Core/Drivers/FUSB302/pd.h @@ -273,13 +273,13 @@ * Where a range is specified, the middle of the range (rounded down to the * nearest millisecond) is used. */ -#define PD_T_CHUNKING_NOT_SUPPORTED (45) -#define PD_T_HARD_RESET_COMPLETE (40) -#define PD_T_PS_TRANSITION (500) -#define PD_T_SENDER_RESPONSE (270) -#define PD_T_SINK_REQUEST (100) -#define PD_T_TYPEC_SINK_WAIT_CAP (45) -#define PD_T_PD_DEBOUNCE (20) +#define PD_T_CHUNKING_NOT_SUPPORTED (450) +#define PD_T_HARD_RESET_COMPLETE (1000) +#define PD_T_PS_TRANSITION (5000) +#define PD_T_SENDER_RESPONSE (2700) +#define PD_T_SINK_REQUEST (1000) +#define PD_T_TYPEC_SINK_WAIT_CAP (7000) +#define PD_T_PD_DEBOUNCE (2000) /* * Counter maximums From d73ad0d11c186239885f1261a848ce4980995981 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 2 Aug 2020 16:18:17 +1000 Subject: [PATCH 47/53] No need to listen to SOP' SOP" now --- workspace/TS100/Core/BSP/Miniware/fusb302b.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp index 0a3fbd2d..9deb8c2f 100644 --- a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp @@ -157,6 +157,9 @@ void fusb_setup() { return; } } + /* Fully reset the FUSB302B */ + fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES); + osDelay(2); if (!fusb_read_id()) { return; } @@ -177,7 +180,7 @@ void fusb_setup() { fusb_write_byte( FUSB_CONTROL2, 0x00); /* Flush the RX buffer */ fusb_write_byte( FUSB_CONTROL1, - FUSB_CONTROL1_RX_FLUSH | FUSB_CONTROL1_ENSOP2 | FUSB_CONTROL1_ENSOP1); + FUSB_CONTROL1_RX_FLUSH); /* Measure CC1 */ fusb_write_byte( FUSB_SWITCHES0, 0x07); @@ -243,8 +246,7 @@ void fusb_reset() { /* Flush the TX buffer */ fusb_write_byte( FUSB_CONTROL0, 0x44); /* Flush the RX buffer */ - fusb_write_byte( FUSB_CONTROL1, - FUSB_CONTROL1_RX_FLUSH | FUSB_CONTROL1_ENSOP2 | FUSB_CONTROL1_ENSOP1); + fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); /* Reset the PD logic */ // fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { From 666c25063028c07e12e5cfdc991144916f27a5bb Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 2 Aug 2020 16:18:32 +1000 Subject: [PATCH 48/53] Setup to basically always pick 5V --- workspace/TS100/Core/BSP/Miniware/BSP.cpp | 2 +- workspace/TS100/Core/BSP/Miniware/BSP_PD.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/BSP.cpp b/workspace/TS100/Core/BSP/Miniware/BSP.cpp index c48f90a5..a2afb4f3 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP.cpp +++ b/workspace/TS100/Core/BSP/Miniware/BSP.cpp @@ -300,7 +300,7 @@ uint8_t getButtonB() { } void reboot() { - asm("bkpt"); + NVIC_SystemReset(); } diff --git a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c index fba573d7..0f41beb3 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c +++ b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c @@ -15,7 +15,7 @@ const uint16_t USB_PD_Desired_Levels[] = { //mV desired input, mA minimum required current 12000, 2000, //12V @ 2A 9000, 2000, //9V @ 2A - 5000, 1100, //5V @ 1.1A + 5000, 100, //5V @ whatever }; const uint8_t USB_PD_Desired_Levels_Len = 3; From 026e5cc9c57ca1babd4d32ba01de45d4eaf40ea3 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 2 Aug 2020 16:18:43 +1000 Subject: [PATCH 49/53] NULL pointer checks for race --- .../TS100/Core/Drivers/FUSB302/hard_reset.cpp | 13 +++++--- .../TS100/Core/Drivers/FUSB302/int_n.cpp | 15 +++++---- workspace/TS100/Core/Drivers/FUSB302/int_n.h | 2 +- .../Core/Drivers/FUSB302/policy_engine.cpp | 32 +++++++------------ .../Drivers/FUSB302/policy_engine_user.cpp | 12 ++----- .../Core/Drivers/FUSB302/protocol_rx.cpp | 17 ++++++---- .../Core/Drivers/FUSB302/protocol_tx.cpp | 31 ++++++++++++------ 7 files changed, 64 insertions(+), 58 deletions(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp index 07426f95..97ffdd71 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp @@ -23,7 +23,7 @@ #include "protocol_tx.h" #include "fusb302b.h" -osThreadId ResetHandler::TaskHandle; +osThreadId ResetHandler::TaskHandle = NULL; uint32_t ResetHandler::TaskBuffer[ResetHandler::TaskStackSize]; osStaticThreadDef_t ResetHandler::TaskControlBlock; @@ -39,7 +39,8 @@ ResetHandler::hardrst_state ResetHandler::hardrst_reset_layer() { ProtocolReceive::notify( PDB_EVT_PRLRX_RESET); taskYIELD(); /* Reset the Protocol TX machine */ - ProtocolTransmit::notify( ProtocolTransmit::Notifications::PDB_EVT_PRLTX_RESET); + ProtocolTransmit::notify( + ProtocolTransmit::Notifications::PDB_EVT_PRLTX_RESET); taskYIELD(); /* Continue the process based on what event started the reset. */ if (evt & PDB_EVT_HARDRST_RESET) { @@ -97,13 +98,15 @@ ResetHandler::hardrst_state ResetHandler::hardrst_complete() { } void ResetHandler::init() { - osThreadStaticDef(rstHand, Thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, - &TaskControlBlock); + osThreadStaticDef(rstHand, Thread, PDB_PRIO_PRL, 0, TaskStackSize, + TaskBuffer, &TaskControlBlock); TaskHandle = osThreadCreate(osThread(rstHand), NULL); } void ResetHandler::notify(uint32_t notification) { - xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits); + if (TaskHandle != NULL) { + xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits); + } } void ResetHandler::Thread(const void *arg) { diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index 4e3dad92..52d7701b 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -28,7 +28,7 @@ #include "task.h" #include "BSP.h" -osThreadId InterruptHandler::TaskHandle; +osThreadId InterruptHandler::TaskHandle=NULL; uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize]; osStaticThreadDef_t InterruptHandler::TaskControlBlock; @@ -46,9 +46,9 @@ void InterruptHandler::Thread(const void *arg) { while (true) { /* If the INT_N line is low */ if (xTaskNotifyWait(0x00, 0x0F, NULL, - PolicyEngine::setupCompleteOrTimedOut() ? 1000 : 200) == pdPASS) { + PolicyEngine::setupCompleteOrTimedOut() ? 1000 : 10) == pdPASS) { //delay slightly so we catch the crc with better timing - osDelay(2); + osDelay(1); } notifSent = false; /* Read the FUSB302B status and interrupt registers */ @@ -99,7 +99,10 @@ void InterruptHandler::Thread(const void *arg) { } } void InterruptHandler::irqCallback() { - BaseType_t taskWoke = pdFALSE; - xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, &taskWoke); - portYIELD_FROM_ISR(taskWoke); + if (TaskHandle != NULL) { + BaseType_t taskWoke = pdFALSE; + xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, + &taskWoke); + portYIELD_FROM_ISR(taskWoke); + } } diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.h b/workspace/TS100/Core/Drivers/FUSB302/int_n.h index e7af6a4c..69c460f7 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.h +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.h @@ -30,7 +30,7 @@ public: private: static void Thread(const void *arg); static osThreadId TaskHandle; - static const size_t TaskStackSize = 1536 / 4; + static const size_t TaskStackSize = 1536 / 3; static uint32_t TaskBuffer[TaskStackSize]; static osStaticThreadDef_t TaskControlBlock; /* diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp index d015dd2a..0e8464fc 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -33,7 +33,7 @@ int8_t PolicyEngine::_hard_reset_counter; int8_t PolicyEngine::_old_tcc_match; uint8_t PolicyEngine::_pps_index; uint8_t PolicyEngine::_last_pps; -osThreadId PolicyEngine::TaskHandle; +osThreadId PolicyEngine::TaskHandle = NULL; uint32_t PolicyEngine::TaskBuffer[PolicyEngine::TaskStackSize]; osStaticThreadDef_t PolicyEngine::TaskControlBlock; union pd_msg PolicyEngine::tempMessage; @@ -42,8 +42,8 @@ PolicyEngine::policy_engine_state PolicyEngine::state = PESinkStartup; StaticQueue_t PolicyEngine::xStaticQueue; uint8_t PolicyEngine::ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)]; -QueueHandle_t PolicyEngine::messagesWaiting; -EventGroupHandle_t PolicyEngine::xEventGroupHandle; +QueueHandle_t PolicyEngine::messagesWaiting = NULL; +EventGroupHandle_t PolicyEngine::xEventGroupHandle = NULL; StaticEventGroup_t PolicyEngine::xCreatedEventGroup; void PolicyEngine::init() { messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, @@ -56,7 +56,9 @@ void PolicyEngine::init() { } void PolicyEngine::notify(uint32_t notification) { - xEventGroupSetBits(xEventGroupHandle, notification); + if (xEventGroupHandle != NULL) { + xEventGroupSetBits(xEventGroupHandle, notification); + } } void PolicyEngine::pe_task(const void *arg) { @@ -228,20 +230,14 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_eval_cap() { /* New capabilities also means we can't be making a request from the * same PPS APDO */ _last_pps = 8; - /* Get a message object for the request if we don't have one already */ - - /* Remember the last PDO we requested if it was a PPS APDO */ - if (PD_RDO_OBJPOS_GET(&_last_dpm_request) >= _pps_index) { - _last_pps = PD_RDO_OBJPOS_GET(&_last_dpm_request); - /* Otherwise, forget any PPS APDO we had requested */ - } else { - _last_pps = 8; - } /* Ask the DPM what to request */ - pdbs_dpm_evaluate_capability(&tempMessage, &_last_dpm_request); + if (pdbs_dpm_evaluate_capability(&tempMessage, &_last_dpm_request)) { - return PESinkSelectCap; + return PESinkSelectCap; + } + + return PESinkWaitCap; } PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { @@ -253,7 +249,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { ProtocolTransmit::notify( ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX); eventmask_t evt = waitForEvent( - PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET, 1000); + PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET); /* If we got reset signaling, transition to default */ if (evt & PDB_EVT_PE_RESET || evt == 0) { return PESinkTransitionDefault; @@ -281,10 +277,6 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() { /* If the source accepted our request, wait for the new power */ if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_ACCEPT && PD_NUMOBJ_GET(&tempMessage) == 0) { - /* Transition to Sink Standby if necessary */ - if (PD_RDO_OBJPOS_GET(&_last_dpm_request) != _last_pps) { - pdbs_dpm_transition_standby(); - } return PESinkTransitionSink; /* If the message was a Soft_Reset, do the soft reset procedure */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp index 8464e06d..71e14f33 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp @@ -114,7 +114,7 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability( /* Update requested voltage */ _requested_voltage = 5000; - /* At this point, we have a capability match iff the output is disabled */ + return false; } @@ -194,9 +194,6 @@ bool PolicyEngine::pdbs_dpm_evaluate_typec_current( return true; } -void PolicyEngine::pdbs_dpm_pd_start() { -//PD neg is starting -} void PolicyEngine::pdbs_dpm_transition_default() { /* Cast the dpm_data to the right type */ @@ -207,13 +204,8 @@ void PolicyEngine::pdbs_dpm_transition_default() { pdNegotiationComplete = false; } -void PolicyEngine::pdbs_dpm_transition_min() { -} -void PolicyEngine::pdbs_dpm_transition_standby() { - /* If the voltage is changing, enter Sink Standby */ -} void PolicyEngine::pdbs_dpm_transition_requested() { /* Cast the dpm_data to the right type */ @@ -229,7 +221,7 @@ bool PolicyEngine::messageWaiting() { } bool PolicyEngine::readMessage() { - return xQueueReceive(messagesWaiting, &tempMessage, 1) == pdTRUE; + return xQueueReceive(messagesWaiting, &tempMessage,0) == pdTRUE; } void PolicyEngine::pdbs_dpm_transition_typec() { diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp index 3e7304cf..132cd6a3 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp @@ -23,7 +23,9 @@ #include "policy_engine.h" #include "protocol_tx.h" #include "fusb302b.h" -osThreadId ProtocolReceive::TaskHandle; +osThreadId ProtocolReceive::TaskHandle = NULL; +EventGroupHandle_t ProtocolReceive::xEventGroupHandle = NULL; +StaticEventGroup_t ProtocolReceive::xCreatedEventGroup; uint32_t ProtocolReceive::TaskBuffer[ProtocolReceive::TaskStackSize]; osStaticThreadDef_t ProtocolReceive::TaskControlBlock; union pd_msg ProtocolReceive::tempMessage; @@ -138,8 +140,6 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_store_messageid( return PRLRxWaitPHY; } -EventGroupHandle_t ProtocolReceive::xEventGroupHandle; -StaticEventGroup_t ProtocolReceive::xCreatedEventGroup; void ProtocolReceive::init() { osThreadStaticDef(protRX, thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, &TaskControlBlock); @@ -175,10 +175,15 @@ void ProtocolReceive::thread(const void *args) { } void ProtocolReceive::notify(uint32_t notification) { - xEventGroupSetBits(xEventGroupHandle, notification); + if (xEventGroupHandle != NULL) { + xEventGroupSetBits(xEventGroupHandle, notification); + } } uint32_t ProtocolReceive::waitForEvent(uint32_t mask, uint32_t ticksToWait) { - return xEventGroupWaitBits(xEventGroupHandle, mask, mask, - pdFALSE, ticksToWait); + if (xEventGroupHandle != NULL) { + return xEventGroupWaitBits(xEventGroupHandle, mask, mask, + pdFALSE, ticksToWait); + } + return 0; } diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp index 7f63a09f..61bdb101 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp @@ -22,16 +22,18 @@ #include "fusb302b.h" #include "fusbpd.h" -osThreadId ProtocolTransmit::TaskHandle; +osThreadId ProtocolTransmit::TaskHandle = NULL; uint32_t ProtocolTransmit::TaskBuffer[ProtocolTransmit::TaskStackSize]; osStaticThreadDef_t ProtocolTransmit::TaskControlBlock; StaticQueue_t ProtocolTransmit::xStaticQueue; bool ProtocolTransmit::messageSending = false; uint8_t ProtocolTransmit::ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)]; -QueueHandle_t ProtocolTransmit::messagesWaiting; +QueueHandle_t ProtocolTransmit::messagesWaiting = NULL; uint8_t ProtocolTransmit::_tx_messageidcounter; union pd_msg ProtocolTransmit::temp_msg; +EventGroupHandle_t ProtocolTransmit::xEventGroupHandle = NULL; +StaticEventGroup_t ProtocolTransmit::xCreatedEventGroup; /* * PRL_Tx_PHY_Layer_Reset state */ @@ -249,10 +251,10 @@ void ProtocolTransmit::thread(const void *args) { } } -EventGroupHandle_t ProtocolTransmit::xEventGroupHandle; -StaticEventGroup_t ProtocolTransmit::xCreatedEventGroup; void ProtocolTransmit::notify(ProtocolTransmit::Notifications notification) { - xEventGroupSetBits(xEventGroupHandle, (uint32_t) notification); + if (xEventGroupHandle != NULL) { + xEventGroupSetBits(xEventGroupHandle, (uint32_t) notification); + } } void ProtocolTransmit::init() { @@ -266,20 +268,29 @@ void ProtocolTransmit::init() { } void ProtocolTransmit::pushMessage(union pd_msg *msg) { - xQueueSend(messagesWaiting, msg, 100); + if (messagesWaiting) { + xQueueSend(messagesWaiting, msg, 100); + } } bool ProtocolTransmit::messagePending() { - return uxQueueMessagesWaiting(messagesWaiting) > 0; + if (messagesWaiting) { + return uxQueueMessagesWaiting(messagesWaiting) > 0; + } } void ProtocolTransmit::getMessage() { //Loads the pending message into the buffer - xQueueReceive(messagesWaiting, &temp_msg, 1); + if (messagesWaiting) { + xQueueReceive(messagesWaiting, &temp_msg, 1); + } } ProtocolTransmit::Notifications ProtocolTransmit::waitForEvent(uint32_t mask, uint32_t ticksToWait) { - return (Notifications) xEventGroupWaitBits(xEventGroupHandle, mask, mask, - pdFALSE, ticksToWait); + if (xEventGroupHandle) { + return (Notifications) xEventGroupWaitBits(xEventGroupHandle, mask, + mask, + pdFALSE, ticksToWait); + } } From c066ec8ae5386ae323edbbebed547f53d6b689d3 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 2 Aug 2020 16:18:50 +1000 Subject: [PATCH 50/53] Setup delay not required anymore --- workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp index 5101f7e9..f6bb58e1 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -23,7 +23,6 @@ void fusb302_start_processing() { /* Initialize the FUSB302B */ resetWatchdog(); fusb_setup(); - osDelay(50); resetWatchdog(); /* Create the policy engine thread. */ PolicyEngine::init(); From e4aab8aa9138212906647965d3644415ffae3601 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 2 Aug 2020 16:27:34 +1000 Subject: [PATCH 51/53] Update pd.h --- workspace/TS100/Core/Drivers/FUSB302/pd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/pd.h b/workspace/TS100/Core/Drivers/FUSB302/pd.h index c3fd1a0e..60cbd26a 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/pd.h +++ b/workspace/TS100/Core/Drivers/FUSB302/pd.h @@ -278,7 +278,7 @@ #define PD_T_PS_TRANSITION (5000) #define PD_T_SENDER_RESPONSE (2700) #define PD_T_SINK_REQUEST (1000) -#define PD_T_TYPEC_SINK_WAIT_CAP (7000) +#define PD_T_TYPEC_SINK_WAIT_CAP (1000) #define PD_T_PD_DEBOUNCE (2000) /* From b370fcfa6fd36920885e33b51b786e2326647d3e Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 2 Aug 2020 16:36:52 +1000 Subject: [PATCH 52/53] Fix warnings --- .../TS100/Core/Drivers/FUSB302/policy_engine_user.cpp | 8 ++------ workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp | 2 ++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp index 71e14f33..4e65cf85 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp @@ -114,7 +114,6 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability( /* Update requested voltage */ _requested_voltage = 5000; - return false; } @@ -186,6 +185,7 @@ void PolicyEngine::pdbs_dpm_get_sink_capability(union pd_msg *cap) { bool PolicyEngine::pdbs_dpm_evaluate_typec_current( enum fusb_typec_current tcc) { + (void) tcc; //This is for evaluating 5V static current advertised by resistors /* We don't control the voltage anymore; it will always be 5 V. */ current_voltage_mv = _requested_voltage = 5000; @@ -194,7 +194,6 @@ bool PolicyEngine::pdbs_dpm_evaluate_typec_current( return true; } - void PolicyEngine::pdbs_dpm_transition_default() { /* Cast the dpm_data to the right type */ @@ -204,9 +203,6 @@ void PolicyEngine::pdbs_dpm_transition_default() { pdNegotiationComplete = false; } - - - void PolicyEngine::pdbs_dpm_transition_requested() { /* Cast the dpm_data to the right type */ pdNegotiationComplete = true; @@ -221,7 +217,7 @@ bool PolicyEngine::messageWaiting() { } bool PolicyEngine::readMessage() { - return xQueueReceive(messagesWaiting, &tempMessage,0) == pdTRUE; + return xQueueReceive(messagesWaiting, &tempMessage, 0) == pdTRUE; } void PolicyEngine::pdbs_dpm_transition_typec() { diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp index 61bdb101..6caeeac3 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp @@ -277,6 +277,7 @@ bool ProtocolTransmit::messagePending() { if (messagesWaiting) { return uxQueueMessagesWaiting(messagesWaiting) > 0; } + return false; } void ProtocolTransmit::getMessage() { @@ -293,4 +294,5 @@ ProtocolTransmit::Notifications ProtocolTransmit::waitForEvent(uint32_t mask, mask, pdFALSE, ticksToWait); } + return (Notifications)0; } From 8faeb4e587ac6097707305e023d0c9d9173e071f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 15 Aug 2020 16:41:28 +1000 Subject: [PATCH 53/53] More accurate TS80P peak 12V current draw --- workspace/TS100/Core/BSP/Miniware/BSP_PD.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c index 0f41beb3..0b3c2af9 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c +++ b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c @@ -13,7 +13,7 @@ */ const uint16_t USB_PD_Desired_Levels[] = { //mV desired input, mA minimum required current - 12000, 2000, //12V @ 2A + 12000, 2400, //12V @ 2.4A 9000, 2000, //9V @ 2A 5000, 100, //5V @ whatever