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.

This commit is contained in:
Nicholas Chin 2019-07-23 09:06:29 -06:00 committed by Gregory Nutt
parent 96f019a822
commit f5ff35ad9c
2 changed files with 162 additions and 143 deletions

View File

@ -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)

View File

@ -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 <ivanucherdjiev@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
@ -33,9 +33,9 @@
*
****************************************************************************/
/************************************************************************************
/****************************************************************************
* Included Files
************************************************************************************/
****************************************************************************/
#include <nuttx/config.h>
@ -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)
{