diff --git a/driver/tcpm/anx74xx.c b/driver/tcpm/anx74xx.c index 889d4f0bd4..229e79a7c2 100644 --- a/driver/tcpm/anx74xx.c +++ b/driver/tcpm/anx74xx.c @@ -23,6 +23,14 @@ struct anx_state { int vconn_en; int mux_state; }; +#define clear_recvd_msg_int(port) do {\ + int reg, rv; \ + rv = tcpc_read(port, ANX74XX_REG_RECVD_MSG_INT, ®); \ + if (!rv) \ + tcpc_write(port, ANX74XX_REG_RECVD_MSG_INT, \ + reg | 0x01); \ + } while (0) + static struct anx_state anx[CONFIG_USB_PD_PORT_COUNT]; static int anx74xx_set_mux(int port, int polarity); @@ -294,8 +302,20 @@ static int anx74xx_send_message(int port, uint16_t header, int reg, rv = EC_SUCCESS; uint8_t *buf = NULL; int num_retry = 0, i = 0; - - + /* If sending Soft_reset, clear received message */ + /* Soft Reset Message type = 1101 and Number of Data Object = 0 */ + if ((header & 0x700f) == 0x000d) { + /* + * When sending soft reset, + * the Rx buffer of ANX3429 shall be clear + */ + rv = tcpc_read(port, ANX74XX_REG_CTRL_FW, ®); + rv |= tcpc_write( + port, ANX74XX_REG_CTRL_FW, reg | CLEAR_RX_BUFFER); + if (rv) + return EC_ERROR_UNKNOWN; + tcpc_write(port, ANX74XX_REG_RECVD_MSG_INT, 0xFF); + } /* Inform chip about message length and TX type * type->bit-0..2, len->bit-3..7 */ @@ -375,12 +395,7 @@ static int anx74xx_read_pd_obj(int port, 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)); - + clear_recvd_msg_int(port); return rv; } @@ -388,58 +403,41 @@ static int anx74xx_tcpm_get_cc(int port, int *cc1, int *cc2) { int rv = EC_SUCCESS; int reg = 0; - int status = 0; - - rv |= tcpc_read(port, ANX74XX_REG_ANALOG_STATUS, ®); - + rv |= tcpc_read(port, ANX74XX_REG_CC_STATUS, ®); if (!anx[port].pull) {/* get CC in sink mode */ - rv |= tcpc_read(port, ANX74XX_REG_POWER_DOWN_CTRL, ®); - if (rv) - return EC_ERROR_UNKNOWN; /* CC1 */ - if (reg & ANX74XX_REG_STATUS_CC1_VRD_USB) + if (reg & BIT_VALUE_OF_SNK_CC1_DEFAULT) *cc1 = TYPEC_CC_VOLT_SNK_DEF; - else if (reg & ANX74XX_REG_STATUS_CC1_VRD_1P5) + else if (reg & BIT_VALUE_OF_SNK_CC1_1_P_5) *cc1 = TYPEC_CC_VOLT_SNK_1_5; - else if (reg & ANX74XX_REG_STATUS_CC1_VRD_3P0) + else if (reg & BIT_VALUE_OF_SNK_CC1_3_P_0) *cc1 = TYPEC_CC_VOLT_SNK_3_0; else *cc1 = TYPEC_CC_VOLT_OPEN; /* CC2 */ - if (reg & ANX74XX_REG_STATUS_CC2_VRD_USB) + if (reg & BIT_VALUE_OF_SNK_CC2_DEFAULT) *cc2 = TYPEC_CC_VOLT_SNK_DEF; - else if (reg & ANX74XX_REG_STATUS_CC2_VRD_1P5) + else if (reg & BIT_VALUE_OF_SNK_CC2_1_P_5) *cc2 = TYPEC_CC_VOLT_SNK_1_5; - else if (reg & ANX74XX_REG_STATUS_CC2_VRD_3P0) + else if (reg & BIT_VALUE_OF_SNK_CC2_3_P_0) *cc2 = TYPEC_CC_VOLT_SNK_3_0; else *cc2 = TYPEC_CC_VOLT_OPEN; } else {/* get CC in source mode */ - rv |= tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_7, ®); - if (rv) - return EC_ERROR_UNKNOWN; /* CC1 */ - status = ANX74XX_REG_STATUS_CC1(reg); - if (status) { - if ((status & ANX74XX_REG_STATUS_CC_RA) == - ANX74XX_REG_STATUS_CC_RA) - *cc1 = TYPEC_CC_VOLT_RA; - else if (status & ANX74XX_REG_STATUS_CC_RD) - *cc1 = TYPEC_CC_VOLT_RD; - } else { - *cc1 = TYPEC_CC_VOLT_OPEN; - } + if (reg & BIT_VALUE_OF_SRC_CC1_RA) + *cc1 = TYPEC_CC_VOLT_RA; + else if (reg & BIT_VALUE_OF_SRC_CC1_RD) + *cc1 = TYPEC_CC_VOLT_RD; + else + *cc1 = TYPEC_CC_VOLT_OPEN; /* CC2 */ - status = ANX74XX_REG_STATUS_CC2(reg); - if (status) { - if ((status & ANX74XX_REG_STATUS_CC_RA) == - ANX74XX_REG_STATUS_CC_RA) - *cc2 = TYPEC_CC_VOLT_RA; - else if (status & ANX74XX_REG_STATUS_CC_RD) - *cc2 = TYPEC_CC_VOLT_RD; - } else { - *cc2 = TYPEC_CC_VOLT_OPEN; - } + if (reg & BIT_VALUE_OF_SRC_CC2_RA) + *cc2 = TYPEC_CC_VOLT_RA; + else if (reg & BIT_VALUE_OF_SRC_CC2_RD) + *cc2 = TYPEC_CC_VOLT_RD; + else + *cc2 = TYPEC_CC_VOLT_OPEN; } /* clear HPD status*/ if (!(*cc1) && !(*cc2)) { @@ -600,41 +598,32 @@ static int anx74xx_alert_status(int port, int *alert) /* 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; + *alert = 0; rv = tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, ®); if (rv) return EC_ERROR_UNKNOWN; - rv |= tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, 0); + + /*Clear msg received bit, until read it by TCPM*/ + rv |= tcpc_write(port, ANX74XX_REG_RECVD_MSG_INT, (reg & 0xFE)); 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) { + if (reg & ANX74XX_REG_IRQ_CC_STATUS_INT) *alert |= ANX74XX_REG_ALERT_CC_CHANGE; - } else { - *alert &= (~ANX74XX_REG_ALERT_CC_CHANGE); - } - if (reg & ANX74XX_REG_IRQ_GOOD_CRC_INT) { + if (reg & ANX74XX_REG_IRQ_GOOD_CRC_INT) *alert |= ANX74XX_REG_ALERT_TX_ACK_RECV; - } else { - *alert &= (~ANX74XX_REG_ALERT_TX_ACK_RECV); - } - if (reg & ANX74XX_REG_IRQ_TX_FAIL_INT) { + if (reg & ANX74XX_REG_IRQ_TX_FAIL_INT) *alert |= ANX74XX_REG_ALERT_TX_MSG_ERROR; - } + + 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); + /* Read TCPC Alert register2 */ rv |= tcpc_read(port, ANX74XX_REG_IRQ_EXT_SOURCE_2, ®); @@ -643,8 +632,6 @@ static int anx74xx_alert_status(int port, int *alert) if (reg & ANX74XX_REG_EXT_HARD_RST) *alert |= ANX74XX_REG_ALERT_HARD_RST_RECV; - else - *alert &= (~ANX74XX_REG_ALERT_HARD_RST_RECV); return rv; } @@ -661,11 +648,14 @@ static int anx74xx_tcpm_set_rx_enable(int port, int enable) anx74xx_tcpm_set_auto_good_crc(port, 1); anx74xx_rp_control(port, selected_rp); } else { - /* Disable RX message by masking interrupt */ + /* Disable RX message by masking interrupt */ reg |= (ANX74XX_REG_IRQ_CC_MSG_INT); anx74xx_tcpm_set_auto_good_crc(port, 0); anx74xx_rp_control(port, TYPEC_RP_USB); } + /*When this function was call, the interrupt status shall be cleared*/ + tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, 0); + return tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK, reg); } @@ -688,21 +678,15 @@ static int anx74xx_tcpm_get_message(int port, uint32_t *payload, int *head) 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)); - + clear_recvd_msg_int(port); 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; + clear_recvd_msg_int(port); + return EC_SUCCESS; } /* Receive message : assuming payload have enough @@ -738,6 +722,8 @@ static int anx74xx_tcpm_transmit(int port, enum tcpm_transmit_type type, 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); + /*After Hard Reset, TCPM shall disable goodCRC*/ + anx74xx_tcpm_set_auto_good_crc(port, 0); break; case TCPC_TX_CABLE_RESET: /* Request CABLE RESET */ @@ -772,7 +758,7 @@ void anx74xx_tcpc_alert(int port) { int status; - /* Check the alert status */ + /* Check the alert status from anx74xx */ if (anx74xx_alert_status(port, &status)) status = 0; if (status) { diff --git a/driver/tcpm/anx74xx.h b/driver/tcpm/anx74xx.h index 8fc81c0bc0..6e31dbdf7d 100644 --- a/driver/tcpm/anx74xx.h +++ b/driver/tcpm/anx74xx.h @@ -152,6 +152,10 @@ #define ANX74XX_REG_PWR_ROLE_BIT_POS (2) #define ANX74XX_REG_DATA_ROLE_BIT_POS (1) +#define ANX74XX_REG_RECVD_MSG_INT 0x98 +#define ANX74XX_REG_CC_STATUS 0x99 +#define ANX74XX_REG_CTRL_FW 0x2E +#define CLEAR_RX_BUFFER (1) #define ANX74XX_REG_POWER_DOWN_CTRL 0x0d #define ANX74XX_REG_STATUS_CC1_VRD_USB (1 << 7) #define ANX74XX_REG_STATUS_CC1_VRD_1P5 (1 << 6) @@ -160,6 +164,19 @@ #define ANX74XX_REG_STATUS_CC2_VRD_1P5 (1 << 3) #define ANX74XX_REG_STATUS_CC2_VRD_3P0 (1 << 2) +/* defined in the inter-bock Spec: 4.2.10 CC Detect Status */ + +#define BIT_VALUE_OF_SRC_CC1_RD 0x01 +#define BIT_VALUE_OF_SRC_CC1_RA 0x02 +#define BIT_VALUE_OF_SNK_CC1_DEFAULT 0x04 +#define BIT_VALUE_OF_SNK_CC1_1_P_5 0x08 +#define BIT_VALUE_OF_SNK_CC1_3_P_0 0x0C +#define BIT_VALUE_OF_SRC_CC2_RD 0x10 +#define BIT_VALUE_OF_SRC_CC2_RA 0x20 +#define BIT_VALUE_OF_SNK_CC2_DEFAULT 0x40 +#define BIT_VALUE_OF_SNK_CC2_1_P_5 0x80 +#define BIT_VALUE_OF_SNK_CC2_3_P_0 0xC0 + extern const struct tcpm_drv anx74xx_tcpm_drv; extern const struct usb_mux_driver anx74xx_tcpm_usb_mux_driver; void anx74xx_tcpc_set_vbus(int port, int enable);