From 1ddb719bd0521ccaeaeddce656c0468192ffc360 Mon Sep 17 00:00:00 2001 From: Stefan Adolfsson Date: Mon, 7 May 2018 00:13:09 +0200 Subject: npcx: CEC: Add resend-logic to CEC driver According to the CEC specification, a resend must be attempted at least once and up to five times after NAK. This fix does it five times. Signed-off-by: Stefan Adolfsson BUG=b:76467407 BRANCH=none TEST=Write CEC message without sink. Verify with logical analyzer that it resends 5 times. CQ-DEPEND=CL:1030221 Change-Id: Id296e12b6657b9e7ca0453a2deb06e8aaf17f839 Reviewed-on: https://chromium-review.googlesource.com/1030222 Commit-Ready: Stefan Adolfsson Tested-by: Stefan Adolfsson Reviewed-by: Randall Spangler --- chip/npcx/cec.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/chip/npcx/cec.c b/chip/npcx/cec.c index f52e4ff76d..ac597860a5 100644 --- a/chip/npcx/cec.c +++ b/chip/npcx/cec.c @@ -33,8 +33,15 @@ /* CEC broadcast address. Also the highest possible CEC address */ #define CEC_BROADCAST_ADDR 15 +/* + * The CEC specification requires at least one and a maximum of + * five resends attempts + */ +#define CEC_MAX_RESENDS 5 + /* Free time timing (us). */ #define NOMINAL_BIT_TIME APB1_TICKS(2400) +#define FREE_TIME_RS (3 * (NOMINAL_BIT_TIME)) /* Resend */ #define FREE_TIME_NI (5 * (NOMINAL_BIT_TIME)) /* New initiator */ /* Start bit timing (us) */ @@ -107,6 +114,8 @@ struct cec_tx { struct cec_msg_transfer msgt; /* Message length */ uint8_t len; + /* Number of resends attempted in current send */ + uint8_t resends; /* Acknowledge received from sink? */ uint8_t ack; }; @@ -181,7 +190,10 @@ void enter_state(enum cec_state new_state) break; case CEC_STATE_INITIATOR_FREE_TIME: gpio = 1; - timeout = FREE_TIME_NI; + if (cec_tx.resends) + timeout = FREE_TIME_RS; + else + timeout = FREE_TIME_NI; break; case CEC_STATE_INITIATOR_START_LOW: cec_tx.msgt.bit = 0; @@ -301,12 +313,20 @@ static void cec_event_timeout(void) } else { /* Transfer completed successfully */ cec_tx.len = 0; + cec_tx.resends = 0; enter_state(CEC_STATE_IDLE); } } else { - /* Transfer failed */ - cec_tx.len = 0; - enter_state(CEC_STATE_IDLE); + if (cec_tx.resends < CEC_MAX_RESENDS) { + /* Resend */ + cec_tx.resends++; + enter_state(CEC_STATE_INITIATOR_FREE_TIME); + } else { + /* Transfer failed */ + cec_tx.len = 0; + cec_tx.resends = 0; + enter_state(CEC_STATE_IDLE); + } } break; case CEC_STATE_INITIATOR_DATA_LOW: -- cgit v1.2.1