static int anx74xx_init_analog(int port) { int reg, rv = EC_SUCCESS; /* Analog settings for chip */ rv |= tcpc_write(port, ANX74XX_REG_HPD_CONTROL, ANX74XX_REG_HPD_OP_MODE); rv |= tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, ANX74XX_REG_HPD_DEFAULT); if (rv) return rv; rv = tcpc_read(port, ANX74XX_REG_GPIO_CTRL_4_5, ®); if (rv) return rv; reg &= ANX74XX_REG_VBUS_GPIO_MODE; reg |= ANX74XX_REG_VBUS_OP_ENABLE; rv = tcpc_write(port, ANX74XX_REG_GPIO_CTRL_4_5, reg); if (rv) return rv; rv = tcpc_read(port, ANX74XX_REG_CC_SOFTWARE_CTRL, ®); if (rv) return rv; reg |= ANX74XX_REG_TX_MODE_ENABLE; rv = tcpc_write(port, ANX74XX_REG_CC_SOFTWARE_CTRL, reg); return rv; }
static int tcpci_tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header, const uint32_t *data) { int reg = TCPC_REG_TX_DATA; int rv, cnt = 4*PD_HEADER_CNT(header); /* TX_BYTE_CNT includes 2 bytes for message header */ rv = tcpc_write(port, TCPC_REG_TX_BYTE_CNT, cnt + 2); rv |= tcpc_write16(port, TCPC_REG_TX_HDR, header); /* If tcpc read fails, return error */ if (rv) return rv; if (cnt > 0) { tcpc_lock(port, 1); rv = tcpc_xfer(port, (uint8_t *)®, 1, NULL, 0, I2C_XFER_START); rv |= tcpc_xfer(port, (uint8_t *)data, cnt, NULL, 0, I2C_XFER_STOP); tcpc_lock(port, 0); } /* If tcpc read fails, return error */ if (rv) return rv; rv = tcpc_write(port, TCPC_REG_TRANSMIT, TCPC_REG_TRANSMIT_SET(type)); 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; return fusb302_send_message(port, header, data, buf, buf_pos); case TCPC_TX_HARD_RESET: state[port].tx_hard_reset_req = 1; /* 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: /* Simply hit the BIST_MODE2 bit */ 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; }
static int measure_cc_pin_source(int port, int cc_measure) { int switches0_reg; int reg; int cc_lvl; /* 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; }
static int fusb302_tcpm_set_polarity(int port, int polarity) { /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */ int reg; 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_select_rp_value(int port, int rp) { int reg; int rv; uint8_t vnc, rd; 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; return tcpc_write(port, TCPC_REG_CONTROL0, reg); }
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 { 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 anx74xx_tcpm_mux_exit(int port) { int rv = EC_SUCCESS; rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2, ANX74XX_REG_MODE_TRANS); rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_1, 0x0); rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_5, 0x04); rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2, 0x0); if (rv) return EC_ERROR_UNKNOWN; return rv; }
static int anx7688_mux_set(int i2c_addr, mux_state_t mux_state) { int reg = 0; int rv, polarity; int port = i2c_addr; /* use port index in port_addr field */ rv = tcpc_read(port, TCPC_REG_CONFIG_STD_OUTPUT, ®); if (rv != EC_SUCCESS) return rv; reg &= ~TCPC_REG_CONFIG_STD_OUTPUT_MUX_MASK; if (mux_state & MUX_USB_ENABLED) reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_USB; if (mux_state & MUX_DP_ENABLED) reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_DP; /* ANX7688 needs to set bit0 */ rv = tcpc_read(port, TCPC_REG_TCPC_CTRL, &polarity); if (rv != EC_SUCCESS) return rv; /* copy the polarity from TCPC_CTRL[0], take care clear then set */ reg &= ~TCPC_REG_TCPC_CTRL_POLARITY(1); reg |= TCPC_REG_TCPC_CTRL_POLARITY(polarity); return tcpc_write(port, TCPC_REG_CONFIG_STD_OUTPUT, reg); }
static int anx74xx_read_pd_obj(int port, uint8_t *buf, int plen) { int rv = EC_SUCCESS, i; int reg, addr = ANX74XX_REG_PD_RX_DATA_OBJ; /* Read PD data objects from ANX */ for (i = 0; i < plen ; i++) { /* Register sequence changes for last two bytes, if * plen is greater than 26 */ if (i == 26) addr = ANX74XX_REG_PD_RX_DATA_OBJ_M; rv = tcpc_read(port, addr + i, ®); if (rv) break; buf[i] = reg; } /* Clear receive message interrupt bit(bit-0) */ rv |= tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, ®); rv |= tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, reg & (~0x01)); return rv; }
void anx74xx_tcpc_clear_hpd_status(int port) { int reg; tcpc_read(port, ANX74XX_REG_HPD_CTRL_0, ®); reg &= 0xcf; tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg); }
static void fusb302_flush_tx_fifo(int port) { int reg; tcpc_read(port, TCPC_REG_CONTROL0, ®); reg |= TCPC_REG_CONTROL0_TX_FLUSH; tcpc_write(port, TCPC_REG_CONTROL0, reg); }
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! */ tcpc_write(port, TCPC_REG_CONTROL1, TCPC_REG_CONTROL1_RX_FLUSH); }
static int tcpci_tcpm_set_cc(int port, int pull) { /* * Set manual control of Rp/Rd, and set both CC lines to the same * pull. */ /* TODO: set desired Rp strength */ return tcpc_write(port, TCPC_REG_ROLE_CTRL, TCPC_REG_ROLE_CTRL_SET(0, 0, pull, pull)); }
void anx74xx_tcpc_update_hpd_status(int port, int hpd_lvl, int hpd_irq) { int reg; tcpc_read(port, ANX74XX_REG_HPD_CTRL_0, ®); if (hpd_lvl) reg |= ANX74XX_REG_HPD_OUT_DATA; else reg &= ~ANX74XX_REG_HPD_OUT_DATA; tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg); if (hpd_irq) { tcpc_read(port, ANX74XX_REG_HPD_CTRL_0, ®); reg &= ~ANX74XX_REG_HPD_OUT_DATA; tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg); msleep(1); reg |= ANX74XX_REG_HPD_OUT_DATA; tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg); } }
void anx74xx_tcpc_discharge_vbus(int port, int enable) { int reg; tcpc_read(port, ANX74XX_REG_HPD_CTRL_0, ®); if (enable) reg |= ANX74XX_REG_DISCHARGE_CTRL; else reg &= ~ANX74XX_REG_DISCHARGE_CTRL; tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg); }
void anx74xx_tcpc_set_vbus(int port, int enable) { int reg; tcpc_read(port, ANX74XX_REG_GPIO_CTRL_4_5, ®); if (enable) reg |= ANX74XX_REG_SET_VBUS; else reg &= ~ANX74XX_REG_SET_VBUS; tcpc_write(port, ANX74XX_REG_GPIO_CTRL_4_5, reg); }
static int anx74xx_tcpm_set_msg_header(int port, int power_role, int data_role) { int rv = 0, reg; rv |= tcpc_read(port, ANX74XX_REG_TX_MSG_HEADER, ®); reg |= ((!!power_role) << ANX74XX_REG_PWR_ROLE_BIT_POS); reg |= ((!!data_role) << ANX74XX_REG_DATA_ROLE_BIT_POS); rv |= tcpc_write(port, ANX74XX_REG_TX_MSG_HEADER, reg); return rv; }
int anx74xx_tcpm_init(int port) { int rv = 0, reg; memset(anx, 0, CONFIG_USB_PD_PORT_COUNT*sizeof(struct anx_state)); /* Bring chip in normal mode to work */ anx74xx_set_power_mode(port, ANX74XX_NORMAL_MODE); /* Set Pd dual role mode */ pd_set_dual_role(PD_DRP_TOGGLE_ON); /* Initialize analog section of ANX */ rv |= anx74xx_init_analog(port); /* disable all interrupts */ rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_MASK_1, ANX74XX_REG_CLEAR_SET_BITS); /* Initialize interrupt polarity */ rv |= tcpc_write(port, ANX74XX_REG_IRQ_STATUS, ANX74XX_INT_ACTIVE_POLARITY); /* unmask interrupts */ rv |= tcpc_read(port, ANX74XX_REG_IRQ_EXT_MASK_1, ®); reg &= (~ANX74XX_REG_ALERT_TX_MSG_ERROR); reg &= (~ANX74XX_REG_ALERT_TX_CABLE_RESETOK); reg &= (~ANX74XX_REG_ALERT_TX_HARD_RESETOK); rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_MASK_1, reg); rv |= tcpc_read(port, ANX74XX_REG_IRQ_EXT_MASK_2, ®); reg &= (~ANX74XX_REG_EXT_HARD_RST); rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_MASK_2, reg); /* HPD pin output enable*/ rv |= tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, ANX74XX_REG_HPD_DEFAULT); if (rv) return EC_ERROR_UNKNOWN; return EC_SUCCESS; }
static int anx74xx_alert_status(int port, int *alert) { int reg, rv = EC_SUCCESS; /* Clear soft irq bit */ rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_SOURCE_3, ANX74XX_REG_CLEAR_SOFT_IRQ); /* Read TCPC Alert register1 */ rv |= tcpc_read(port, ANX74XX_REG_IRQ_EXT_SOURCE_1, ®); if (rv) return EC_ERROR_UNKNOWN; /* Clears interrupt bits */ rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_SOURCE_1, reg); *alert = reg; rv = tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, ®); if (rv) return EC_ERROR_UNKNOWN; if (reg & ANX74XX_REG_IRQ_CC_MSG_INT) *alert |= ANX74XX_REG_ALERT_MSG_RECV; else *alert &= (~ANX74XX_REG_ALERT_MSG_RECV); if (reg & ANX74XX_REG_IRQ_CC_STATUS_INT) { *alert |= ANX74XX_REG_ALERT_CC_CHANGE; rv |= tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, reg & 0xfd); } else { *alert &= (~ANX74XX_REG_ALERT_CC_CHANGE); } if (reg & ANX74XX_REG_IRQ_GOOD_CRC_INT) { *alert |= ANX74XX_REG_ALERT_TX_ACK_RECV; rv |= tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, reg & 0xfb); } else { *alert &= (~ANX74XX_REG_ALERT_TX_ACK_RECV); } if (reg & ANX74XX_REG_IRQ_TX_FAIL_INT) { *alert |= ANX74XX_REG_ALERT_TX_MSG_ERROR; rv |= tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, reg & 0xf7); } /* Read TCPC Alert register2 */ rv |= tcpc_read(port, ANX74XX_REG_IRQ_EXT_SOURCE_2, ®); /* Clears interrupt bits */ rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_SOURCE_2, reg); if (reg & ANX74XX_REG_EXT_HARD_RST) *alert |= ANX74XX_REG_ALERT_HARD_RST_RECV; else *alert &= (~ANX74XX_REG_ALERT_HARD_RST_RECV); return rv; }
static int anx74xx_tcpm_set_cc(int port, int pull) { int rv = EC_SUCCESS; int reg; /* Enable CC software Control */ rv |= tcpc_read(port, ANX74XX_REG_CC_SOFTWARE_CTRL, ®); if (rv) return EC_ERROR_UNKNOWN; reg |= ANX74XX_REG_CC_SW_CTRL_ENABLE; rv |= tcpc_write(port, ANX74XX_REG_CC_SOFTWARE_CTRL, reg); if (rv) return EC_ERROR_UNKNOWN; switch (pull) { case TYPEC_CC_RP: /* Enable Rp */ rv |= tcpc_read(port, ANX74XX_REG_ANALOG_STATUS, ®); if (rv) return EC_ERROR_UNKNOWN; reg |= ANX74XX_REG_CC_PULL_RP; rv |= tcpc_write(port, ANX74XX_REG_ANALOG_STATUS, reg); anx[port].pull = 1; break; case TYPEC_CC_RD: /* Enable Rd */ rv |= tcpc_read(port, ANX74XX_REG_ANALOG_STATUS, ®); if (rv) return EC_ERROR_UNKNOWN; reg &= ANX74XX_REG_CC_PULL_RD; rv |= tcpc_write(port, ANX74XX_REG_ANALOG_STATUS, reg); anx[port].pull = 0; break; default: rv = EC_ERROR_UNKNOWN; break; } return rv; }
static void fusb302_auto_goodcrc_enable(int port, int enable) { int reg; 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); }
static void anx74xx_tcpm_set_auto_good_crc(int port, int enable) { int reg; if (enable) { /* Set default header for Good CRC auto reply */ tcpc_read(port, ANX74XX_REG_TX_MSG_HEADER, ®); reg |= (PD_REV20 << ANX74XX_REG_SPEC_REV_BIT_POS); reg |= ANX74XX_REG_AUTO_GOODCRC_EN; tcpc_write(port, ANX74XX_REG_TX_MSG_HEADER, reg); reg = ANX74XX_REG_ENABLE_GOODCRC; tcpc_write(port, ANX74XX_REG_TX_AUTO_GOODCRC_2, reg); /* Set bit-0 if enable, reset bit-0 if disable */ tcpc_read(port, ANX74XX_REG_TX_AUTO_GOODCRC_1, ®); reg |= ANX74XX_REG_AUTO_GOODCRC_EN; } else { reg &= ~ANX74XX_REG_AUTO_GOODCRC_EN; tcpc_write(port, ANX74XX_REG_TX_AUTO_GOODCRC_2, 0); } tcpc_write(port, ANX74XX_REG_TX_AUTO_GOODCRC_1, reg); }
static int anx74xx_tcpm_mux_set(int i2c_addr, mux_state_t mux_state) { int reg = 0, val = 0; int rv; int port = i2c_addr; rv = tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_5, ®); if (rv) return EC_ERROR_UNKNOWN; reg &= 0x0f; if (mux_state & MUX_USB_ENABLED) { /* Set pin assignment D */ if (mux_state & MUX_POLARITY_INVERTED) { val = ANX74XX_REG_MUX_DP_MODE_BDF_CC2; reg |= ANX74XX_REG_MUX_SSTX_B; } else { val = ANX74XX_REG_MUX_DP_MODE_BDF_CC1; reg |= ANX74XX_REG_MUX_SSTX_A; } } else if (mux_state & MUX_DP_ENABLED) { /* Set pin assignment C */ if (mux_state & MUX_POLARITY_INVERTED) { val = ANX74XX_REG_MUX_DP_MODE_ACE_CC2; reg |= ANX74XX_REG_MUX_ML2_B; } else { val = ANX74XX_REG_MUX_DP_MODE_ACE_CC1; reg |= ANX74XX_REG_MUX_ML2_A; } } else { return EC_ERROR_UNIMPLEMENTED; } rv = tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_1, val); rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_5, reg); anx[port].mux_state = mux_state; return rv; }
static int anx74xx_tcpm_set_rx_enable(int port, int enable) { int reg, rv = 0; rv |= tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK, ®); if (enable) reg &= ~(ANX74XX_REG_IRQ_CC_MSG_INT); else/* Disable RX message by masking interrupt */ reg |= (ANX74XX_REG_IRQ_CC_MSG_INT); anx74xx_tcpm_set_auto_good_crc(port, enable); rv |= tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK, reg); return rv; }
static int init_power_status_mask(int port) { uint8_t mask; int rv; #ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC mask = TCPC_REG_POWER_STATUS_VBUS_PRES; #else mask = 0; #endif rv = tcpc_write(port, TCPC_REG_POWER_STATUS_MASK , mask); return rv; }
static int anx74xx_tcpm_get_message(int port, uint32_t *payload, int *head) { int reg = 0, rv = EC_SUCCESS; int len = 0; /* Fetch the header */ rv |= tcpc_read16(port, ANX74XX_REG_PD_HEADER, ®); if (rv) { *head = 0; /* Clear receive message interrupt bit(bit-0) */ tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, ®); tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, reg & (~0x01)); return EC_ERROR_UNKNOWN; } *head = reg; len = PD_HEADER_CNT(*head) * 4; if (!len) { /* Clear receive message interrupt bit(bit-0) */ tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, ®); tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, reg & (~0x01)); return EC_SUCCESS; } /* Receive message : assuming payload have enough * memory allocated */ rv |= anx74xx_read_pd_obj(port, (uint8_t *)payload, len); if (rv) { *head = 0; return EC_ERROR_UNKNOWN; } return rv; }
static int anx74xx_tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header, const uint32_t *data) { uint8_t len = 0; int ret = 0, reg = 0; switch (type) { /* ANX is aware of type */ case TCPC_TX_SOP: case TCPC_TX_SOP_PRIME: case TCPC_TX_SOP_PRIME_PRIME: len = PD_HEADER_CNT(header) * 4 + 2; ret = anx74xx_send_message(port, header, data, type, len); break; case TCPC_TX_HARD_RESET: /* Request HARD RESET */ tcpc_read(port, ANX74XX_REG_TX_CTRL_1, ®); reg |= ANX74XX_REG_TX_HARD_RESET_REQ; ret = tcpc_write(port, ANX74XX_REG_TX_CTRL_1, reg); break; case TCPC_TX_CABLE_RESET: /* Request CABLE RESET */ tcpc_read(port, ANX74XX_REG_TX_CTRL_1, ®); reg |= ANX74XX_REG_TX_CABLE_RESET_REQ; ret = tcpc_write(port, ANX74XX_REG_TX_CTRL_1, reg); break; case TCPC_TX_BIST_MODE_2: /* Request BIST MODE 2 */ reg = ANX74XX_REG_TX_BIST_START | ANX74XX_REG_TX_BIXT_FOREVER | (0x02 << 4); ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL, reg); msleep(1); ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL, reg | ANX74XX_REG_TX_BIST_ENABLE); msleep(30); tcpc_read(port, ANX74XX_REG_TX_BIST_CTRL, ®); ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL, reg | ANX74XX_REG_TX_BIST_STOP); ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL, reg & (~ANX74XX_REG_TX_BIST_STOP)); ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL, 0); break; default: return EC_ERROR_UNIMPLEMENTED; } return ret; }
static void anx7688_update_hpd_enable(int port) { int status, reg, rv; rv = tcpc_read(port, ANX7688_REG_STATUS, &status); rv |= tcpc_read(port, ANX7688_REG_HPD, ®); if (rv) return; if (!(reg & ANX7688_REG_HPD_ENABLE) || !(status & ANX7688_REG_STATUS_LINK)) { reg &= ~ANX7688_REG_HPD_IRQ; tcpc_write(port, ANX7688_REG_HPD, (status & ANX7688_REG_STATUS_LINK) ? reg | ANX7688_REG_HPD_ENABLE : reg & ~ANX7688_REG_HPD_ENABLE); } }
static int anx74xx_set_mux(int port, int polarity) { int reg, rv = EC_SUCCESS; rv = tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_2, ®); if (rv) return EC_ERROR_UNKNOWN; if (polarity) { reg |= ANX74XX_REG_AUX_SWAP_SET_CC2; reg &= ~ANX74XX_REG_AUX_SWAP_SET_CC1; } else { reg |= ANX74XX_REG_AUX_SWAP_SET_CC1; reg &= ~ANX74XX_REG_AUX_SWAP_SET_CC2; } rv = tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg); return rv; }