From f5ff35ad9c10adb1aeaaeb477578971294f6227b Mon Sep 17 00:00:00 2001 From: Nicholas Chin Date: Tue, 23 Jul 2019 09:06:29 -0600 Subject: [PATCH] arch/arm/src/imxrt/imxrt_lpi2c.c: Slave addresses are now correctly shifted when sending start. TX/RX FIFOs now discarded on error to prevent FIFO underflow errors. Fixes error checking to use priv structure and removes checking of BBF flag as it is not an error. --- arch/arm/src/imxrt/hardware/imxrt_lpi2c.h | 3 +- arch/arm/src/imxrt/imxrt_lpi2c.c | 302 ++++++++++++---------- 2 files changed, 162 insertions(+), 143 deletions(-) diff --git a/arch/arm/src/imxrt/hardware/imxrt_lpi2c.h b/arch/arm/src/imxrt/hardware/imxrt_lpi2c.h index e48cd49d23..ff293f9367 100644 --- a/arch/arm/src/imxrt/hardware/imxrt_lpi2c.h +++ b/arch/arm/src/imxrt/hardware/imxrt_lpi2c.h @@ -281,7 +281,7 @@ #define LPI2C_MSR_BBF (1 << 25) /* Bus Busy Flag Bit */ /* Bits 31-26 Reserved */ #define LPI2C_MSR_ERROR_MASK (LPI2C_MSR_NDF | LPI2C_MSR_ALF | \ - LPI2C_MSR_BBF | LPI2C_MSR_FEF) + LPI2C_MSR_FEF) /* LPI2C Master Interrupt Enable Register */ @@ -427,7 +427,6 @@ #define LPI2C_MCCR1_DATAVD(n) ((n << LPI2C_MCCR1_DATAVD_SHIFT) & LPI2C_MCCR1_DATAVD_MASK) /* Bits 31-30 Reserved */ - /* LPI2C Master FIFO Control Register */ #define LPI2C_MFCR_TXWATER_SHIFT (0) diff --git a/arch/arm/src/imxrt/imxrt_lpi2c.c b/arch/arm/src/imxrt/imxrt_lpi2c.c index 8309b263f7..8630a1ba92 100644 --- a/arch/arm/src/imxrt/imxrt_lpi2c.c +++ b/arch/arm/src/imxrt/imxrt_lpi2c.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/imxrt/imxrt_lpi2c.c * - * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Copyright (C) 2018-2019 Gregory Nutt. All rights reserved. * Author: Ivan Ucherdzhiev * * Redistribution and use in source and binary forms, with or without @@ -33,9 +33,9 @@ * ****************************************************************************/ -/************************************************************************************ +/**************************************************************************** * Included Files - ************************************************************************************/ + ****************************************************************************/ #include @@ -70,13 +70,14 @@ #if defined(CONFIG_IMXRT_LPI2C1) || defined(CONFIG_IMXRT_LPI2C2) || \ defined(CONFIG_IMXRT_LPI2C3) || defined(CONFIG_IMXRT_LPI2C4) -/************************************************************************************ +/**************************************************************************** * Pre-processor Definitions - ************************************************************************************/ + ****************************************************************************/ -/* Configuration ********************************************************************/ -/* CONFIG_I2C_POLLED may be set so that I2C interrupts will not be used. Instead, - * CPU-intensive polling will be used. +/* Configuration ************************************************************/ + +/* CONFIG_I2C_POLLED may be set so that I2C interrupts will not be used. + * Instead, CPU-intensive polling will be used. */ /* Interrupt wait timeout in seconds and milliseconds */ @@ -101,11 +102,11 @@ # define CONFIG_IMXRT_I2C_DYNTIMEO_STARTSTOP TICK2USEC(CONFIG_IMXRT_I2CTIMEOTICKS) #endif -/* Debug ****************************************************************************/ +/* Debug ********************************************************************/ -/* I2C event trace logic. NOTE: trace uses the internal, non-standard, low-level - * debug interface syslog() but does not require that any other debug - * is enabled. +/* I2C event trace logic. NOTE: trace uses the internal, non-standard, + * low-level debug interface syslog() but does not require that any other + * debug is enabled. */ #ifndef CONFIG_I2C_TRACE @@ -136,9 +137,9 @@ IOMUX_CMOS_INPUT | (5 << GPIO_ALT_SHIFT) | \ IOMUX_PULL_NONE) -/************************************************************************************ +/**************************************************************************** * Private Types - ************************************************************************************/ + ****************************************************************************/ /* Interrupt state */ @@ -196,7 +197,7 @@ struct imxrt_lpi2c_priv_s { const struct i2c_ops_s *ops; /* Standard I2C operations */ const struct imxrt_lpi2c_config_s *config; /* Port configuration */ - int refs; /* Referernce count */ + int refs; /* Reference count */ sem_t sem_excl; /* Mutual exclusion semaphore */ #ifndef CONFIG_I2C_POLLED sem_t sem_isr; /* Interrupt wait semaphore */ @@ -224,9 +225,9 @@ struct imxrt_lpi2c_priv_s uint32_t status; /* End of transfer SR2|SR1 status */ }; -/************************************************************************************ +/**************************************************************************** * Private Function Prototypes - ************************************************************************************/ + ****************************************************************************/ static inline uint32_t imxrt_lpi2c_getreg(FAR struct imxrt_lpi2c_priv_s *priv, uint16_t offset); @@ -249,9 +250,10 @@ static inline void imxrt_lpi2c_sem_destroy(FAR struct imxrt_lpi2c_priv_s *priv); #ifdef CONFIG_I2C_TRACE static void imxrt_lpi2c_tracereset(FAR struct imxrt_lpi2c_priv_s *priv); -static void imxrt_lpi2c_tracenew(FAR struct imxrt_lpi2c_priv_s *priv, uint32_t status); +static void imxrt_lpi2c_tracenew(FAR struct imxrt_lpi2c_priv_s *priv, + uint32_t status); static void imxrt_lpi2c_traceevent(FAR struct imxrt_lpi2c_priv_s *priv, - enum imxrt_trace_e event, uint32_t parm); + enum imxrt_trace_e event, uint32_t parm); static void imxrt_lpi2c_tracedump(FAR struct imxrt_lpi2c_priv_s *priv); #endif /* CONFIG_I2C_TRACE */ @@ -278,9 +280,9 @@ static int imxrt_lpi2c_transfer(FAR struct i2c_master_s *dev, static int imxrt_lpi2c_reset(FAR struct i2c_master_s *dev); #endif -/************************************************************************************ +/**************************************************************************** * Private Data - ************************************************************************************/ + ****************************************************************************/ /* Trace events strings */ @@ -446,17 +448,17 @@ static struct imxrt_lpi2c_priv_s imxrt_lpi2c4_priv = }; #endif -/************************************************************************************ +/**************************************************************************** * Private Functions - ************************************************************************************/ + ****************************************************************************/ -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_getreg * * Description: * Get a 32-bit register value by offset * - ************************************************************************************/ + ****************************************************************************/ static inline uint32_t imxrt_lpi2c_getreg(FAR struct imxrt_lpi2c_priv_s *priv, uint16_t offset) @@ -464,13 +466,13 @@ static inline uint32_t imxrt_lpi2c_getreg(FAR struct imxrt_lpi2c_priv_s *priv, return getreg32(priv->config->base + offset); } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_putreg * * Description: * Put a 32-bit register value by offset * - ************************************************************************************/ + ****************************************************************************/ static inline void imxrt_lpi2c_putreg(FAR struct imxrt_lpi2c_priv_s *priv, uint16_t offset, uint32_t value) @@ -478,13 +480,13 @@ static inline void imxrt_lpi2c_putreg(FAR struct imxrt_lpi2c_priv_s *priv, putreg32(value, priv->config->base + offset); } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_modifyreg * * Description: * Modify a 32-bit register value by offset * - ************************************************************************************/ + ****************************************************************************/ static inline void imxrt_lpi2c_modifyreg(FAR struct imxrt_lpi2c_priv_s *priv, uint16_t offset, uint32_t clearbits, @@ -493,13 +495,13 @@ static inline void imxrt_lpi2c_modifyreg(FAR struct imxrt_lpi2c_priv_s *priv, modifyreg32(priv->config->base + offset, clearbits, setbits); } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_sem_wait * * Description: * Take the exclusive access, waiting as necessary * - ************************************************************************************/ + ****************************************************************************/ static inline void imxrt_lpi2c_sem_wait(FAR struct imxrt_lpi2c_priv_s *priv) { @@ -520,13 +522,14 @@ static inline void imxrt_lpi2c_sem_wait(FAR struct imxrt_lpi2c_priv_s *priv) while (ret == -EINTR); } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_tousecs * * Description: - * Return a micro-second delay based on the number of bytes left to be processed. + * Return a micro-second delay based on the number of bytes left to be + * processed. * - ************************************************************************************/ + ****************************************************************************/ #ifdef CONFIG_IMXRT_I2C_DYNTIMEO static useconds_t imxrt_lpi2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs) @@ -549,13 +552,13 @@ static useconds_t imxrt_lpi2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs) } #endif -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_sem_waitdone * * Description: * Wait for a transfer to complete * - ************************************************************************************/ + ****************************************************************************/ #ifndef CONFIG_I2C_POLLED static inline int imxrt_lpi2c_sem_waitdone(FAR struct imxrt_lpi2c_priv_s *priv) @@ -570,28 +573,27 @@ static inline int imxrt_lpi2c_sem_waitdone(FAR struct imxrt_lpi2c_priv_s *priv) /* Enable Interrupts when master mode */ if (priv->config->mode == LPI2C_MASTER) - { + { if ((priv->flags & I2C_M_READ) != 0) - { + { regval = LPI2C_MIER_TDIE | LPI2C_MIER_RDIE | LPI2C_MIER_NDIE | \ LPI2C_MIER_ALIE | LPI2C_MIER_SDIE; imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MIER_OFFSET, regval); - } + } else - { + { regval = LPI2C_MIER_TDIE | LPI2C_MIER_NDIE | \ LPI2C_MIER_ALIE | LPI2C_MIER_SDIE; imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MIER_OFFSET, regval); - } - - } + } + } /* Enable Interrupts when slave mode */ else - { - #warning Missing logic for I2C Slave mode - } + { +#warning Missing logic for I2C Slave mode + } /* Signal the interrupt handler that we are waiting. NOTE: Interrupts * are currently disabled but will be temporarily re-enabled below when @@ -723,13 +725,13 @@ static inline int imxrt_lpi2c_sem_waitdone(FAR struct imxrt_lpi2c_priv_s *priv) } #endif -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_sem_waitstop * * Description: * Wait for a STOP to complete * - ************************************************************************************/ + ****************************************************************************/ static inline void imxrt_lpi2c_sem_waitstop(FAR struct imxrt_lpi2c_priv_s *priv) { @@ -811,26 +813,26 @@ static inline void imxrt_lpi2c_sem_waitstop(FAR struct imxrt_lpi2c_priv_s *priv) i2cinfo("Timeout with Status Register: %x\n", regval); } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_sem_post * * Description: * Release the mutual exclusion semaphore * - ************************************************************************************/ + ****************************************************************************/ static inline void imxrt_lpi2c_sem_post(struct imxrt_lpi2c_priv_s *priv) { nxsem_post(&priv->sem_excl); } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_sem_init * * Description: * Initialize semaphores * - ************************************************************************************/ + ****************************************************************************/ static inline void imxrt_lpi2c_sem_init(FAR struct imxrt_lpi2c_priv_s *priv) { @@ -846,13 +848,13 @@ static inline void imxrt_lpi2c_sem_init(FAR struct imxrt_lpi2c_priv_s *priv) #endif } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_sem_destroy * * Description: * Destroy semaphores. * - ************************************************************************************/ + ****************************************************************************/ static inline void imxrt_lpi2c_sem_destroy(FAR struct imxrt_lpi2c_priv_s *priv) { @@ -862,13 +864,13 @@ static inline void imxrt_lpi2c_sem_destroy(FAR struct imxrt_lpi2c_priv_s *priv) #endif } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_trace* * * Description: * I2C trace instrumentation * - ************************************************************************************/ + ****************************************************************************/ #ifdef CONFIG_I2C_TRACE static void imxrt_lpi2c_traceclear(FAR struct imxrt_lpi2c_priv_s *priv) @@ -891,7 +893,8 @@ static void imxrt_lpi2c_tracereset(FAR struct imxrt_lpi2c_priv_s *priv) imxrt_lpi2c_traceclear(priv); } -static void imxrt_lpi2c_tracenew(FAR struct imxrt_lpi2c_priv_s *priv, uint32_t status) +static void imxrt_lpi2c_tracenew(FAR struct imxrt_lpi2c_priv_s *priv, + uint32_t status) { struct imxrt_trace_s *trace = &priv->trace[priv->tndx]; @@ -905,7 +908,7 @@ static void imxrt_lpi2c_tracenew(FAR struct imxrt_lpi2c_priv_s *priv, uint32_t s { /* Yes.. bump up the trace index (unless we are out of trace entries) */ - if (priv->tndx >= (CONFIG_I2C_NTRACE-1)) + if (priv->tndx >= (CONFIG_I2C_NTRACE - 1)) { i2cerr("ERROR: Trace table overflow\n"); return; @@ -946,7 +949,7 @@ static void imxrt_lpi2c_traceevent(FAR struct imxrt_lpi2c_priv_s *priv, /* Bump up the trace index (unless we are out of trace entries) */ - if (priv->tndx >= (CONFIG_I2C_NTRACE-1)) + if (priv->tndx >= (CONFIG_I2C_NTRACE - 1)) { i2cerr("ERROR: Trace table overflow\n"); return; @@ -970,19 +973,19 @@ static void imxrt_lpi2c_tracedump(FAR struct imxrt_lpi2c_priv_s *priv) trace = &priv->trace[i]; syslog(LOG_DEBUG, "%2d. STATUS: %08x COUNT: %3d EVENT: %s(%2d) PARM: %08x TIME: %d\n", - i+1, trace->status, trace->count, g_trace_names[trace->event], + i + 1, trace->status, trace->count, g_trace_names[trace->event], trace->event, trace->parm, trace->time - priv->start_time); } } #endif /* CONFIG_I2C_TRACE */ -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_setclock * * Description: * Set the I2C clock * - ************************************************************************************/ + ****************************************************************************/ static void imxrt_lpi2c_setclock(FAR struct imxrt_lpi2c_priv_s *priv, uint32_t frequency) @@ -1038,19 +1041,23 @@ static void imxrt_lpi2c_setclock(FAR struct imxrt_lpi2c_priv_s *priv, pll3_div = 20; } - lpi2c_clk_div = (getreg32(IMXRT_CCM_CSCDR2) & CCM_CSCDR2_LPI2C_CLK_PODF_MASK) >> + lpi2c_clk_div = (getreg32(IMXRT_CCM_CSCDR2) & + CCM_CSCDR2_LPI2C_CLK_PODF_MASK) >> CCM_CSCDR2_LPI2C_CLK_PODF_SHIFT; lpi2c_clk_div = lpi2c_clk_div + 1; - src_freq = (BOARD_XTAL_FREQUENCY * pll3_div) / (8 * lpi2c_clk_div) ; + src_freq = (BOARD_XTAL_FREQUENCY * pll3_div) / + (8 * lpi2c_clk_div) ; } - /* LPI2C output frequency = (Source Clock (Hz)/ 2^prescale) / (CLKLO + 1 + CLKHI + 1 + - * ROUNDDOWN((2 + FILTSCL) / 2^prescale) + /* LPI2C output frequency = (Source Clock (Hz)/ 2^prescale) / + * (CLKLO + 1 + CLKHI + 1 + ROUNDDOWN((2 + FILTSCL) / 2^prescale) * * Assume CLKLO = 2 * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI / 2 */ - for (prescale = 1; (prescale <= 128) && (best_error != 0); prescale *= 2) + for (prescale = 1; + (prescale <= 128) && (best_error != 0); + prescale *= 2) { for (clk_hi_cycle = 1; clk_hi_cycle < 32; clk_hi_cycle++) { @@ -1062,7 +1069,8 @@ static void imxrt_lpi2c_setclock(FAR struct imxrt_lpi2c_priv_s *priv, else { computed_rate = (src_freq / prescale) / - ((3 * clk_hi_cycle + 2) + (2 / prescale)); + ((3 * clk_hi_cycle + 2) + + (2 / prescale)); } if (frequency > computed_rate) @@ -1092,12 +1100,14 @@ static void imxrt_lpi2c_setclock(FAR struct imxrt_lpi2c_priv_s *priv, if (best_clk_hi < 2) { - regval |= LPI2C_MCCR0_CLKLO(3) | LPI2C_MCCR0_SETHOLD(2) | LPI2C_MCCR0_DATAVD(1); + regval |= LPI2C_MCCR0_CLKLO(3) | LPI2C_MCCR0_SETHOLD(2) | + LPI2C_MCCR0_DATAVD(1); } else { - regval |= LPI2C_MCCR0_CLKLO(2 * best_clk_hi) | LPI2C_MCCR0_SETHOLD(best_clk_hi) | - LPI2C_MCCR0_DATAVD(best_clk_hi / 2); + regval |= LPI2C_MCCR0_CLKLO(2 * best_clk_hi) | + LPI2C_MCCR0_SETHOLD(best_clk_hi) | + LPI2C_MCCR0_DATAVD(best_clk_hi / 2); } imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MCCR0_OFFSET, regval); @@ -1125,17 +1135,17 @@ static void imxrt_lpi2c_setclock(FAR struct imxrt_lpi2c_priv_s *priv, /* Save the new LPI2C frequency */ priv->frequency = frequency; - } + } } } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_sendstart * * Description: * Send the START conditions/force Master mode * - ************************************************************************************/ + ****************************************************************************/ static inline void imxrt_lpi2c_sendstart(FAR struct imxrt_lpi2c_priv_s *priv, uint8_t address) @@ -1145,9 +1155,11 @@ static inline void imxrt_lpi2c_sendstart(FAR struct imxrt_lpi2c_priv_s *priv, uint8_t addr; /* Generate START condition and send the address */ + /* Turn off auto_stop option */ - imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MCFGR1_OFFSET, LPI2C_MCFGR1_IGNACK, 0); + imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MCFGR1_OFFSET, + LPI2C_MCFGR1_IGNACK, 0); do { @@ -1159,57 +1171,58 @@ static inline void imxrt_lpi2c_sendstart(FAR struct imxrt_lpi2c_priv_s *priv, if (status & LPI2C_MSR_ERROR_MASK) { - imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MSR_OFFSET, status & LPI2C_MSR_ERROR_MASK); + imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MSR_OFFSET, + status & LPI2C_MSR_ERROR_MASK); } } while (txcount == 0); if ((priv->flags & I2C_M_READ) != 0) { - addr = address | 0x01; + addr = I2C_READADDR8(address); } else { - addr = address; + addr = I2C_WRITEADDR8(address); } imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MTDR_OFFSET, (LPI2C_MTDR_CMD_START | LPI2C_MTDR_DATA(addr))); } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_sendstop * * Description: * Send the STOP conditions * - ************************************************************************************/ + ****************************************************************************/ static inline void imxrt_lpi2c_sendstop(FAR struct imxrt_lpi2c_priv_s *priv) { imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MTDR_OFFSET, LPI2C_MTDR_CMD_STOP); } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_getstatus * * Description: * Get 32-bit status * - ************************************************************************************/ + ****************************************************************************/ static inline uint32_t imxrt_lpi2c_getstatus(FAR struct imxrt_lpi2c_priv_s *priv) { return imxrt_lpi2c_getreg(priv, IMXRT_LPI2C_MSR_OFFSET); } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_isr_process * * Description: * Common Interrupt Service Routine * - ************************************************************************************/ + ****************************************************************************/ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv) { @@ -1221,7 +1234,7 @@ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv) /* Continue with either sending or reading data */ - /* Check if there is more butes to send */ + /* Check if there is more bytes to send */ if (((priv->flags & I2C_M_READ) == 0) && (status & LPI2C_MSR_TDF) != 0) { @@ -1229,7 +1242,8 @@ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv) { imxrt_lpi2c_traceevent(priv, I2CEVENT_SENDBYTE, priv->dcnt); imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MTDR_OFFSET, - LPI2C_MTDR_CMD_TXD | LPI2C_MTDR_DATA(*priv->ptr++)); + LPI2C_MTDR_CMD_TXD | + LPI2C_MTDR_DATA(*priv->ptr++)); priv->dcnt--; if ((priv->msgc <= 0) && (priv->dcnt == 0)) @@ -1307,7 +1321,10 @@ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv) LPI2C_MIER_TDIE, LPI2C_MIER_RDIE); #endif /* Set LPI2C in read mode */ - imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MTDR_OFFSET, LPI2C_MTDR_CMD_RXD | LPI2C_MTDR_DATA((priv->dcnt - 1))); + + imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MTDR_OFFSET, + LPI2C_MTDR_CMD_RXD | + LPI2C_MTDR_DATA((priv->dcnt - 1))); } else { @@ -1315,15 +1332,14 @@ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv) imxrt_lpi2c_traceevent(priv, I2CEVENT_SENDBYTE, priv->dcnt); imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MTDR_OFFSET, - LPI2C_MTDR_CMD_TXD | LPI2C_MTDR_DATA(*priv->ptr++)); + LPI2C_MTDR_CMD_TXD | + LPI2C_MTDR_DATA(*priv->ptr++)); priv->dcnt--; if ((priv->msgc <= 0) && (priv->dcnt == 0)) { imxrt_lpi2c_sendstop(priv); } - } - - + } } else if (priv->msgv && ((status & LPI2C_MSR_SDF) != 0)) { @@ -1365,14 +1381,20 @@ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv) imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MSR_OFFSET, LPI2C_MSR_EPF); } - if ((status & (LPI2C_MSR_NDF | LPI2C_MSR_ALF | LPI2C_MSR_FEF)) != 0) + if ((status & LPI2C_MSR_ERROR_MASK) != 0) { imxrt_lpi2c_traceevent(priv, I2CEVENT_ERROR, 0); + /* Clear the TX and RX FIFOs */ + + imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MCR_OFFSET, 0, + LPI2C_MCR_RTF | LPI2C_MCR_RRF); + /* Clear the error */ imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MSR_OFFSET, - (status & (LPI2C_MSR_NDF | LPI2C_MSR_ALF | LPI2C_MSR_FEF))); + (status & (LPI2C_MSR_NDF | LPI2C_MSR_ALF | + LPI2C_MSR_FEF))); #ifndef CONFIG_I2C_POLLED if (priv->intstate == INTSTATE_WAITING) @@ -1393,13 +1415,13 @@ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv) return OK; } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_isr * * Description: * Common I2C interrupt service routine * - ************************************************************************************/ + ****************************************************************************/ #ifndef CONFIG_I2C_POLLED static int imxrt_lpi2c_isr(int irq, void *context, FAR void *arg) @@ -1411,13 +1433,13 @@ static int imxrt_lpi2c_isr(int irq, void *context, FAR void *arg) } #endif -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_clock_enable * * Description: * Ungate LPI2C clock * - ************************************************************************************/ + ****************************************************************************/ void imxrt_lpi2c_clock_enable (uint32_t base) { @@ -1439,13 +1461,13 @@ void imxrt_lpi2c_clock_enable (uint32_t base) } } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_clock_disable * * Description: * Gate LPI2C clock * - ************************************************************************************/ + ****************************************************************************/ void imxrt_lpi2c_clock_disable (uint32_t base) { @@ -1467,13 +1489,13 @@ void imxrt_lpi2c_clock_disable (uint32_t base) } } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_init * * Description: * Setup the I2C hardware, ready for operation with defaults * - ************************************************************************************/ + ****************************************************************************/ static int imxrt_lpi2c_init(FAR struct imxrt_lpi2c_priv_s *priv) { @@ -1500,7 +1522,8 @@ static int imxrt_lpi2c_init(FAR struct imxrt_lpi2c_priv_s *priv) /* Disable host request */ imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MCFGR0_OFFSET, - LPI2C_MCFG0_HREN | LPI2C_MCFG0_HRSEL, LPI2C_MCFG0_HRPOL); + LPI2C_MCFG0_HREN | LPI2C_MCFG0_HRSEL, + LPI2C_MCFG0_HRPOL); /* Pin config and ignore NACK disable */ @@ -1524,30 +1547,31 @@ static int imxrt_lpi2c_init(FAR struct imxrt_lpi2c_priv_s *priv) LPI2C_MCFG2_FILTSCL_CYCLES(priv->config->filtscl) | LPI2C_MCFG2_FILTSDA_CYCLES(priv->config->filtsda)); - /* Set pin low cycles to 0 (disable) */ + /* Set pin low cycles to 0 (disable) */ - imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MCFGR3_OFFSET, LPI2C_MCFG3_PINLOW_CYCLES(0)); + imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MCFGR3_OFFSET, + LPI2C_MCFG3_PINLOW_CYCLES(0)); - /* Attach ISRs */ + /* Attach ISRs */ #ifndef CONFIG_I2C_POLLED - irq_attach(priv->config->irq, imxrt_lpi2c_isr, priv); - up_enable_irq(priv->config->irq); + irq_attach(priv->config->irq, imxrt_lpi2c_isr, priv); + up_enable_irq(priv->config->irq); #endif - /* Enable I2C */ + /* Enable I2C */ - imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MCR_OFFSET, 0, LPI2C_MCR_MEN); - return OK; + imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MCR_OFFSET, 0, LPI2C_MCR_MEN); + return OK; } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_deinit * * Description: * Shutdown the I2C hardware * - ************************************************************************************/ + ****************************************************************************/ static int imxrt_lpi2c_deinit(FAR struct imxrt_lpi2c_priv_s *priv) { @@ -1574,20 +1598,20 @@ static int imxrt_lpi2c_deinit(FAR struct imxrt_lpi2c_priv_s *priv) return OK; } -/************************************************************************************ +/**************************************************************************** * Device Driver Operations - ************************************************************************************/ + ****************************************************************************/ -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_transfer * * Description: * Generic I2C transfer function * - ************************************************************************************/ + ****************************************************************************/ -static int imxrt_lpi2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs, - int count) +static int imxrt_lpi2c_transfer(FAR struct i2c_master_s *dev, + FAR struct i2c_msg_s *msgs, int count) { FAR struct imxrt_lpi2c_priv_s *priv = (struct imxrt_lpi2c_priv_s *)dev; uint32_t status = 0; @@ -1635,33 +1659,25 @@ static int imxrt_lpi2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg if (imxrt_lpi2c_sem_waitdone(priv) < 0) { - status = imxrt_lpi2c_getstatus(priv); ret = -ETIMEDOUT; - i2cerr("ERROR: Timed out: MCR: status: 0x%x\n", status); + i2cerr("ERROR: Timed out: MCR: status: 0x%x\n", priv->status); } /* Check for error status conditions */ - if ((status & LPI2C_MSR_ERROR_MASK) != 0) + else if ((priv->status & LPI2C_MSR_ERROR_MASK) != 0) { /* I2C_SR1_ERRORMASK is the 'OR' of the following individual bits: */ - if (status & LPI2C_MSR_BBF) - { - /* Bus Error */ - - i2cerr("Bus error\n"); - ret = -EIO; - } - else if (status & LPI2C_MSR_ALF) + if (priv->status & LPI2C_MSR_ALF) { /* Arbitration Lost (master mode) */ i2cerr("Arbitration lost\n"); ret = -EAGAIN; } - else if (status & LPI2C_MSR_NDF) + else if (priv->status & LPI2C_MSR_NDF) { /* Acknowledge Failure */ @@ -1670,8 +1686,10 @@ static int imxrt_lpi2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg } else { - i2cerr("Unspecified error\n"); - ret = -EINTR; + /* FIFO Error */ + + i2cerr("Transfer without start condition\n"); + ret = -EINVAL; } } @@ -1679,7 +1697,9 @@ static int imxrt_lpi2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg imxrt_lpi2c_tracedump(priv); - /* Ensure that any ISR happening after we finish can't overwrite any user data */ + /* Ensure that any ISR happening after we finish can't overwrite any user + * data. + */ priv->dcnt = 0; priv->ptr = NULL; @@ -1688,7 +1708,7 @@ static int imxrt_lpi2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg return ret; } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_lpi2c_reset * * Description: @@ -1700,7 +1720,7 @@ static int imxrt_lpi2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg * Returned Value: * Zero (OK) on success; a negated errno value on failure. * - ************************************************************************************/ + ****************************************************************************/ #ifdef CONFIG_I2C_RESET static int imxrt_lpi2c_reset(FAR struct i2c_master_s *dev) @@ -1823,17 +1843,17 @@ out: } #endif /* CONFIG_I2C_RESET */ -/************************************************************************************ +/**************************************************************************** * Public Functions - ************************************************************************************/ + ****************************************************************************/ -/************************************************************************************ +/**************************************************************************** * Name: imxrt_i2cbus_initialize * * Description: * Initialize one I2C bus * - ************************************************************************************/ + ****************************************************************************/ FAR struct i2c_master_s *imxrt_i2cbus_initialize(int port) { @@ -1885,13 +1905,13 @@ FAR struct i2c_master_s *imxrt_i2cbus_initialize(int port) return (struct i2c_master_s *)priv; } -/************************************************************************************ +/**************************************************************************** * Name: imxrt_i2cbus_uninitialize * * Description: * Uninitialize an I2C bus * - ************************************************************************************/ + ****************************************************************************/ int imxrt_i2cbus_uninitialize(FAR struct i2c_master_s *dev) {