summaryrefslogtreecommitdiff
path: root/chip/it83xx/intc.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/it83xx/intc.c')
-rw-r--r--chip/it83xx/intc.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/chip/it83xx/intc.c b/chip/it83xx/intc.c
index ae52a5d5a2..36a6029f9c 100644
--- a/chip/it83xx/intc.c
+++ b/chip/it83xx/intc.c
@@ -11,8 +11,51 @@
#include "task.h"
#include "tcpm.h"
#include "usb_pd.h"
+#include "console.h"
+
+#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
#ifdef CONFIG_USB_PD_TCPM_ITE83XX
+/* Store each port last message id of received packet */
+static uint8_t message_id_last[USBPD_PORT_COUNT];
+
+/* Invalidate last received message id variable */
+void invalidate_last_message_id(int port)
+{
+ /*
+ * Message id starts from 0 to 7. If static global variable
+ * message_id_last is initialed 0, it will occur repetitive message id
+ * with first received packet, so we initial an invalid value 0xff.
+ */
+ message_id_last[port] = 0xff;
+}
+
+static int consume_repeat_message(int port)
+{
+ uint16_t msg_header = IT83XX_USBPD_RMH(port);
+ int msg_id = PD_HEADER_ID(msg_header);
+ /* pre-set not repeat */
+ int ret = 0;
+
+ /*
+ * Check does message id repeat? if yes don't respond subsequent
+ * messages, except softreset control request.
+ */
+ if (PD_HEADER_TYPE(msg_header) == PD_CTRL_SOFT_RESET &&
+ PD_HEADER_CNT(msg_header) == 0)
+ invalidate_last_message_id(port);
+ else if (message_id_last[port] != msg_id)
+ message_id_last[port] = msg_id;
+ else if (message_id_last[port] == msg_id) {
+ /* If clear this bit, USBPD receives next packet */
+ IT83XX_USBPD_MRSR(port) = USBPD_REG_MASK_RX_MSG_VALID;
+ CPRINTS("receive repetitive msg id: p[%d] id=%d", port, msg_id);
+ ret = 1;
+ }
+
+ return ret;
+}
+
static void chip_pd_irq(enum usbpd_port port)
{
task_clear_pending_irq(usbpd_ctrl_regs[port].irq);
@@ -21,11 +64,14 @@ static void chip_pd_irq(enum usbpd_port port)
if (USBPD_IS_HARD_RESET_DETECT(port)) {
/* clear interrupt */
IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_HARD_RESET_DETECT;
+ /* Invalidate last received message id variable */
+ invalidate_last_message_id(port);
task_set_event(PD_PORT_TO_TASK_ID(port),
PD_EVENT_TCPC_RESET, 0);
} else {
if (USBPD_IS_RX_DONE(port)) {
- tcpm_enqueue_message(port);
+ if (!consume_repeat_message(port))
+ tcpm_enqueue_message(port);
/* clear RX done interrupt */
IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_MSG_RX_DONE;
}