diff options
author | Stefan Adolfsson <sadolfsson@google.com> | 2018-05-07 00:13:09 +0200 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-05-11 09:30:31 -0700 |
commit | 1ddb719bd0521ccaeaeddce656c0468192ffc360 (patch) | |
tree | 66593026a597f283dc93365abd99e0d04de14f6c | |
parent | e89486c9b6751b375fe823a2555c64760dcf832d (diff) | |
download | chrome-ec-1ddb719bd0521ccaeaeddce656c0468192ffc360.tar.gz |
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 <sadolfsson@chromium.org>
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 <sadolfsson@chromium.org>
Tested-by: Stefan Adolfsson <sadolfsson@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r-- | chip/npcx/cec.c | 28 |
1 files 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: |