mfd: fusb302: Don't mistake meaningful packets for Good_CRC
authorzain wang <wzz@rock-chips.com>
Thu, 11 May 2017 07:46:25 +0000 (15:46 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Fri, 12 May 2017 10:20:03 +0000 (18:20 +0800)
If a partner port sends a packet at approximately the same time as we
send a packet, we may end up with the initial packet followed by the
GOOD_CRC reply in our HW FIFO. Don't automatically discard the first
packet in the FIFO. Instead, discard the packet only if it's a GOOD_CRC
packet. And, modify our get_message function to automatically discard
GOOD_CRC in search of a meaningful packet.

In addition, due to interrupt latency, we can't rely on receiving one
interrupt per incoming packet. If our Rx FIFO is non-empty, assume that
it contains at least one packet.

Change-Id: Iaad80a4c55eea3e9e2791d81d7c5d28ce97bd2f5
Signed-off-by: zain wang <wzz@rock-chips.com>
drivers/mfd/fusb302.c

index aea504bbce32f59375b6d8b2e94d27ddb700d8f3..e0c9468b8d205a6751d114be72341bd0e701abe5 100644 (file)
 #define PIN_MAP_E              BIT(4)
 #define PIN_MAP_F              BIT(5)
 
+#define PACKET_IS_GOOD_CRC(header) \
+               (PD_HEADER_TYPE(header) == CMT_GOODCRC && \
+                PD_HEADER_CNT(header) == 0)
+
 static u8 fusb30x_port_used;
 static struct fusb30x_chip *fusb30x_port_info[256];
 
@@ -339,11 +343,14 @@ static int tcpm_get_message(struct fusb30x_chip *chip)
        u8 buf[32];
        int len;
 
-       regmap_raw_read(chip->regmap, FUSB_REG_FIFO, buf, 3);
-       chip->rec_head = (buf[1] & 0xff) | ((buf[2] << 8) & 0xff00);
+       do {
+               regmap_raw_read(chip->regmap, FUSB_REG_FIFO, buf, 3);
+               chip->rec_head = (buf[1] & 0xff) | ((buf[2] << 8) & 0xff00);
 
-       len = PD_HEADER_CNT(chip->rec_head) << 2;
-       regmap_raw_read(chip->regmap, FUSB_REG_FIFO, buf, len + 4);
+               len = PD_HEADER_CNT(chip->rec_head) << 2;
+               regmap_raw_read(chip->regmap, FUSB_REG_FIFO, buf, len + 4);
+       /* ignore good_crc message */
+       } while (PACKET_IS_GOOD_CRC(chip->rec_head));
 
        memcpy(chip->rec_load, buf, len);
 
@@ -352,7 +359,7 @@ static int tcpm_get_message(struct fusb30x_chip *chip)
 
 static void fusb302_flush_rx_fifo(struct fusb30x_chip *chip)
 {
-       tcpm_get_message(chip);
+       regmap_write(chip->regmap, FUSB_REG_CONTROL1, CONTROL1_RX_FLUSH);
 }
 
 static int tcpm_get_cc(struct fusb30x_chip *chip, int *CC1, int *CC2)
@@ -741,7 +748,6 @@ static void tcpc_alert(struct fusb30x_chip *chip, int *evt)
 
        if (interrupta & INTERRUPTA_TXSENT) {
                *evt |= EVENT_TX;
-               fusb302_flush_rx_fifo(chip);
                chip->tx_state = tx_success;
        }