mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 08:36:24 +08:00
I2C: Remove the setfrequency method from the interface
This commit is contained in:
@@ -258,6 +258,7 @@ struct efm32_i2c_priv_s
|
||||
uint8_t *ptr; /* Current message buffer */
|
||||
int dcnt; /* Current message length */
|
||||
uint32_t flags; /* Current message flags */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
|
||||
/* I2C trace support */
|
||||
|
||||
@@ -275,11 +276,8 @@ struct efm32_i2c_priv_s
|
||||
|
||||
struct efm32_i2c_inst_s
|
||||
{
|
||||
const struct i2c_ops_s *ops; /* Standard I2C operations */
|
||||
struct efm32_i2c_priv_s *priv; /* Common driver private data structure
|
||||
*/
|
||||
|
||||
uint32_t frequency; /* Frequency used in this instantiation */
|
||||
const struct i2c_ops_s *ops; /* Standard I2C operations */
|
||||
struct efm32_i2c_priv_s *priv; /* Common driver private data structure */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -325,10 +323,8 @@ static int efm32_i2c1_isr(int irq, void *context);
|
||||
#endif /* !CONFIG_I2C_POLLED */
|
||||
|
||||
static void efm32_i2c_reset(FAR struct efm32_i2c_priv_s *priv);
|
||||
static int efm32_i2c_init(FAR struct efm32_i2c_priv_s *priv, int frequency);
|
||||
static int efm32_i2c_init(FAR struct efm32_i2c_priv_s *priv);
|
||||
static int efm32_i2c_deinit(FAR struct efm32_i2c_priv_s *priv);
|
||||
static uint32_t efm32_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int efm32_i2c_process(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
static int efm32_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
@@ -404,8 +400,7 @@ static struct efm32_i2c_priv_s efm32_i2c1_priv =
|
||||
|
||||
static const struct i2c_ops_s efm32_i2c_ops =
|
||||
{
|
||||
.setfrequency = efm32_i2c_setfrequency,
|
||||
.transfer = efm32_i2c_transfer
|
||||
.transfer = efm32_i2c_transfer
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -830,21 +825,25 @@ static void efm32_i2c_setclock(FAR struct efm32_i2c_priv_s *priv,
|
||||
{
|
||||
uint32_t div;
|
||||
|
||||
/* Set the CLHR (clock low to high ratio). */
|
||||
/* Has the I2C bus frequency changed? */
|
||||
|
||||
efm32_i2c_modifyreg(priv, EFM32_I2C_CTRL_OFFSET, _I2C_CTRL_CLHR_MASK,
|
||||
if (priv->frequency != frequency)
|
||||
{
|
||||
/* Set the CLHR (clock low to high ratio). */
|
||||
|
||||
efm32_i2c_modifyreg(priv, EFM32_I2C_CTRL_OFFSET, _I2C_CTRL_CLHR_MASK,
|
||||
#if defined(CONFIG_EFM32_I2C_CLHR_FAST)
|
||||
_I2C_CTRL_CLHR_FAST /* Ratio is 11:3 */
|
||||
_I2C_CTRL_CLHR_FAST /* Ratio is 11:3 */
|
||||
#elif defined(CONFIG_EFM32_I2C_CLHR_ASYMMETRIC)
|
||||
_I2C_CTRL_CLHR_ASYMMETRIC /* Ratio is 6:3 */
|
||||
_I2C_CTRL_CLHR_ASYMMETRIC /* Ratio is 6:3 */
|
||||
#else /* CLHR STANDARD */
|
||||
_I2C_CTRL_CLHR_STANDARD /* Ratio is 4:4 */
|
||||
_I2C_CTRL_CLHR_STANDARD /* Ratio is 4:4 */
|
||||
#endif
|
||||
<< _I2C_CTRL_CLHR_SHIFT);
|
||||
<< _I2C_CTRL_CLHR_SHIFT);
|
||||
|
||||
/* Frequency is given by fSCL = fHFPERCLK/((Nlow + Nhigh)(DIV + 1) + 4), thus
|
||||
* DIV = ((fHFPERCLK - 4fSCL)/((Nlow + Nhigh)fSCL)) - 1
|
||||
*/
|
||||
/* Frequency is given by fSCL = fHFPERCLK/((Nlow + Nhigh)(DIV + 1) + 4),
|
||||
* thus DIV = ((fHFPERCLK - 4fSCL)/((Nlow + Nhigh)fSCL)) - 1
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_EFM32_I2C_CLHR_FAST)
|
||||
# define n (11 + 6) /* Ratio is 11:3 */
|
||||
@@ -854,19 +853,26 @@ static void efm32_i2c_setclock(FAR struct efm32_i2c_priv_s *priv,
|
||||
# define n ( 4 + 4) /* Ratio is 4:4 */
|
||||
#endif
|
||||
|
||||
div = (BOARD_HFPERCLK_FREQUENCY - (4 * frequency)) / (n * frequency);
|
||||
div = (BOARD_HFPERCLK_FREQUENCY - (4 * frequency)) / (n * frequency);
|
||||
|
||||
/* Clock divisor must be at least 1 in slave mode according to reference */
|
||||
/* manual (in which case there is normally no need to set bus frequency). */
|
||||
/* Clock divisor must be at least 1 in slave mode according to
|
||||
* reference manual (in which case there is normally no need to set
|
||||
* bus frequency).
|
||||
*/
|
||||
|
||||
if ((efm32_i2c_getreg(priv, EFM32_I2C_CTRL_OFFSET) & I2C_CTRL_SLAVE) && !div)
|
||||
{
|
||||
div = 1;
|
||||
if ((efm32_i2c_getreg(priv, EFM32_I2C_CTRL_OFFSET) & I2C_CTRL_SLAVE) && !div)
|
||||
{
|
||||
div = 1;
|
||||
}
|
||||
|
||||
DEBUGASSERT(div <= (_I2C_CLKDIV_DIV_MASK >> _I2C_CLKDIV_DIV_SHIFT));
|
||||
|
||||
efm32_i2c_putreg(priv, EFM32_I2C_CLKDIV_OFFSET, div);
|
||||
|
||||
/* Save the new I2C frequency */
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
|
||||
DEBUGASSERT(div <= (_I2C_CLKDIV_DIV_MASK >> _I2C_CLKDIV_DIV_SHIFT));
|
||||
|
||||
efm32_i2c_putreg(priv, EFM32_I2C_CLKDIV_OFFSET, div);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -1347,7 +1353,7 @@ static void efm32_i2c_reset(FAR struct efm32_i2c_priv_s *priv)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int efm32_i2c_init(FAR struct efm32_i2c_priv_s *priv, int frequency)
|
||||
static int efm32_i2c_init(FAR struct efm32_i2c_priv_s *priv)
|
||||
{
|
||||
int regval;
|
||||
|
||||
@@ -1445,25 +1451,6 @@ static int efm32_i2c_deinit(FAR struct efm32_i2c_priv_s *priv)
|
||||
* Device Driver Operations
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: efm32_i2c_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the I2C frequency
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t efm32_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency)
|
||||
{
|
||||
efm32_i2c_sem_wait(dev);
|
||||
|
||||
((struct efm32_i2c_inst_s *)dev)->frequency = frequency;
|
||||
|
||||
efm32_i2c_sem_post(dev);
|
||||
return frequency;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: efm32_i2c_process
|
||||
*
|
||||
@@ -1504,9 +1491,13 @@ static int efm32_i2c_process(FAR struct i2c_master_s *dev,
|
||||
|
||||
efm32_i2c_tracereset(priv);
|
||||
|
||||
/* Set I2C clock frequency (on change it toggles I2C_CR1_PE !) */
|
||||
/* Set I2C clock frequency (on change it toggles I2C_CR1_PE !).
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
efm32_i2c_setclock(priv, inst->frequency);
|
||||
efm32_i2c_setclock(priv, msgs->frequency);
|
||||
|
||||
/* Prepare for a transfer */
|
||||
|
||||
@@ -1677,9 +1668,8 @@ FAR struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Initialize instance */
|
||||
|
||||
inst->ops = &efm32_i2c_ops;
|
||||
inst->ops = &efm32_i2c_ops;
|
||||
inst->priv = priv;
|
||||
inst->frequency = 100000;
|
||||
|
||||
/* Initialize private data for the first time, increment reference count,
|
||||
* power-up hardware and configure GPIOs.
|
||||
@@ -1690,7 +1680,7 @@ FAR struct i2c_master_s *up_i2cinitialize(int port)
|
||||
if ((volatile int)priv->refs++ == 0)
|
||||
{
|
||||
efm32_i2c_sem_init((struct i2c_master_s *)inst);
|
||||
efm32_i2c_init(priv, inst->frequency);
|
||||
efm32_i2c_init(priv);
|
||||
}
|
||||
|
||||
irqrestore(irqs);
|
||||
@@ -1847,7 +1837,7 @@ int up_i2creset(FAR struct i2c_master_s *dev)
|
||||
|
||||
/* Re-init the port */
|
||||
|
||||
efm32_i2c_init(priv, ((struct efm32_i2c_inst_s *)dev)->frequency);
|
||||
efm32_i2c_init(priv);
|
||||
ret = OK;
|
||||
|
||||
out:
|
||||
|
||||
@@ -105,38 +105,39 @@
|
||||
|
||||
struct lpc11_i2cdev_s
|
||||
{
|
||||
struct i2c_master_s dev; /* Generic I2C device */
|
||||
unsigned int base; /* Base address of registers */
|
||||
uint16_t irqid; /* IRQ for this device */
|
||||
struct i2c_master_s dev; /* Generic I2C device */
|
||||
unsigned int base; /* Base address of registers */
|
||||
uint16_t irqid; /* IRQ for this device */
|
||||
|
||||
sem_t mutex; /* Only one thread can access at a time */
|
||||
sem_t wait; /* Place to wait for state machine completion */
|
||||
volatile uint8_t state; /* State of state machine */
|
||||
WDOG_ID timeout; /* watchdog to timeout when bus hung */
|
||||
sem_t mutex; /* Only one thread can access at a time */
|
||||
sem_t wait; /* Place to wait for state machine completion */
|
||||
volatile uint8_t state; /* State of state machine */
|
||||
WDOG_ID timeout; /* Watchdog to timeout when bus hung */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
|
||||
struct i2c_msg_s *msgs; /* Remaining transfers - first one is in progress */
|
||||
unsigned int nmsg; /* Number of transfer remaining */
|
||||
struct i2c_msg_s *msgs; /* Remaining transfers - first one is in progress */
|
||||
unsigned int nmsg; /* Number of transfer remaining */
|
||||
|
||||
uint16_t wrcnt; /* Number of bytes sent to tx fifo */
|
||||
uint16_t rdcnt; /* Number of bytes read from rx fifo */
|
||||
uint16_t wrcnt; /* Number of bytes sent to tx fifo */
|
||||
uint16_t rdcnt; /* Number of bytes read from rx fifo */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int lpc11_i2c_start(struct lpc11_i2cdev_s *priv);
|
||||
static void lpc11_i2c_stop(struct lpc11_i2cdev_s *priv);
|
||||
static int lpc11_i2c_interrupt(int irq, FAR void *context);
|
||||
static void lpc11_i2c_timeout(int argc, uint32_t arg, ...);
|
||||
static int lpc11_i2c_start(struct lpc11_i2cdev_s *priv);
|
||||
static void lpc11_i2c_stop(struct lpc11_i2cdev_s *priv);
|
||||
static int lpc11_i2c_interrupt(int irq, FAR void *context);
|
||||
static void lpc11_i2c_timeout(int argc, uint32_t arg, ...);
|
||||
static void lpc11_i2c_setfrequency(struct lpc11_i2cdev_s *priv,
|
||||
uint32_t frequency);
|
||||
|
||||
/* I2C device operations */
|
||||
|
||||
static uint32_t lpc11_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int lpc11_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
static void lpc11_stopnext(struct lpc11_i2cdev_s *priv);
|
||||
static int lpc11_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
static void lpc11_stopnext(struct lpc11_i2cdev_s *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
@@ -154,45 +155,43 @@ static struct lpc11_i2cdev_s g_i2c2dev;
|
||||
|
||||
struct i2c_ops_s lpc11_i2c_ops =
|
||||
{
|
||||
.setfrequency = lpc11_i2c_setfrequency,
|
||||
.transfer = lpc11_i2c_transfer
|
||||
.transfer = lpc11_i2c_transfer
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc11_i2c_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the frequence for the next transfer
|
||||
* Set the frequency for the next transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t lpc11_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
static void lpc11_i2c_setfrequency(struct lpc11_i2cdev_s *priv,
|
||||
uint32_t frequency)
|
||||
{
|
||||
struct lpc11_i2cdev_s *priv = (struct lpc11_i2cdev_s *) dev;
|
||||
|
||||
if (frequency > 100000)
|
||||
if (frequency != priv->frequency)
|
||||
{
|
||||
/* Asymetric per 400Khz I2C spec */
|
||||
if (frequency > 100000)
|
||||
{
|
||||
/* Asymetric per 400Khz I2C spec */
|
||||
|
||||
putreg32(LPC11_MCLK / (83 + 47) * 47 / frequency,
|
||||
priv->base + LPC11_I2C_SCLH_OFFSET);
|
||||
putreg32(LPC11_MCLK / (83 + 47) * 83 / frequency,
|
||||
priv->base + LPC11_I2C_SCLL_OFFSET);
|
||||
putreg32(LPC11_MCLK / (83 + 47) * 47 / frequency,
|
||||
priv->base + LPC11_I2C_SCLH_OFFSET);
|
||||
putreg32(LPC11_MCLK / (83 + 47) * 83 / frequency,
|
||||
priv->base + LPC11_I2C_SCLL_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 50/50 mark space ratio */
|
||||
|
||||
putreg32(LPC11_MCLK / 100 * 50 / frequency,
|
||||
priv->base + LPC11_I2C_SCLH_OFFSET);
|
||||
putreg32(LPC11_MCLK / 100 * 50 / frequency,
|
||||
priv->base + LPC11_I2C_SCLL_OFFSET);
|
||||
}
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 50/50 mark space ratio */
|
||||
|
||||
putreg32(LPC11_MCLK / 100 * 50 / frequency,
|
||||
priv->base + LPC11_I2C_SCLH_OFFSET);
|
||||
putreg32(LPC11_MCLK / 100 * 50 / frequency,
|
||||
priv->base + LPC11_I2C_SCLL_OFFSET);
|
||||
}
|
||||
|
||||
/* FIXME: This function should return the actual selected frequency */
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -207,8 +206,6 @@ static int lpc11_i2c_start(struct lpc11_i2cdev_s *priv)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
sem_wait(&priv->mutex);
|
||||
|
||||
putreg32(I2C_CONCLR_STAC | I2C_CONCLR_SIC,
|
||||
priv->base + LPC11_I2C_CONCLR_OFFSET);
|
||||
putreg32(I2C_CONSET_STA, priv->base + LPC11_I2C_CONSET_OFFSET);
|
||||
@@ -218,11 +215,7 @@ static int lpc11_i2c_start(struct lpc11_i2cdev_s *priv)
|
||||
|
||||
wd_cancel(priv->timeout);
|
||||
|
||||
ret = priv->nmsg;
|
||||
|
||||
sem_post(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
return priv->nmsg;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -276,15 +269,32 @@ static int lpc11_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
struct lpc11_i2cdev_s *priv = (struct lpc11_i2cdev_s *)dev;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
DEBUGASSERT(dev != NULL && msgs != NULL && count > 0);
|
||||
|
||||
/* Get exclusive access to the I2C bus */
|
||||
|
||||
sem_wait(&priv->mutex);
|
||||
|
||||
/* Set up for the transfer */
|
||||
|
||||
priv->wrcnt = 0;
|
||||
priv->rdcnt = 0;
|
||||
priv->msgs = msgs;
|
||||
priv->nmsg = count;
|
||||
|
||||
/* Configure the I2C frequency.
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
lpc11_i2c_setfrequency(priv, msgs->frequency);
|
||||
|
||||
/* Perform the transfer */
|
||||
|
||||
ret = lpc11_i2c_start(priv);
|
||||
|
||||
sem_post(&priv->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -479,8 +489,7 @@ struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Set default frequency */
|
||||
|
||||
lpc11_i2c_setfrequency((struct i2c_master_s *)priv,
|
||||
CONFIG_LPC11_I2C0_FREQUENCY);
|
||||
lpc11_i2c_setfrequency(priv, CONFIG_LPC11_I2C0_FREQUENCY);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -509,8 +518,7 @@ struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Set default frequency */
|
||||
|
||||
lpc11_i2c_setfrequency((struct i2c_master_s *)priv,
|
||||
CONFIG_LPC11_I2C1_FREQUENCY);
|
||||
lpc11_i2c_setfrequency(priv, CONFIG_LPC11_I2C1_FREQUENCY);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -539,8 +547,7 @@ struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Set default frequency */
|
||||
|
||||
lpc11_i2c_setfrequency((struct i2c_master_s *)priv,
|
||||
CONFIG_LPC11_I2C2_FREQUENCY);
|
||||
lpc11_i2c_setfrequency(priv, CONFIG_LPC11_I2C2_FREQUENCY);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
@@ -112,7 +112,8 @@ struct lpc17_i2cdev_s
|
||||
sem_t mutex; /* Only one thread can access at a time */
|
||||
sem_t wait; /* Place to wait for state machine completion */
|
||||
volatile uint8_t state; /* State of state machine */
|
||||
WDOG_ID timeout; /* watchdog to timeout when bus hung */
|
||||
WDOG_ID timeout; /* Watchdog to timeout when bus hung */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
|
||||
struct i2c_msg_s *msgs; /* remaining transfers - first one is in progress */
|
||||
unsigned int nmsg; /* number of transfer remaining */
|
||||
@@ -125,18 +126,18 @@ struct lpc17_i2cdev_s
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int lpc17_i2c_start(struct lpc17_i2cdev_s *priv);
|
||||
static void lpc17_i2c_stop(struct lpc17_i2cdev_s *priv);
|
||||
static int lpc17_i2c_interrupt(int irq, FAR void *context);
|
||||
static void lpc17_i2c_timeout(int argc, uint32_t arg, ...);
|
||||
static int lpc17_i2c_start(struct lpc17_i2cdev_s *priv);
|
||||
static void lpc17_i2c_stop(struct lpc17_i2cdev_s *priv);
|
||||
static int lpc17_i2c_interrupt(int irq, FAR void *context);
|
||||
static void lpc17_i2c_timeout(int argc, uint32_t arg, ...);
|
||||
static void lpc17_i2c_setfrequency(struct lpc17_i2cdev_s *priv,
|
||||
uint32_t frequency);
|
||||
|
||||
/* I2C device operations */
|
||||
|
||||
static uint32_t lpc17_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int lpc17_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
static void lpc17_stopnext(struct lpc17_i2cdev_s *priv);
|
||||
static int lpc17_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
static void lpc17_stopnext(struct lpc17_i2cdev_s *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
@@ -154,45 +155,43 @@ static struct lpc17_i2cdev_s g_i2c2dev;
|
||||
|
||||
struct i2c_ops_s lpc17_i2c_ops =
|
||||
{
|
||||
.setfrequency = lpc17_i2c_setfrequency,
|
||||
.transfer = lpc17_i2c_transfer
|
||||
.transfer = lpc17_i2c_transfer
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc17_i2c_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the frequence for the next transfer
|
||||
* Set the frequency for the next transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t lpc17_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency)
|
||||
static void lpc17_i2c_setfrequency(struct lpc17_i2cdev_s *priv,
|
||||
uint32_t frequency);
|
||||
{
|
||||
struct lpc17_i2cdev_s *priv = (struct lpc17_i2cdev_s *) dev;
|
||||
|
||||
if (frequency > 100000)
|
||||
if (frequency != priv->frequency)
|
||||
{
|
||||
/* Asymetric per 400Khz I2C spec */
|
||||
if (frequency > 100000)
|
||||
{
|
||||
/* Asymetric per 400Khz I2C spec */
|
||||
|
||||
putreg32(LPC17_CCLK / (83 + 47) * 47 / frequency,
|
||||
priv->base + LPC17_I2C_SCLH_OFFSET);
|
||||
putreg32(LPC17_CCLK / (83 + 47) * 83 / frequency,
|
||||
priv->base + LPC17_I2C_SCLL_OFFSET);
|
||||
putreg32(LPC17_CCLK / (83 + 47) * 47 / frequency,
|
||||
priv->base + LPC17_I2C_SCLH_OFFSET);
|
||||
putreg32(LPC17_CCLK / (83 + 47) * 83 / frequency,
|
||||
priv->base + LPC17_I2C_SCLL_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 50/50 mark space ratio */
|
||||
|
||||
putreg32(LPC17_CCLK / 100 * 50 / frequency,
|
||||
priv->base + LPC17_I2C_SCLH_OFFSET);
|
||||
putreg32(LPC17_CCLK / 100 * 50 / frequency,
|
||||
priv->base + LPC17_I2C_SCLL_OFFSET);
|
||||
}
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 50/50 mark space ratio */
|
||||
|
||||
putreg32(LPC17_CCLK / 100 * 50 / frequency,
|
||||
priv->base + LPC17_I2C_SCLH_OFFSET);
|
||||
putreg32(LPC17_CCLK / 100 * 50 / frequency,
|
||||
priv->base + LPC17_I2C_SCLL_OFFSET);
|
||||
}
|
||||
|
||||
/* FIXME: This function should return the actual selected frequency */
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -207,8 +206,6 @@ static int lpc17_i2c_start(struct lpc17_i2cdev_s *priv)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
sem_wait(&priv->mutex);
|
||||
|
||||
putreg32(I2C_CONCLR_STAC | I2C_CONCLR_SIC,
|
||||
priv->base + LPC17_I2C_CONCLR_OFFSET);
|
||||
putreg32(I2C_CONSET_STA, priv->base + LPC17_I2C_CONSET_OFFSET);
|
||||
@@ -218,11 +215,7 @@ static int lpc17_i2c_start(struct lpc17_i2cdev_s *priv)
|
||||
|
||||
wd_cancel(priv->timeout);
|
||||
|
||||
ret = priv->nmsg;
|
||||
|
||||
sem_post(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
return priv->nmsg;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -276,15 +269,32 @@ static int lpc17_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
struct lpc17_i2cdev_s *priv = (struct lpc17_i2cdev_s *)dev;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
DEBUGASSERT(dev != NULL && msgs != NULL && count > 0);
|
||||
|
||||
/* Get exclusive access to the I2C bus */
|
||||
|
||||
sem_wait(&priv->mutex);
|
||||
|
||||
/* Set up for the transfer */
|
||||
|
||||
priv->wrcnt = 0;
|
||||
priv->rdcnt = 0;
|
||||
priv->msgs = msgs;
|
||||
priv->nmsg = count;
|
||||
|
||||
/* Configure the I2C frequency.
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
lpc17_i2c_setfrequency(priv, msgs->frequency);
|
||||
|
||||
/* Perform the transfer */
|
||||
|
||||
ret = lpc17_i2c_start(priv);
|
||||
|
||||
sem_post(&priv->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -484,8 +494,7 @@ struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Set default frequency */
|
||||
|
||||
lpc17_i2c_setfrequency((struct i2c_master_s *)priv,
|
||||
CONFIG_LPC17_I2C0_FREQUENCY);
|
||||
lpc17_i2c_setfrequency(priv, CONFIG_LPC17_I2C0_FREQUENCY);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -514,8 +523,7 @@ struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Set default frequency */
|
||||
|
||||
lpc17_i2c_setfrequency((struct i2c_master_s *)priv,
|
||||
CONFIG_LPC17_I2C1_FREQUENCY);
|
||||
lpc17_i2c_setfrequency(priv, CONFIG_LPC17_I2C1_FREQUENCY);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -544,8 +552,7 @@ struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Set default frequency */
|
||||
|
||||
lpc17_i2c_setfrequency((struct i2c_master_s *)priv,
|
||||
CONFIG_LPC17_I2C2_FREQUENCY);
|
||||
lpc17_i2c_setfrequency(priv, CONFIG_LPC17_I2C2_FREQUENCY);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
@@ -117,7 +117,8 @@ struct lpc2378_i2cdev_s
|
||||
sem_t mutex; /* Only one thread can access at a time */
|
||||
sem_t wait; /* Place to wait for state machine completion */
|
||||
volatile uint8_t state; /* State of state machine */
|
||||
WDOG_ID timeout; /* watchdog to timeout when bus hung */
|
||||
WDOG_ID timeout; /* Watchdog to timeout when bus hung */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
|
||||
struct i2c_msg_s *msgs; /* remaining transfers - first one is in progress */
|
||||
unsigned int nmsg; /* number of transfer remaining */
|
||||
@@ -130,18 +131,18 @@ struct lpc2378_i2cdev_s
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int lpc2378_i2c_start(struct lpc2378_i2cdev_s *priv);
|
||||
static void lpc2378_i2c_stop(struct lpc2378_i2cdev_s *priv);
|
||||
static int lpc2378_i2c_interrupt(int irq, FAR void *context);
|
||||
static void lpc2378_i2c_timeout(int argc, uint32_t arg, ...);
|
||||
static int lpc2378_i2c_start(struct lpc2378_i2cdev_s *priv);
|
||||
static void lpc2378_i2c_stop(struct lpc2378_i2cdev_s *priv);
|
||||
static int lpc2378_i2c_interrupt(int irq, FAR void *context);
|
||||
static void lpc2378_i2c_timeout(int argc, uint32_t arg, ...);
|
||||
static void lpc2378_i2c_setfrequency(struct lpc2378_i2cdev_s *priv,
|
||||
uint32_t frequency);
|
||||
|
||||
/* I2C device operations */
|
||||
|
||||
static uint32_t lpc2378_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int lpc2378_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
static void lpc2378_stopnext(struct lpc2378_i2cdev_s *priv);
|
||||
static int lpc2378_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
static void lpc2378_stopnext(struct lpc2378_i2cdev_s *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
@@ -159,45 +160,43 @@ static struct lpc2378_i2cdev_s g_i2c2dev;
|
||||
|
||||
struct i2c_ops_s lpc2378_i2c_ops =
|
||||
{
|
||||
.setfrequency = lpc2378_i2c_setfrequency,
|
||||
.transfer = lpc2378_i2c_transfer
|
||||
.transfer = lpc2378_i2c_transfer
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc2378_i2c_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the frequence for the next transfer
|
||||
* Set the frequency for the next transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t lpc2378_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency)
|
||||
static void lpc2378_i2c_setfrequency(struct lpc2378_i2cdev_s *priv,
|
||||
uint32_t frequency)
|
||||
{
|
||||
struct lpc2378_i2cdev_s *priv = (struct lpc2378_i2cdev_s *) dev;
|
||||
|
||||
if (frequency > 100000)
|
||||
if (frequency != priv->frequency)
|
||||
{
|
||||
/* Asymetric per 400Khz I2C spec */
|
||||
if (frequency > 100000)
|
||||
{
|
||||
/* Asymetric per 400Khz I2C spec */
|
||||
|
||||
putreg32(LPC23XX_CCLK / (83 + 47) * 47 / frequency,
|
||||
priv->base + I2C_SCLH_OFFSET);
|
||||
putreg32(LPC23XX_CCLK / (83 + 47) * 83 / frequency,
|
||||
priv->base + I2C_SCLL_OFFSET);
|
||||
putreg32(LPC23XX_CCLK / (83 + 47) * 47 / frequency,
|
||||
priv->base + I2C_SCLH_OFFSET);
|
||||
putreg32(LPC23XX_CCLK / (83 + 47) * 83 / frequency,
|
||||
priv->base + I2C_SCLL_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 50/50 mark space ratio */
|
||||
|
||||
putreg32(LPC23XX_CCLK / 100 * 50 / frequency,
|
||||
priv->base + I2C_SCLH_OFFSET);
|
||||
putreg32(LPC23XX_CCLK / 100 * 50 / frequency,
|
||||
priv->base + I2C_SCLL_OFFSET);
|
||||
}
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 50/50 mark space ratio */
|
||||
|
||||
putreg32(LPC23XX_CCLK / 100 * 50 / frequency,
|
||||
priv->base + I2C_SCLH_OFFSET);
|
||||
putreg32(LPC23XX_CCLK / 100 * 50 / frequency,
|
||||
priv->base + I2C_SCLL_OFFSET);
|
||||
}
|
||||
|
||||
/* FIXME: This function should return the actual selected frequency */
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -212,8 +211,6 @@ static int lpc2378_i2c_start(struct lpc2378_i2cdev_s *priv)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
sem_wait(&priv->mutex);
|
||||
|
||||
putreg32(I2C_CONCLR_STAC | I2C_CONCLR_SIC,
|
||||
priv->base + I2C_CONCLR_OFFSET);
|
||||
putreg32(I2C_CONSET_STA, priv->base + I2C_CONSET_OFFSET);
|
||||
@@ -223,11 +220,7 @@ static int lpc2378_i2c_start(struct lpc2378_i2cdev_s *priv)
|
||||
|
||||
wd_cancel(priv->timeout);
|
||||
|
||||
ret = priv->nmsg;
|
||||
|
||||
sem_post(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
return priv->nmsg;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -281,15 +274,32 @@ static int lpc2378_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
struct lpc2378_i2cdev_s *priv = (struct lpc2378_i2cdev_s *)dev;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
DEBUGASSERT(dev != NULL && msgs != NULL && count > 0);
|
||||
|
||||
/* Get exclusive access to the I2C bus */
|
||||
|
||||
sem_wait(&priv->mutex);
|
||||
|
||||
/* Set up for the transfer */
|
||||
|
||||
priv->wrcnt = 0;
|
||||
priv->rdcnt = 0;
|
||||
priv->msgs = msgs;
|
||||
priv->nmsg = count;
|
||||
|
||||
/* Configure the I2C frequency.
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
lpc23_i2c_setfrequency(priv, msgs->frequency);
|
||||
|
||||
/* Perform the transfer */
|
||||
|
||||
ret = lpc2378_i2c_start(priv);
|
||||
|
||||
sem_post(&priv->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -491,8 +501,7 @@ struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Set default frequency */
|
||||
|
||||
lpc2378_i2c_setfrequency((struct i2c_master_s *)priv,
|
||||
CONFIG_LPC2378_I2C0_FREQUENCY);
|
||||
lpc2378_i2c_setfrequency(priv, CONFIG_LPC2378_I2C0_FREQUENCY);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -523,8 +532,7 @@ struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Set default frequency */
|
||||
|
||||
lpc2378_i2c_setfrequency((struct i2c_master_s *)priv,
|
||||
CONFIG_LPC2378_I2C1_FREQUENCY);
|
||||
lpc2378_i2c_setfrequency(priv, CONFIG_LPC2378_I2C1_FREQUENCY);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -555,8 +563,7 @@ struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Set default frequency */
|
||||
|
||||
lpc2378_i2c_setfrequency((struct i2c_master_s *)priv,
|
||||
CONFIG_LPC2378_I2C2_FREQUENCY);
|
||||
lpc2378_i2c_setfrequency(priv, CONFIG_LPC2378_I2C2_FREQUENCY);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
@@ -86,10 +86,10 @@ struct lpc31_i2cdev_s
|
||||
uint16_t irqid; /* IRQ for this device */
|
||||
|
||||
sem_t mutex; /* Only one thread can access at a time */
|
||||
|
||||
sem_t wait; /* Place to wait for state machine completion */
|
||||
volatile uint8_t state; /* State of state machine */
|
||||
WDOG_ID timeout; /* watchdog to timeout when bus hung */
|
||||
WDOG_ID timeout; /* Watchdog to timeout when bus hung */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
|
||||
struct i2c_msg_s *msgs; /* remaining transfers - first one is in progress */
|
||||
unsigned int nmsg; /* number of transfer remaining */
|
||||
@@ -108,31 +108,24 @@ struct lpc31_i2cdev_s
|
||||
static struct lpc31_i2cdev_s i2cdevices[2];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int i2c_interrupt(int irq, FAR void *context);
|
||||
static void i2c_progress(struct lpc31_i2cdev_s *priv);
|
||||
static void i2c_timeout(int argc, uint32_t arg, ...);
|
||||
static void i2c_reset(struct lpc31_i2cdev_s *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
static void i2c_setfrequency(struct lpc31_i2cdev_s *priv, uint32_t frequency);
|
||||
static int i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
|
||||
/****************************************************************************
|
||||
* I2C device operations
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
|
||||
struct i2c_ops_s lpc31_i2c_ops =
|
||||
{
|
||||
.setfrequency = i2c_setfrequency,
|
||||
.transfer = i2c_transfer
|
||||
.transfer = i2c_transfer
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -215,34 +208,37 @@ void up_i2cuninitalize(struct lpc31_i2cdev_s *priv)
|
||||
* Name: lpc31_i2c_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the frequence for the next transfer
|
||||
* Set the frequency for the next transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t i2c_setfrequency(FAR struct i2c_master_s *dev, uint32_t frequency)
|
||||
static void i2c_setfrequency(struct lpc31_i2cdev_s *priv, uint32_t frequency)
|
||||
{
|
||||
struct lpc31_i2cdev_s *priv = (struct lpc31_i2cdev_s *) dev;
|
||||
|
||||
uint32_t freq = lpc31_clkfreq(priv->clkid, DOMAINID_AHB0APB1);
|
||||
|
||||
if (freq > 100000)
|
||||
if (frequency != priv->frequency)
|
||||
{
|
||||
/* asymetric per 400Khz I2C spec */
|
||||
uint32_t freq = lpc31_clkfreq(priv->clkid, DOMAINID_AHB0APB1);
|
||||
|
||||
putreg32(((47 * freq) / (83 + 47)) / frequency, priv->base + LPC31_I2C_CLKHI_OFFSET);
|
||||
putreg32(((83 * freq) / (83 + 47)) / frequency, priv->base + LPC31_I2C_CLKLO_OFFSET);
|
||||
if (freq > 100000)
|
||||
{
|
||||
/* asymetric per 400Khz I2C spec */
|
||||
|
||||
putreg32(((47 * freq) / (83 + 47)) / frequency,
|
||||
priv->base + LPC31_I2C_CLKHI_OFFSET);
|
||||
putreg32(((83 * freq) / (83 + 47)) / frequency,
|
||||
priv->base + LPC31_I2C_CLKLO_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 50/50 mark space ratio */
|
||||
|
||||
putreg32(((50 * freq) / 100) / frequency,
|
||||
priv->base + LPC31_I2C_CLKLO_OFFSET);
|
||||
putreg32(((50 * freq) / 100) / frequency,
|
||||
priv->base + LPC31_I2C_CLKHI_OFFSET);
|
||||
}
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 50/50 mark space ratio */
|
||||
|
||||
putreg32(((50 * freq) / 100) / frequency, priv->base + LPC31_I2C_CLKLO_OFFSET);
|
||||
putreg32(((50 * freq) / 100) / frequency, priv->base + LPC31_I2C_CLKHI_OFFSET);
|
||||
}
|
||||
|
||||
/* FIXME: This function should return the actual selected frequency */
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -259,33 +255,45 @@ static int i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
/* Get exclusive access to the I2C bus */
|
||||
|
||||
sem_wait(&priv->mutex);
|
||||
flags = irqsave();
|
||||
|
||||
/* Set up for the transfer */
|
||||
|
||||
priv->state = I2C_STATE_START;
|
||||
priv->msgs = msgs;
|
||||
priv->nmsg = count;
|
||||
|
||||
i2c_progress(priv);
|
||||
|
||||
/* start a watchdog to timeout the transfer if
|
||||
* the bus is locked up...
|
||||
/* Configure the I2C frequency.
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
i2c_setfrequency(priv, msgs->frequency);
|
||||
|
||||
/* Start the transfer */
|
||||
|
||||
i2c_progress(priv);
|
||||
|
||||
/* Start a watchdog to timeout the transfer if the bus is locked up... */
|
||||
|
||||
wd_start(priv->timeout, I2C_TIMEOUT, i2c_timeout, 1, (uint32_t)priv);
|
||||
|
||||
/* Wait for the transfer to complete */
|
||||
|
||||
while (priv->state != I2C_STATE_DONE)
|
||||
{
|
||||
sem_wait(&priv->wait);
|
||||
}
|
||||
|
||||
wd_cancel(priv->timeout);
|
||||
|
||||
ret = count - priv->nmsg;
|
||||
|
||||
irqrestore(flags);
|
||||
sem_post(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ struct lpc43_i2cdev_s
|
||||
sem_t wait; /* Place to wait for state machine completion */
|
||||
volatile uint8_t state; /* State of state machine */
|
||||
WDOG_ID timeout; /* watchdog to timeout when bus hung */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
|
||||
struct i2c_msg_s *msgs; /* remaining transfers - first one is in progress */
|
||||
unsigned int nmsg; /* number of transfer remaining */
|
||||
@@ -126,61 +127,58 @@ static struct lpc43_i2cdev_s g_i2c1dev;
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int lpc43_i2c_start(struct lpc43_i2cdev_s *priv);
|
||||
static void lpc43_i2c_stop(struct lpc43_i2cdev_s *priv);
|
||||
static int lpc43_i2c_interrupt(int irq, FAR void *context);
|
||||
static void lpc43_i2c_timeout(int argc, uint32_t arg, ...);
|
||||
static int lpc43_i2c_start(struct lpc43_i2cdev_s *priv);
|
||||
static void lpc43_i2c_stop(struct lpc43_i2cdev_s *priv);
|
||||
static int lpc43_i2c_interrupt(int irq, FAR void *context);
|
||||
static void lpc43_i2c_timeout(int argc, uint32_t arg, ...);
|
||||
static void lpc43_i2c_setfrequency(struct lpc43_i2cdev_s *priv,
|
||||
uint32_t frequency);
|
||||
static int lpc43_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
|
||||
/****************************************************************************
|
||||
* I2C device operations
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t lpc43_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int lpc43_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
|
||||
struct i2c_ops_s lpc43_i2c_ops =
|
||||
{
|
||||
.setfrequency = lpc43_i2c_setfrequency,
|
||||
.transfer = lpc43_i2c_transfer
|
||||
.transfer = lpc43_i2c_transfer
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc43_i2c_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the frequence for the next transfer
|
||||
* Set the frequency for the next transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t lpc43_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency)
|
||||
static void lpc43_i2c_setfrequency(struct lpc43_i2cdev_s *priv,
|
||||
uint32_t frequency)
|
||||
{
|
||||
struct lpc43_i2cdev_s *priv = (struct lpc43_i2cdev_s *) dev;
|
||||
|
||||
if (frequency > 100000)
|
||||
if (frequency != priv->frequency)
|
||||
{
|
||||
/* asymetric per 400Khz I2C spec */
|
||||
if (frequency > 100000)
|
||||
{
|
||||
/* asymetric per 400Khz I2C spec */
|
||||
|
||||
putreg32(priv->baseFreq / (83 + 47) * 47 / frequency, priv->base +
|
||||
LPC43_I2C_SCLH_OFFSET);
|
||||
putreg32(priv->baseFreq / (83 + 47) * 83 / frequency, priv->base +
|
||||
LPC43_I2C_SCLL_OFFSET);
|
||||
putreg32(priv->baseFreq / (83 + 47) * 47 / frequency,
|
||||
priv->base + LPC43_I2C_SCLH_OFFSET);
|
||||
putreg32(priv->baseFreq / (83 + 47) * 83 / frequency,
|
||||
priv->base + LPC43_I2C_SCLL_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 50/50 mark space ratio */
|
||||
|
||||
putreg32(priv->baseFreq / 100 * 50 / frequency,
|
||||
priv->base + LPC43_I2C_SCLH_OFFSET);
|
||||
putreg32(priv->baseFreq / 100 * 50 / frequency,
|
||||
priv->base + LPC43_I2C_SCLL_OFFSET);
|
||||
}
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 50/50 mark space ratio */
|
||||
|
||||
putreg32(priv->baseFreq / 100 * 50 / frequency, priv->base +
|
||||
LPC43_I2C_SCLH_OFFSET);
|
||||
putreg32(priv->baseFreq / 100 * 50 / frequency, priv->base +
|
||||
LPC43_I2C_SCLL_OFFSET);
|
||||
}
|
||||
|
||||
/* FIXME: This function should return the actual selected frequency */
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -195,8 +193,6 @@ static int lpc43_i2c_start(struct lpc43_i2cdev_s *priv)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
sem_wait(&priv->mutex);
|
||||
|
||||
putreg32(I2C_CONCLR_STAC | I2C_CONCLR_SIC,
|
||||
priv->base + LPC43_I2C_CONCLR_OFFSET);
|
||||
putreg32(I2C_CONSET_STA, priv->base + LPC43_I2C_CONSET_OFFSET);
|
||||
@@ -205,12 +201,7 @@ static int lpc43_i2c_start(struct lpc43_i2cdev_s *priv)
|
||||
sem_wait(&priv->wait);
|
||||
|
||||
wd_cancel(priv->timeout);
|
||||
|
||||
ret = priv->nmsg;
|
||||
|
||||
sem_post(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
return priv->nmsg;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -266,17 +257,42 @@ static int lpc43_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
/* Get exclusive access to the I2C bus */
|
||||
|
||||
sem_wait(&priv->mutex);
|
||||
|
||||
/* Set up for the transfer */
|
||||
|
||||
priv->wrcnt = 0;
|
||||
priv->rdcnt = 0;
|
||||
priv->msgs = msgs;
|
||||
priv->nmsg = count;
|
||||
|
||||
/* Configure the I2C frequency.
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
lpc43_i2c_setfrequency(priv, msgs->frequency);
|
||||
|
||||
/* Perform the transfer */
|
||||
|
||||
ret = lpc43_i2c_start(priv);
|
||||
|
||||
sem_post(&priv->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void startStopNextMessage(struct lpc43_i2cdev_s *priv)
|
||||
/****************************************************************************
|
||||
* Name: lpc32_i2c_nextmsg
|
||||
*
|
||||
* Description:
|
||||
* Setup for the next message.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void lpc32_i2c_nextmsg(struct lpc43_i2cdev_s *priv)
|
||||
{
|
||||
priv->nmsg--;
|
||||
|
||||
@@ -362,7 +378,7 @@ static int lpc43_i2c_interrupt(int irq, FAR void *context)
|
||||
}
|
||||
else
|
||||
{
|
||||
startStopNextMessage(priv);
|
||||
lpc32_i2c_nextmsg(priv);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -392,7 +408,7 @@ static int lpc43_i2c_interrupt(int irq, FAR void *context)
|
||||
|
||||
case 0x58: /* Data byte has been received; NACK has been returned. */
|
||||
msg->buffer[priv->rdcnt] = getreg32(priv->base + LPC43_I2C_BUFR_OFFSET);
|
||||
startStopNextMessage(priv);
|
||||
lpc32_i2c_nextmsg(priv);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -459,8 +475,7 @@ struct i2c_master_s *up_i2cinitialize(int port)
|
||||
regval |= CCU_CLK_CFG_RUN;
|
||||
putreg32(regval, LPC43_CCU1_APB1_I2C0_CFG);
|
||||
|
||||
lpc43_i2c_setfrequency((struct i2c_master_s *)priv,
|
||||
I2C0_DEFAULT_FREQUENCY);
|
||||
lpc43_i2c_setfrequency(priv, I2C0_DEFAULT_FREQUENCY);
|
||||
|
||||
/* No pin configuration needed */
|
||||
}
|
||||
|
||||
@@ -119,8 +119,8 @@ struct twi_dev_s
|
||||
struct i2c_master_s dev; /* Generic I2C device */
|
||||
struct i2c_msg_s *msg; /* Message list */
|
||||
uintptr_t base; /* Base address of registers */
|
||||
uint32_t frequency; /* TWI input clock frequency */
|
||||
uint32_t deffreq; /* Selected TWI frequency */
|
||||
uint32_t clkin; /* TWI input clock frequency */
|
||||
uint32_t i2cfreq; /* Selected TWI frequency */
|
||||
uint16_t irq; /* IRQ number for this device */
|
||||
uint8_t msgc; /* Number of message in the message list */
|
||||
uint8_t twi; /* TWI peripheral number (for debug output) */
|
||||
@@ -187,15 +187,12 @@ static void twi_startmessage(struct twi_dev_s *priv, struct i2c_msg_s *msg);
|
||||
|
||||
/* I2C device operations */
|
||||
|
||||
static uint32_t twi_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int twi_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
|
||||
/* Initialization */
|
||||
|
||||
static uint32_t twi_hw_setfrequency(struct twi_dev_s *priv,
|
||||
uint32_t frequency);
|
||||
static void twi_setfrequency(struct twi_dev_s *priv, uint32_t frequency);
|
||||
static void twi_hw_initialize(struct twi_dev_s *priv, unsigned int pid,
|
||||
uint32_t frequency);
|
||||
|
||||
@@ -213,8 +210,7 @@ static struct twi_dev_s g_twi1;
|
||||
|
||||
struct i2c_ops_s g_twiops =
|
||||
{
|
||||
.setfrequency = twi_setfrequency,
|
||||
.transfer = twi_transfer
|
||||
.transfer = twi_transfer
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -689,32 +685,6 @@ static void twi_startmessage(struct twi_dev_s *priv, struct i2c_msg_s *msg)
|
||||
* I2C device operations
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: twi_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the frequency for the next transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t twi_setfrequency(FAR struct i2c_master_s *dev, uint32_t frequency)
|
||||
{
|
||||
struct twi_dev_s *priv = (struct twi_dev_s *)dev;
|
||||
uint32_t actual;
|
||||
|
||||
DEBUGASSERT(dev);
|
||||
|
||||
/* Get exclusive access to the device */
|
||||
|
||||
twi_takesem(&priv->exclsem);
|
||||
|
||||
/* And setup the clock frequency */
|
||||
|
||||
actual = twi_hw_setfrequency(priv, frequency);
|
||||
twi_givesem(&priv->exclsem);
|
||||
return actual;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: twi_transfer
|
||||
*
|
||||
@@ -738,11 +708,19 @@ static int twi_transfer(FAR struct i2c_master_s *dev,
|
||||
|
||||
twi_takesem(&priv->exclsem);
|
||||
|
||||
/* Initiate the message transfer */
|
||||
/* Setup the message transfer */
|
||||
|
||||
priv->msg = msgs;
|
||||
priv->msgc = count;
|
||||
|
||||
/* Configure the I2C frequency.
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
twi_setfrequency(priv, msgs->frequency);
|
||||
|
||||
/* Initiate the transfer. The rest will be handled from interrupt
|
||||
* logic. Interrupts must be disabled to prevent re-entrance from the
|
||||
* interrupt level.
|
||||
@@ -771,59 +749,54 @@ static int twi_transfer(FAR struct i2c_master_s *dev,
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: twi_hw_setfrequency
|
||||
* Name: twi_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the frequency for the next transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t twi_hw_setfrequency(struct twi_dev_s *priv, uint32_t frequency)
|
||||
static void twi_setfrequency(struct twi_dev_s *priv, uint32_t frequency)
|
||||
{
|
||||
unsigned int ckdiv;
|
||||
unsigned int cldiv;
|
||||
uint32_t actual;
|
||||
uint32_t regval;
|
||||
|
||||
/* Configure TWI output clocking, trying each value of CKDIV {0..7} */
|
||||
|
||||
for (ckdiv = 0; ckdiv < 8; ckdiv++)
|
||||
if (frequency != priv->i2cfreq)
|
||||
{
|
||||
/* Calulate the CLDIV value using the current CKDIV guess */
|
||||
/* Configure TWI output clocking, trying each value of CKDIV {0..7} */
|
||||
|
||||
cldiv = ((priv->frequency / (frequency << 1)) - 4) / (1 << ckdiv);
|
||||
|
||||
/* Is CLDIV in range? */
|
||||
|
||||
if (cldiv <= 255)
|
||||
for (ckdiv = 0; ckdiv < 8; ckdiv++)
|
||||
{
|
||||
/* Yes, break out and use it */
|
||||
/* Calulate the CLDIV value using the current CKDIV guess */
|
||||
|
||||
break;
|
||||
cldiv = ((priv->clkin / (frequency << 1)) - 4) / (1 << ckdiv);
|
||||
|
||||
/* Is CLDIV in range? */
|
||||
|
||||
if (cldiv <= 255)
|
||||
{
|
||||
/* Yes, break out and use it */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then setup the TWI Clock Waveform Generator Register, using the same
|
||||
* value for CLDIV and CHDIV (for 1:1 duty).
|
||||
*/
|
||||
|
||||
twi_putrel(priv, SAM_TWI_CWGR_OFFSET, 0);
|
||||
|
||||
regval = ((uint32_t)ckdiv << TWI_CWGR_CKDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWI_CWGR_CHDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWI_CWGR_CLDIV_SHIFT);
|
||||
twi_putrel(priv, SAM_TWI_CWGR_OFFSET, regval);
|
||||
|
||||
/* Remember the selected frequency for error recovery */
|
||||
|
||||
priv->i2cfreq = frequency;
|
||||
}
|
||||
|
||||
/* Then setup the TWI Clock Waveform Generator Register, using the same
|
||||
* value for CLDIV and CHDIV (for 1:1 duty).
|
||||
*/
|
||||
|
||||
twi_putrel(priv, SAM_TWI_CWGR_OFFSET, 0);
|
||||
|
||||
regval = ((uint32_t)ckdiv << TWI_CWGR_CKDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWI_CWGR_CHDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWI_CWGR_CLDIV_SHIFT);
|
||||
twi_putrel(priv, SAM_TWI_CWGR_OFFSET, regval);
|
||||
|
||||
/* Return the actual frequency */
|
||||
|
||||
actual = (priv->frequency / 2) / (((1 << ckdiv) * cldiv) + 2);
|
||||
i2cvdbg("TWI%d frequency: %d ckdiv: %d cldiv: %d actual: %d\n",
|
||||
priv->twi, frequency, ckdiv, cldiv, actual);
|
||||
|
||||
/* Remember the selected frequency for error recovery */
|
||||
|
||||
priv->deffreq = frequency;
|
||||
return actual;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -864,7 +837,7 @@ static void twi_hw_initialize(struct twi_dev_s *priv, unsigned int pid,
|
||||
|
||||
/* Set base frequency */
|
||||
|
||||
priv->frequency = BOARD_MCK_FREQUENCY;
|
||||
priv->clkin = BOARD_MCK_FREQUENCY;
|
||||
|
||||
#if 0
|
||||
/* Determine the maximum valid frequency setting */
|
||||
@@ -874,23 +847,23 @@ static void twi_hw_initialize(struct twi_dev_s *priv, unsigned int pid,
|
||||
|
||||
if (mck <= TWI_MAX_FREQUENCY)
|
||||
{
|
||||
priv->frequency = mck;
|
||||
regval = PMC_PCR_DIV1;
|
||||
priv->clkin = mck;
|
||||
regval = PMC_PCR_DIV1;
|
||||
}
|
||||
else if ((mck >> 1) <= TWI_MAX_FREQUENCY)
|
||||
{
|
||||
priv->frequency = (mck >> 1);
|
||||
regval = PMC_PCR_DIV2;
|
||||
priv->clkin = (mck >> 1);
|
||||
regval = PMC_PCR_DIV2;
|
||||
}
|
||||
else if ((mck >> 2) <= TWI_MAX_FREQUENCY)
|
||||
{
|
||||
priv->frequency = (mck >> 2);
|
||||
regval = PMC_PCR_DIV4;
|
||||
priv->clkin = (mck >> 2);
|
||||
regval = PMC_PCR_DIV4;
|
||||
}
|
||||
else /* if ((mck >> 3) <= TWI_MAX_FREQUENCY) */
|
||||
{
|
||||
priv->frequency = (mck >> 3);
|
||||
regval = PMC_PCR_DIV8;
|
||||
priv->clkin = (mck >> 3);
|
||||
regval = PMC_PCR_DIV8;
|
||||
}
|
||||
|
||||
/* Set the TWI peripheral input clock to the maximum, valid frequency */
|
||||
@@ -901,7 +874,7 @@ static void twi_hw_initialize(struct twi_dev_s *priv, unsigned int pid,
|
||||
|
||||
/* Set the initial TWI data transfer frequency */
|
||||
|
||||
(void)twi_hw_setfrequency(priv, frequency);
|
||||
twi_setfrequency(priv, frequency);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -162,9 +162,7 @@ struct twi_dev_s
|
||||
const struct twi_attr_s *attr; /* Invariant attributes of TWI device */
|
||||
struct i2c_msg_s *msg; /* Message list */
|
||||
uint32_t twiclk; /* TWI input clock frequency */
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
uint32_t frequency; /* TWI transfer clock frequency */
|
||||
#endif
|
||||
uint8_t msgc; /* Number of message in the message list */
|
||||
|
||||
sem_t exclsem; /* Only one thread can access at a time */
|
||||
@@ -234,15 +232,12 @@ static void twi_startmessage(struct twi_dev_s *priv, struct i2c_msg_s *msg);
|
||||
|
||||
/* I2C device operations */
|
||||
|
||||
static uint32_t twi_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int twi_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
|
||||
/* Initialization */
|
||||
|
||||
static uint32_t twi_hw_setfrequency(struct twi_dev_s *priv,
|
||||
uint32_t frequency);
|
||||
static uint32_t twi_setfrequency(struct twi_dev_s *priv, uint32_t frequency);
|
||||
static void twi_hw_initialize(struct twi_dev_s *priv, uint32_t frequency);
|
||||
|
||||
/****************************************************************************
|
||||
@@ -311,8 +306,7 @@ static struct twi_dev_s g_twi3;
|
||||
|
||||
struct i2c_ops_s g_twiops =
|
||||
{
|
||||
.setfrequency = twi_setfrequency,
|
||||
.transfer = twi_transfer
|
||||
.transfer = twi_transfer
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -819,32 +813,6 @@ static void twi_startmessage(struct twi_dev_s *priv, struct i2c_msg_s *msg)
|
||||
* I2C device operations
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: twi_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the frequency for the next transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t twi_setfrequency(FAR struct i2c_master_s *dev, uint32_t frequency)
|
||||
{
|
||||
struct twi_dev_s *priv = (struct twi_dev_s *)dev;
|
||||
uint32_t actual;
|
||||
|
||||
DEBUGASSERT(dev);
|
||||
|
||||
/* Get exclusive access to the device */
|
||||
|
||||
twi_takesem(&priv->exclsem);
|
||||
|
||||
/* And setup the clock frequency */
|
||||
|
||||
actual = twi_hw_setfrequency(priv, frequency);
|
||||
twi_givesem(&priv->exclsem);
|
||||
return actual;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: twi_transfer
|
||||
*
|
||||
@@ -885,11 +853,19 @@ static int twi_transfer(FAR struct i2c_master_s *dev,
|
||||
|
||||
twi_takesem(&priv->exclsem);
|
||||
|
||||
/* Initiate the message transfer */
|
||||
/* Setup the message transfer */
|
||||
|
||||
priv->msg = msgs;
|
||||
priv->msgc = count;
|
||||
|
||||
/* Configure the I2C frequency.
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
twi_setfrequency(priv, msgs->frequency);
|
||||
|
||||
/* Initiate the transfer. The rest will be handled from interrupt
|
||||
* logic. Interrupts must be disabled to prevent re-entrance from the
|
||||
* interrupt level.
|
||||
@@ -945,63 +921,54 @@ static void twi_enableclk(struct twi_dev_s *priv)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: twi_hw_setfrequency
|
||||
* Name: twi_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the frequency for the next transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t twi_hw_setfrequency(struct twi_dev_s *priv, uint32_t frequency)
|
||||
static void twi_setfrequency(struct twi_dev_s *priv, uint32_t frequency)
|
||||
{
|
||||
unsigned int ckdiv;
|
||||
unsigned int cldiv;
|
||||
uint32_t actual;
|
||||
uint32_t regval;
|
||||
|
||||
/* Configure TWI output clocking, trying each value of CKDIV {0..7} */
|
||||
|
||||
for (ckdiv = 0; ckdiv < 8; ckdiv++)
|
||||
if (frequency != priv->frequency)
|
||||
{
|
||||
/* Calculate the CLDIV value using the current CKDIV guess */
|
||||
/* Configure TWI output clocking, trying each value of CKDIV {0..7} */
|
||||
|
||||
cldiv = ((priv->twiclk / (frequency << 1)) - 4) / (1 << ckdiv);
|
||||
|
||||
/* Is CLDIV in range? */
|
||||
|
||||
if (cldiv <= 255)
|
||||
for (ckdiv = 0; ckdiv < 8; ckdiv++)
|
||||
{
|
||||
/* Yes, break out and use it */
|
||||
/* Calculate the CLDIV value using the current CKDIV guess */
|
||||
|
||||
break;
|
||||
cldiv = ((priv->twiclk / (frequency << 1)) - 4) / (1 << ckdiv);
|
||||
|
||||
/* Is CLDIV in range? */
|
||||
|
||||
if (cldiv <= 255)
|
||||
{
|
||||
/* Yes, break out and use it */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then setup the TWI Clock Waveform Generator Register, using the same
|
||||
* value for CLDIV and CHDIV (for 1:1 duty).
|
||||
*/
|
||||
|
||||
twi_putrel(priv, SAM_TWI_CWGR_OFFSET, 0);
|
||||
|
||||
regval = ((uint32_t)ckdiv << TWI_CWGR_CKDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWI_CWGR_CHDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWI_CWGR_CLDIV_SHIFT);
|
||||
twi_putrel(priv, SAM_TWI_CWGR_OFFSET, regval);
|
||||
|
||||
/* Save the requested frequency */
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
|
||||
/* Then setup the TWI Clock Waveform Generator Register, using the same
|
||||
* value for CLDIV and CHDIV (for 1:1 duty).
|
||||
*/
|
||||
|
||||
twi_putrel(priv, SAM_TWI_CWGR_OFFSET, 0);
|
||||
|
||||
regval = ((uint32_t)ckdiv << TWI_CWGR_CKDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWI_CWGR_CHDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWI_CWGR_CLDIV_SHIFT);
|
||||
twi_putrel(priv, SAM_TWI_CWGR_OFFSET, regval);
|
||||
|
||||
/* Calculate the actual I2C frequency */
|
||||
|
||||
actual = (priv->twiclk / 2) / (((1 << ckdiv) * cldiv) + 2);
|
||||
i2cvdbg("TWI%d frequency: %d ckdiv: %d cldiv: %d actual: %d\n",
|
||||
priv->attr->twi, frequency, ckdiv, cldiv, actual);
|
||||
|
||||
/* Save the requested frequency (for I2C reset) and return the
|
||||
* actual frequency.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
priv->frequency = frequency;
|
||||
#endif
|
||||
return actual;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -1093,7 +1060,7 @@ static void twi_hw_initialize(struct twi_dev_s *priv, uint32_t frequency)
|
||||
|
||||
/* Set the initial TWI data transfer frequency */
|
||||
|
||||
twi_hw_setfrequency(priv, frequency);
|
||||
twi_setfrequency(priv, frequency);
|
||||
|
||||
/* Enable Interrupts */
|
||||
|
||||
|
||||
@@ -159,9 +159,7 @@ struct twi_dev_s
|
||||
const struct twi_attr_s *attr; /* Invariant attributes of TWIHS device */
|
||||
struct i2c_msg_s *msg; /* Message list */
|
||||
uint32_t twiclk; /* TWIHS input clock frequency */
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
uint32_t frequency; /* TWIHS transfer clock frequency */
|
||||
#endif
|
||||
bool initd; /* True :device has been initialized */
|
||||
uint8_t msgc; /* Number of message in the message list */
|
||||
|
||||
@@ -229,15 +227,12 @@ static void twi_startmessage(struct twi_dev_s *priv, struct i2c_msg_s *msg);
|
||||
|
||||
/* I2C device operations */
|
||||
|
||||
static uint32_t twi_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int twi_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
|
||||
/* Initialization */
|
||||
|
||||
static uint32_t twi_hw_setfrequency(struct twi_dev_s *priv,
|
||||
uint32_t frequency);
|
||||
static void twi_setfrequency(struct twi_dev_s *priv, uint32_t frequency);
|
||||
static void twi_hw_initialize(struct twi_dev_s *priv, uint32_t frequency);
|
||||
|
||||
/****************************************************************************
|
||||
@@ -291,8 +286,7 @@ static struct twi_dev_s g_twi2;
|
||||
|
||||
struct i2c_ops_s g_twiops =
|
||||
{
|
||||
.setfrequency = twi_setfrequency,
|
||||
.transfer = twi_transfer
|
||||
.transfer = twi_transfer
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -846,32 +840,6 @@ static void twi_startmessage(struct twi_dev_s *priv, struct i2c_msg_s *msg)
|
||||
* I2C device operations
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: twi_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the frequency for the next transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t twi_setfrequency(FAR struct i2c_master_s *dev, uint32_t frequency)
|
||||
{
|
||||
struct twi_dev_s *priv = (struct twi_dev_s *)dev;
|
||||
uint32_t actual;
|
||||
|
||||
DEBUGASSERT(dev);
|
||||
|
||||
/* Get exclusive access to the device */
|
||||
|
||||
twi_takesem(&priv->exclsem);
|
||||
|
||||
/* And setup the clock frequency */
|
||||
|
||||
actual = twi_hw_setfrequency(priv, frequency);
|
||||
twi_givesem(&priv->exclsem);
|
||||
return actual;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: twi_transfer
|
||||
*
|
||||
@@ -912,11 +880,19 @@ static int twi_transfer(FAR struct i2c_master_s *dev,
|
||||
|
||||
twi_takesem(&priv->exclsem);
|
||||
|
||||
/* Initiate the message transfer */
|
||||
/* Setup the message transfer */
|
||||
|
||||
priv->msg = msgs;
|
||||
priv->msgc = count;
|
||||
|
||||
/* Configure the I2C frequency.
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
twi_setfrequency(priv, msgs->frequency);
|
||||
|
||||
/* Initiate the transfer. The rest will be handled from interrupt
|
||||
* logic. Interrupts must be disabled to prevent re-entrance from the
|
||||
* interrupt level.
|
||||
@@ -972,63 +948,54 @@ static void twi_enableclk(struct twi_dev_s *priv)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: twi_hw_setfrequency
|
||||
* Name: twi_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the frequency for the next transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t twi_hw_setfrequency(struct twi_dev_s *priv, uint32_t frequency)
|
||||
static void twi_setfrequency(struct twi_dev_s *priv, uint32_t frequency)
|
||||
{
|
||||
unsigned int ckdiv;
|
||||
unsigned int cldiv;
|
||||
uint32_t actual;
|
||||
uint32_t regval;
|
||||
|
||||
/* Configure TWIHS output clocking, trying each value of CKDIV {0..7} */
|
||||
|
||||
for (ckdiv = 0; ckdiv < 8; ckdiv++)
|
||||
if (frequency != priv->frequency)
|
||||
{
|
||||
/* Calculate the CLDIV value using the current CKDIV guess */
|
||||
/* Configure TWIHS output clocking, trying each value of CKDIV {0..7} */
|
||||
|
||||
cldiv = ((priv->twiclk / (frequency << 1)) - 4) / (1 << ckdiv);
|
||||
|
||||
/* Is CLDIV in range? */
|
||||
|
||||
if (cldiv <= 255)
|
||||
for (ckdiv = 0; ckdiv < 8; ckdiv++)
|
||||
{
|
||||
/* Yes, break out and use it */
|
||||
/* Calculate the CLDIV value using the current CKDIV guess */
|
||||
|
||||
break;
|
||||
cldiv = ((priv->twiclk / (frequency << 1)) - 4) / (1 << ckdiv);
|
||||
|
||||
/* Is CLDIV in range? */
|
||||
|
||||
if (cldiv <= 255)
|
||||
{
|
||||
/* Yes, break out and use it */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then setup the TWIHS Clock Waveform Generator Register, using the same
|
||||
* value for CLDIV and CHDIV (for 1:1 duty).
|
||||
*/
|
||||
|
||||
twi_putrel(priv, SAM_TWIHS_CWGR_OFFSET, 0);
|
||||
|
||||
regval = ((uint32_t)ckdiv << TWIHS_CWGR_CKDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWIHS_CWGR_CHDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWIHS_CWGR_CLDIV_SHIFT);
|
||||
twi_putrel(priv, SAM_TWIHS_CWGR_OFFSET, regval);
|
||||
|
||||
/* Save the requested frequency */
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
|
||||
/* Then setup the TWIHS Clock Waveform Generator Register, using the same
|
||||
* value for CLDIV and CHDIV (for 1:1 duty).
|
||||
*/
|
||||
|
||||
twi_putrel(priv, SAM_TWIHS_CWGR_OFFSET, 0);
|
||||
|
||||
regval = ((uint32_t)ckdiv << TWIHS_CWGR_CKDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWIHS_CWGR_CHDIV_SHIFT) |
|
||||
((uint32_t)cldiv << TWIHS_CWGR_CLDIV_SHIFT);
|
||||
twi_putrel(priv, SAM_TWIHS_CWGR_OFFSET, regval);
|
||||
|
||||
/* Calculate the actual I2C frequency */
|
||||
|
||||
actual = (priv->twiclk / 2) / (((1 << ckdiv) * cldiv) + 2);
|
||||
i2cvdbg("TWIHS%d frequency: %d ckdiv: %d cldiv: %d actual: %d\n",
|
||||
priv->attr->twi, frequency, ckdiv, cldiv, actual);
|
||||
|
||||
/* Save the requested frequency (for I2C reset) and return the
|
||||
* actual frequency.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
priv->frequency = frequency;
|
||||
#endif
|
||||
return actual;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -1120,7 +1087,7 @@ static void twi_hw_initialize(struct twi_dev_s *priv, uint32_t frequency)
|
||||
|
||||
/* Set the initial TWIHS data transfer frequency */
|
||||
|
||||
twi_hw_setfrequency(priv, frequency);
|
||||
twi_setfrequency(priv, frequency);
|
||||
|
||||
/* Enable Interrupts */
|
||||
|
||||
|
||||
@@ -260,6 +260,7 @@ struct stm32_i2c_priv_s
|
||||
uint8_t msgc; /* Message count */
|
||||
struct i2c_msg_s *msgv; /* Message list */
|
||||
uint8_t *ptr; /* Current message buffer */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
int dcnt; /* Current message length */
|
||||
uint16_t flags; /* Current message flags */
|
||||
|
||||
@@ -283,8 +284,6 @@ struct stm32_i2c_inst_s
|
||||
{
|
||||
const struct i2c_ops_s *ops; /* Standard I2C operations */
|
||||
struct stm32_i2c_priv_s *priv; /* Common driver private data structure */
|
||||
|
||||
uint32_t frequency; /* Frequency used in this instantiation */
|
||||
};
|
||||
|
||||
/************************************************************************************
|
||||
@@ -346,8 +345,6 @@ static int stm32_i2c3_isr(int irq, void *context);
|
||||
|
||||
static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv);
|
||||
static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv);
|
||||
static uint32_t stm32_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
|
||||
int count);
|
||||
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
|
||||
@@ -469,8 +466,7 @@ static struct stm32_i2c_priv_s stm32_i2c3_priv =
|
||||
|
||||
static const struct i2c_ops_s stm32_i2c_ops =
|
||||
{
|
||||
.setfrequency = stm32_i2c_setfrequency,
|
||||
.transfer = stm32_i2c_transfer
|
||||
.transfer = stm32_i2c_transfer
|
||||
};
|
||||
|
||||
/************************************************************************************
|
||||
@@ -949,90 +945,99 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
|
||||
uint16_t freqmhz;
|
||||
uint16_t speed;
|
||||
|
||||
/* Disable the selected I2C peripheral to configure TRISE */
|
||||
/* Has the I2C bus frequency changed? */
|
||||
|
||||
cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET);
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1 & ~I2C_CR1_PE);
|
||||
|
||||
/* Update timing and control registers */
|
||||
|
||||
freqmhz = (uint16_t)(STM32_PCLK1_FREQUENCY / 1000000);
|
||||
ccr = 0;
|
||||
|
||||
/* Configure speed in standard mode */
|
||||
|
||||
if (frequency <= 100000)
|
||||
if (frequency != priv->frequency)
|
||||
{
|
||||
/* Standard mode speed calculation */
|
||||
/* Disable the selected I2C peripheral to configure TRISE */
|
||||
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency << 1));
|
||||
cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET);
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1 & ~I2C_CR1_PE);
|
||||
|
||||
/* The CCR fault must be >= 4 */
|
||||
/* Update timing and control registers */
|
||||
|
||||
if (speed < 4)
|
||||
freqmhz = (uint16_t)(STM32_PCLK1_FREQUENCY / 1000000);
|
||||
ccr = 0;
|
||||
|
||||
/* Configure speed in standard mode */
|
||||
|
||||
if (frequency <= 100000)
|
||||
{
|
||||
/* Set the minimum allowed value */
|
||||
/* Standard mode speed calculation */
|
||||
|
||||
speed = 4;
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency << 1));
|
||||
|
||||
/* The CCR fault must be >= 4 */
|
||||
|
||||
if (speed < 4)
|
||||
{
|
||||
/* Set the minimum allowed value */
|
||||
|
||||
speed = 4;
|
||||
}
|
||||
|
||||
ccr |= speed;
|
||||
|
||||
/* Set Maximum Rise Time for standard mode */
|
||||
|
||||
trise = freqmhz + 1;
|
||||
}
|
||||
|
||||
ccr |= speed;
|
||||
/* Configure speed in fast mode */
|
||||
|
||||
/* Set Maximum Rise Time for standard mode */
|
||||
|
||||
trise = freqmhz + 1;
|
||||
}
|
||||
|
||||
/* Configure speed in fast mode */
|
||||
|
||||
else /* (frequency <= 400000) */
|
||||
{
|
||||
/* Fast mode speed calculation with Tlow/Thigh = 16/9 */
|
||||
else /* (frequency <= 400000) */
|
||||
{
|
||||
/* Fast mode speed calculation with Tlow/Thigh = 16/9 */
|
||||
|
||||
#ifdef CONFIG_STM32_I2C_DUTY16_9
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 25));
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 25));
|
||||
|
||||
/* Set DUTY and fast speed bits */
|
||||
/* Set DUTY and fast speed bits */
|
||||
|
||||
ccr |= (I2C_CCR_DUTY | I2C_CCR_FS);
|
||||
ccr |= (I2C_CCR_DUTY | I2C_CCR_FS);
|
||||
#else
|
||||
/* Fast mode speed calculation with Tlow/Thigh = 2 */
|
||||
/* Fast mode speed calculation with Tlow/Thigh = 2 */
|
||||
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 3));
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 3));
|
||||
|
||||
/* Set fast speed bit */
|
||||
/* Set fast speed bit */
|
||||
|
||||
ccr |= I2C_CCR_FS;
|
||||
ccr |= I2C_CCR_FS;
|
||||
#endif
|
||||
|
||||
/* Verify that the CCR speed value is nonzero */
|
||||
/* Verify that the CCR speed value is nonzero */
|
||||
|
||||
if (speed < 1)
|
||||
{
|
||||
/* Set the minimum allowed value */
|
||||
if (speed < 1)
|
||||
{
|
||||
/* Set the minimum allowed value */
|
||||
|
||||
speed = 1;
|
||||
speed = 1;
|
||||
}
|
||||
|
||||
ccr |= speed;
|
||||
|
||||
/* Set Maximum Rise Time for fast mode */
|
||||
|
||||
trise = (uint16_t)(((freqmhz * 300) / 1000) + 1);
|
||||
}
|
||||
|
||||
ccr |= speed;
|
||||
/* Write the new values of the CCR and TRISE registers */
|
||||
|
||||
/* Set Maximum Rise Time for fast mode */
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CCR_OFFSET, ccr);
|
||||
stm32_i2c_putreg(priv, STM32_I2C_TRISE_OFFSET, trise);
|
||||
|
||||
trise = (uint16_t)(((freqmhz * 300) / 1000) + 1);
|
||||
/* Bit 14 of OAR1 must be configured and kept at 1 */
|
||||
|
||||
stm32_i2c_putreg(priv, STM32_I2C_OAR1_OFFSET, I2C_OAR1_ONE);
|
||||
|
||||
/* Re-enable the peripheral (or not) */
|
||||
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1);
|
||||
|
||||
/* Save the new I2C frequency */
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
|
||||
/* Write the new values of the CCR and TRISE registers */
|
||||
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CCR_OFFSET, ccr);
|
||||
stm32_i2c_putreg(priv, STM32_I2C_TRISE_OFFSET, trise);
|
||||
|
||||
/* Bit 14 of OAR1 must be configured and kept at 1 */
|
||||
|
||||
stm32_i2c_putreg(priv, STM32_I2C_OAR1_OFFSET, I2C_OAR1_ONE);
|
||||
|
||||
/* Re-enable the peripheral (or not) */
|
||||
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1);
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
@@ -1598,28 +1603,6 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
|
||||
* Device Driver Operations
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: stm32_i2c_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the I2C frequency
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
static uint32_t stm32_i2c_setfrequency(FAR struct i2c_master_s *dev, uint32_t frequency)
|
||||
{
|
||||
stm32_i2c_sem_wait(dev);
|
||||
|
||||
#if STM32_PCLK1_FREQUENCY < 4000000
|
||||
((struct stm32_i2c_inst_s *)dev)->frequency = 100000;
|
||||
#else
|
||||
((struct stm32_i2c_inst_s *)dev)->frequency = frequency;
|
||||
#endif
|
||||
|
||||
stm32_i2c_sem_post(dev);
|
||||
return ((struct stm32_i2c_inst_s *)dev)->frequency;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
* Name: stm32_i2c_process
|
||||
*
|
||||
@@ -1684,9 +1667,13 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
|
||||
|
||||
stm32_i2c_tracereset(priv);
|
||||
|
||||
/* Set I2C clock frequency (on change it toggles I2C_CR1_PE !) */
|
||||
/* Set I2C clock frequency (on change it toggles I2C_CR1_PE !)
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
stm32_i2c_setclock(priv, inst->frequency);
|
||||
stm32_i2c_setclock(priv, msgs->frequency);
|
||||
|
||||
/* Trigger start condition, then the process moves into the ISR. I2C
|
||||
* interrupts will be enabled within stm32_i2c_waitdone().
|
||||
@@ -1895,9 +1882,8 @@ FAR struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Initialize instance */
|
||||
|
||||
inst->ops = &stm32_i2c_ops;
|
||||
inst->priv = priv;
|
||||
inst->frequency = 100000;
|
||||
inst->ops = &stm32_i2c_ops;
|
||||
inst->priv = priv;
|
||||
|
||||
/* Initialize private data for the first time, increment reference count,
|
||||
* power-up hardware and configure GPIOs.
|
||||
|
||||
@@ -287,6 +287,7 @@ struct stm32_i2c_priv_s
|
||||
uint8_t msgc; /* Message count */
|
||||
struct i2c_msg_s *msgv; /* Message list */
|
||||
uint8_t *ptr; /* Current message buffer */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
int dcnt; /* Current message length */
|
||||
uint16_t flags; /* Current message flags */
|
||||
bool check_addr_ACK; /* Flag to signal if on next interrupt address has ACKed */
|
||||
@@ -312,8 +313,6 @@ struct stm32_i2c_inst_s
|
||||
{
|
||||
const struct i2c_ops_s *ops; /* Standard I2C operations */
|
||||
struct stm32_i2c_priv_s *priv; /* Common driver private data structure */
|
||||
|
||||
uint32_t frequency; /* Frequency used in this instantiation */
|
||||
};
|
||||
|
||||
/************************************************************************************
|
||||
@@ -375,8 +374,6 @@ static int stm32_i2c3_isr(int irq, void *context);
|
||||
|
||||
static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv);
|
||||
static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv);
|
||||
static uint32_t stm32_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
|
||||
int count);
|
||||
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
|
||||
@@ -477,8 +474,7 @@ static struct stm32_i2c_priv_s stm32_i2c3_priv =
|
||||
|
||||
static const struct i2c_ops_s stm32_i2c_ops =
|
||||
{
|
||||
.setfrequency = stm32_i2c_setfrequency,
|
||||
.transfer = stm32_i2c_transfer
|
||||
.transfer = stm32_i2c_transfer
|
||||
};
|
||||
|
||||
/************************************************************************************
|
||||
@@ -957,90 +953,99 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
|
||||
uint16_t freqmhz;
|
||||
uint16_t speed;
|
||||
|
||||
/* Disable the selected I2C peripheral to configure TRISE */
|
||||
/* Has the I2C bus frequency changed? */
|
||||
|
||||
cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET);
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1 & ~I2C_CR1_PE);
|
||||
|
||||
/* Update timing and control registers */
|
||||
|
||||
freqmhz = (uint16_t)(STM32_PCLK1_FREQUENCY / 1000000);
|
||||
ccr = 0;
|
||||
|
||||
/* Configure speed in standard mode */
|
||||
|
||||
if (frequency <= 100000)
|
||||
if (frequency != priv->frequency)
|
||||
{
|
||||
/* Standard mode speed calculation */
|
||||
/* Disable the selected I2C peripheral to configure TRISE */
|
||||
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency << 1));
|
||||
cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET);
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1 & ~I2C_CR1_PE);
|
||||
|
||||
/* The CCR fault must be >= 4 */
|
||||
/* Update timing and control registers */
|
||||
|
||||
if (speed < 4)
|
||||
freqmhz = (uint16_t)(STM32_PCLK1_FREQUENCY / 1000000);
|
||||
ccr = 0;
|
||||
|
||||
/* Configure speed in standard mode */
|
||||
|
||||
if (frequency <= 100000)
|
||||
{
|
||||
/* Set the minimum allowed value */
|
||||
/* Standard mode speed calculation */
|
||||
|
||||
speed = 4;
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency << 1));
|
||||
|
||||
/* The CCR fault must be >= 4 */
|
||||
|
||||
if (speed < 4)
|
||||
{
|
||||
/* Set the minimum allowed value */
|
||||
|
||||
speed = 4;
|
||||
}
|
||||
|
||||
ccr |= speed;
|
||||
|
||||
/* Set Maximum Rise Time for standard mode */
|
||||
|
||||
trise = freqmhz + 1;
|
||||
}
|
||||
|
||||
ccr |= speed;
|
||||
/* Configure speed in fast mode */
|
||||
|
||||
/* Set Maximum Rise Time for standard mode */
|
||||
|
||||
trise = freqmhz + 1;
|
||||
}
|
||||
|
||||
/* Configure speed in fast mode */
|
||||
|
||||
else /* (frequency <= 400000) */
|
||||
{
|
||||
/* Fast mode speed calculation with Tlow/Thigh = 16/9 */
|
||||
else /* (frequency <= 400000) */
|
||||
{
|
||||
/* Fast mode speed calculation with Tlow/Thigh = 16/9 */
|
||||
|
||||
#ifdef CONFIG_STM32_I2C_DUTY16_9
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 25));
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 25));
|
||||
|
||||
/* Set DUTY and fast speed bits */
|
||||
/* Set DUTY and fast speed bits */
|
||||
|
||||
ccr |= (I2C_CCR_DUTY | I2C_CCR_FS);
|
||||
ccr |= (I2C_CCR_DUTY | I2C_CCR_FS);
|
||||
#else
|
||||
/* Fast mode speed calculation with Tlow/Thigh = 2 */
|
||||
/* Fast mode speed calculation with Tlow/Thigh = 2 */
|
||||
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 3));
|
||||
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 3));
|
||||
|
||||
/* Set fast speed bit */
|
||||
/* Set fast speed bit */
|
||||
|
||||
ccr |= I2C_CCR_FS;
|
||||
ccr |= I2C_CCR_FS;
|
||||
#endif
|
||||
|
||||
/* Verify that the CCR speed value is nonzero */
|
||||
/* Verify that the CCR speed value is nonzero */
|
||||
|
||||
if (speed < 1)
|
||||
{
|
||||
/* Set the minimum allowed value */
|
||||
if (speed < 1)
|
||||
{
|
||||
/* Set the minimum allowed value */
|
||||
|
||||
speed = 1;
|
||||
speed = 1;
|
||||
}
|
||||
|
||||
ccr |= speed;
|
||||
|
||||
/* Set Maximum Rise Time for fast mode */
|
||||
|
||||
trise = (uint16_t)(((freqmhz * 300) / 1000) + 1);
|
||||
}
|
||||
|
||||
ccr |= speed;
|
||||
/* Write the new values of the CCR and TRISE registers */
|
||||
|
||||
/* Set Maximum Rise Time for fast mode */
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CCR_OFFSET, ccr);
|
||||
stm32_i2c_putreg(priv, STM32_I2C_TRISE_OFFSET, trise);
|
||||
|
||||
trise = (uint16_t)(((freqmhz * 300) / 1000) + 1);
|
||||
/* Bit 14 of OAR1 must be configured and kept at 1 */
|
||||
|
||||
stm32_i2c_putreg(priv, STM32_I2C_OAR1_OFFSET, I2C_OAR1_ONE);
|
||||
|
||||
/* Re-enable the peripheral (or not) */
|
||||
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1);
|
||||
|
||||
/* Save the new I2C frequency */
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
|
||||
/* Write the new values of the CCR and TRISE registers */
|
||||
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CCR_OFFSET, ccr);
|
||||
stm32_i2c_putreg(priv, STM32_I2C_TRISE_OFFSET, trise);
|
||||
|
||||
/* Bit 14 of OAR1 must be configured and kept at 1 */
|
||||
|
||||
stm32_i2c_putreg(priv, STM32_I2C_OAR1_OFFSET, I2C_OAR1_ONE);
|
||||
|
||||
/* Re-enable the peripheral (or not) */
|
||||
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1);
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
@@ -2029,28 +2034,6 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
|
||||
* Device Driver Operations
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: stm32_i2c_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the I2C frequency
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
static uint32_t stm32_i2c_setfrequency(FAR struct i2c_master_s *dev, uint32_t frequency)
|
||||
{
|
||||
stm32_i2c_sem_wait(dev);
|
||||
|
||||
#if STM32_PCLK1_FREQUENCY < 4000000
|
||||
((struct stm32_i2c_inst_s *)dev)->frequency = 100000;
|
||||
#else
|
||||
((struct stm32_i2c_inst_s *)dev)->frequency = frequency;
|
||||
#endif
|
||||
|
||||
stm32_i2c_sem_post(dev);
|
||||
return ((struct stm32_i2c_inst_s *)dev)->frequency;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
* Name: stm32_i2c_process
|
||||
*
|
||||
@@ -2108,9 +2091,13 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
|
||||
|
||||
stm32_i2c_tracereset(priv);
|
||||
|
||||
/* Set I2C clock frequency (on change it toggles I2C_CR1_PE !) */
|
||||
/* Set I2C clock frequency (on change it toggles I2C_CR1_PE !)
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
stm32_i2c_setclock(priv, inst->frequency);
|
||||
stm32_i2c_setclock(priv, msgs->frequency);
|
||||
|
||||
/* Trigger start condition, then the process moves into the ISR. I2C
|
||||
* interrupts will be enabled within stm32_i2c_waitdone().
|
||||
@@ -2339,9 +2326,8 @@ FAR struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Initialize instance */
|
||||
|
||||
inst->ops = &stm32_i2c_ops;
|
||||
inst->priv = priv;
|
||||
inst->frequency = 100000;
|
||||
inst->ops = &stm32_i2c_ops;
|
||||
inst->priv = priv;
|
||||
|
||||
/* Initialize private data for the first time, increment reference count,
|
||||
* power-up hardware and configure GPIOs.
|
||||
|
||||
@@ -252,6 +252,7 @@ struct stm32_i2c_priv_s
|
||||
uint8_t msgc; /* Message count */
|
||||
struct i2c_msg_s *msgv; /* Message list */
|
||||
uint8_t *ptr; /* Current message buffer */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
int dcnt; /* Current message length */
|
||||
uint16_t flags; /* Current message flags */
|
||||
bool astart; /* START sent */
|
||||
@@ -276,8 +277,6 @@ struct stm32_i2c_inst_s
|
||||
{
|
||||
struct i2c_ops_s *ops; /* Standard I2C operations */
|
||||
struct stm32_i2c_priv_s *priv; /* Common driver private data structure */
|
||||
|
||||
uint32_t frequency; /* Frequency used in this instantiation */
|
||||
};
|
||||
|
||||
/************************************************************************************
|
||||
@@ -332,8 +331,6 @@ static int stm32_i2c3_isr(int irq, void *context);
|
||||
#endif
|
||||
static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv);
|
||||
static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv);
|
||||
static uint32_t stm32_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
|
||||
int count);
|
||||
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
|
||||
@@ -434,8 +431,7 @@ struct stm32_i2c_priv_s stm32_i2c3_priv =
|
||||
|
||||
struct i2c_ops_s stm32_i2c_ops =
|
||||
{
|
||||
.setfrequency = stm32_i2c_setfrequency,
|
||||
.transfer = stm32_i2c_transfer
|
||||
.transfer = stm32_i2c_transfer
|
||||
};
|
||||
|
||||
/************************************************************************************
|
||||
@@ -1066,70 +1062,79 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
|
||||
uint8_t scl_h_period;
|
||||
uint8_t scl_l_period;
|
||||
|
||||
/* Disable the selected I2C peripheral to configure TRISE */
|
||||
/* Has the I2C bus frequency changed? */
|
||||
|
||||
pe = (stm32_i2c_getreg32(priv, STM32_I2C_CR1_OFFSET) & I2C_CR1_PE);
|
||||
if (pe)
|
||||
if (frequency != priv->frequency)
|
||||
{
|
||||
stm32_i2c_modifyreg32(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_PE, 0);
|
||||
}
|
||||
/* Disable the selected I2C peripheral to configure TRISE */
|
||||
|
||||
/* Update timing and control registers */
|
||||
pe = (stm32_i2c_getreg32(priv, STM32_I2C_CR1_OFFSET) & I2C_CR1_PE);
|
||||
if (pe)
|
||||
{
|
||||
stm32_i2c_modifyreg32(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_PE, 0);
|
||||
}
|
||||
|
||||
/* TODO: speed/timing calcs */
|
||||
/* Update timing and control registers */
|
||||
|
||||
/* TODO: speed/timing calcs */
|
||||
#warning "check set filters before timing, see RM0316"
|
||||
|
||||
/* values from 100khz at 8mhz i2c clock */
|
||||
/* values from 100khz at 8mhz i2c clock */
|
||||
|
||||
/* prescaler */
|
||||
/* t_presc= (presc+1)*t_i2cclk */
|
||||
/* RM0316 */
|
||||
/* prescaler */
|
||||
/* t_presc= (presc+1)*t_i2cclk */
|
||||
/* RM0316 */
|
||||
|
||||
if (frequency == 10000)
|
||||
{
|
||||
presc = 0x01;
|
||||
scl_l_period = 0xc7;
|
||||
scl_h_period = 0xc3;
|
||||
h_time = 0x02;
|
||||
s_time = 0x04;
|
||||
}
|
||||
else if (frequency == 100000)
|
||||
{
|
||||
/* values from datasheet with clock 8mhz */
|
||||
if (frequency == 10000)
|
||||
{
|
||||
presc = 0x01;
|
||||
scl_l_period = 0xc7;
|
||||
scl_h_period = 0xc3;
|
||||
h_time = 0x02;
|
||||
s_time = 0x04;
|
||||
}
|
||||
else if (frequency == 100000)
|
||||
{
|
||||
/* values from datasheet with clock 8mhz */
|
||||
|
||||
presc = 0x01;
|
||||
scl_l_period = 0x13;
|
||||
scl_h_period = 0x0f;
|
||||
h_time = 0x02;
|
||||
s_time = 0x04;
|
||||
}
|
||||
else
|
||||
{
|
||||
presc = 0x00;
|
||||
scl_l_period = 0x09;
|
||||
scl_h_period = 0x03;
|
||||
h_time = 0x01;
|
||||
s_time = 0x03;
|
||||
}
|
||||
presc = 0x01;
|
||||
scl_l_period = 0x13;
|
||||
scl_h_period = 0x0f;
|
||||
h_time = 0x02;
|
||||
s_time = 0x04;
|
||||
}
|
||||
else
|
||||
{
|
||||
presc = 0x00;
|
||||
scl_l_period = 0x09;
|
||||
scl_h_period = 0x03;
|
||||
h_time = 0x01;
|
||||
s_time = 0x03;
|
||||
}
|
||||
|
||||
uint32_t timingr =
|
||||
(presc << I2C_TIMINGR_PRESC_SHIFT) |
|
||||
(s_time << I2C_TIMINGR_SCLDEL_SHIFT) |
|
||||
(h_time << I2C_TIMINGR_SDADEL_SHIFT) |
|
||||
(scl_h_period << I2C_TIMINGR_SCLH_SHIFT) |
|
||||
(scl_l_period << I2C_TIMINGR_SCLL_SHIFT);
|
||||
uint32_t timingr =
|
||||
(presc << I2C_TIMINGR_PRESC_SHIFT) |
|
||||
(s_time << I2C_TIMINGR_SCLDEL_SHIFT) |
|
||||
(h_time << I2C_TIMINGR_SDADEL_SHIFT) |
|
||||
(scl_h_period << I2C_TIMINGR_SCLH_SHIFT) |
|
||||
(scl_l_period << I2C_TIMINGR_SCLL_SHIFT);
|
||||
|
||||
stm32_i2c_putreg32(priv, STM32_I2C_TIMINGR_OFFSET, timingr);
|
||||
stm32_i2c_putreg32(priv, STM32_I2C_TIMINGR_OFFSET, timingr);
|
||||
|
||||
/* Bit 14 of OAR1 must be configured and kept at 1 */
|
||||
/* Bit 14 of OAR1 must be configured and kept at 1 */
|
||||
|
||||
stm32_i2c_putreg(priv, STM32_I2C_OAR1_OFFSET, I2C_OAR1_ONE);
|
||||
stm32_i2c_putreg(priv, STM32_I2C_OAR1_OFFSET, I2C_OAR1_ONE);
|
||||
|
||||
/* Re-enable the peripheral (or not) */
|
||||
/* Re-enable the peripheral (or not) */
|
||||
|
||||
if (pe)
|
||||
{
|
||||
stm32_i2c_modifyreg32(priv, STM32_I2C_CR1_OFFSET, 0, I2C_CR1_PE);
|
||||
if (pe)
|
||||
{
|
||||
stm32_i2c_modifyreg32(priv, STM32_I2C_CR1_OFFSET, 0, I2C_CR1_PE);
|
||||
}
|
||||
|
||||
/* Save the new I2C frequency */
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1625,28 +1630,6 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
|
||||
* Device Driver Operations
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: stm32_i2c_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the I2C frequency
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
static uint32_t stm32_i2c_setfrequency(FAR struct i2c_master_s *dev, uint32_t frequency)
|
||||
{
|
||||
stm32_i2c_sem_wait(dev);
|
||||
|
||||
#if STM32_PCLK1_FREQUENCY < 4000000
|
||||
((struct stm32_i2c_inst_s *)dev)->frequency = 100000;
|
||||
#else
|
||||
((struct stm32_i2c_inst_s *)dev)->frequency = frequency;
|
||||
#endif
|
||||
|
||||
stm32_i2c_sem_post(dev);
|
||||
return ((struct stm32_i2c_inst_s *)dev)->frequency;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
* Name: stm32_i2c_process
|
||||
*
|
||||
@@ -1690,9 +1673,13 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
|
||||
|
||||
stm32_i2c_tracereset(priv);
|
||||
|
||||
/* Set I2C clock frequency (on change it toggles I2C_CR1_PE !) */
|
||||
/* Set I2C clock frequency (on change it toggles I2C_CR1_PE !)
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
stm32_i2c_setclock(priv, inst->frequency);
|
||||
stm32_i2c_setclock(priv, msgs->frequency);
|
||||
|
||||
/* Trigger start condition, then the process moves into the ISR. I2C
|
||||
* interrupts will be enabled within stm32_i2c_waitdone().
|
||||
@@ -1896,9 +1883,8 @@ FAR struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
/* Initialize instance */
|
||||
|
||||
inst->ops = &stm32_i2c_ops;
|
||||
inst->priv = priv;
|
||||
inst->frequency = 400000;
|
||||
inst->ops = &stm32_i2c_ops;
|
||||
inst->priv = priv;
|
||||
|
||||
/* Init private data for the first time, increment refs count,
|
||||
* power-up hardware and configure GPIOs.
|
||||
|
||||
@@ -225,6 +225,7 @@ struct tiva_i2c_priv_s
|
||||
uint8_t msgc; /* Message count */
|
||||
struct i2c_msg_s *msgv; /* Message list */
|
||||
uint8_t *mptr; /* Current message buffer */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
int mcnt; /* Current message length */
|
||||
uint16_t mflags; /* Current message flags */
|
||||
uint32_t mstatus; /* MCS register at the end of the transfer */
|
||||
@@ -258,8 +259,6 @@ struct tiva_i2c_inst_s
|
||||
{
|
||||
const struct i2c_ops_s *ops; /* Standard I2C operations */
|
||||
struct tiva_i2c_priv_s *priv; /* Common driver private data structure */
|
||||
|
||||
uint32_t frequency; /* Frequency used in this instantiation */
|
||||
};
|
||||
|
||||
/************************************************************************************
|
||||
@@ -336,10 +335,7 @@ static int tiva_i2c9_interrupt(int irq, void *context);
|
||||
|
||||
static int tiva_i2c_initialize(struct tiva_i2c_priv_s *priv, uint32_t frequency);
|
||||
static int tiva_i2c_uninitialize(struct tiva_i2c_priv_s *priv);
|
||||
static uint32_t tiva_i2c_setclock(struct tiva_i2c_priv_s *priv,
|
||||
uint32_t frequency);
|
||||
static uint32_t tiva_i2c_setfrequency(struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static void tiva_i2c_setclock(struct tiva_i2c_priv_s *priv, uint32_t frequency);
|
||||
static int tiva_i2c_process(struct i2c_master_s *dev, struct i2c_msg_s *msgv,
|
||||
int msgc);
|
||||
static int tiva_i2c_transfer(struct i2c_master_s *dev, struct i2c_msg_s *msgv,
|
||||
@@ -573,8 +569,7 @@ static struct tiva_i2c_priv_s tiva_i2c9_priv;
|
||||
|
||||
static const struct i2c_ops_s tiva_i2c_ops =
|
||||
{
|
||||
.setfrequency = tiva_i2c_setfrequency,
|
||||
.transfer = tiva_i2c_transfer
|
||||
.transfer = tiva_i2c_transfer
|
||||
};
|
||||
|
||||
/************************************************************************************
|
||||
@@ -1770,7 +1765,7 @@ static int tiva_i2c_initialize(struct tiva_i2c_priv_s *priv, uint32_t frequency)
|
||||
|
||||
/* Configure the the initial I2C clock frequency. */
|
||||
|
||||
(void)tiva_i2c_setclock(priv, frequency);
|
||||
tiva_i2c_setclock(priv, frequency);
|
||||
|
||||
/* Attach interrupt handlers and enable interrupts at the NVIC (still
|
||||
* disabled at the source).
|
||||
@@ -1835,68 +1830,46 @@ static int tiva_i2c_uninitialize(struct tiva_i2c_priv_s *priv)
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
static uint32_t tiva_i2c_setclock(struct tiva_i2c_priv_s *priv, uint32_t frequency)
|
||||
static void tiva_i2c_setclock(struct tiva_i2c_priv_s *priv, uint32_t frequency)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t tmp;
|
||||
|
||||
i2cvdbg("I2C%d: frequency: %u\n", priv->config->devno, frequency);
|
||||
|
||||
/* Calculate the clock divider that results in the highest frequency that
|
||||
* is than or equal to the desired speed.
|
||||
*/
|
||||
/* Has the I2C bus frequency changed? */
|
||||
|
||||
tmp = 2 * 10 * frequency;
|
||||
regval = (((SYSCLK_FREQUENCY + tmp - 1) / tmp) - 1) << I2CM_TPR_SHIFT;
|
||||
|
||||
DEBUGASSERT((regval & I2CM_TPR_MASK) == regval);
|
||||
tiva_i2c_putreg(priv, TIVA_I2CM_TPR_OFFSET, regval);
|
||||
|
||||
#if defined(CONFIG_TIVA_I2C_HIGHSPEED) && defined(TIVA_I2CSC_PC_OFFSET)
|
||||
/* If the I2C peripheral is High-Speed enabled then choose the highest
|
||||
* speed that is less than or equal to 3.4 Mbps.
|
||||
*/
|
||||
|
||||
regval = tiva_i2c_getreg(priv, TIVA_I2CSC_PC_OFFSET);
|
||||
if ((regval & I2CSC_PC_HS) != 0)
|
||||
if (frequency != priv->frequency)
|
||||
{
|
||||
tmp = (2 * 3 * 3400000);
|
||||
/* Calculate the clock divider that results in the highest frequency that
|
||||
* is than or equal to the desired speed.
|
||||
*/
|
||||
|
||||
tmp = 2 * 10 * frequency;
|
||||
regval = (((SYSCLK_FREQUENCY + tmp - 1) / tmp) - 1) << I2CM_TPR_SHIFT;
|
||||
|
||||
tiva_i2c_putreg(priv, TIVA_I2CM_TPR_OFFSET, I2CM_TPR_HS | regval);
|
||||
}
|
||||
DEBUGASSERT((regval & I2CM_TPR_MASK) == regval);
|
||||
tiva_i2c_putreg(priv, TIVA_I2CM_TPR_OFFSET, regval);
|
||||
|
||||
#if defined(CONFIG_TIVA_I2C_HIGHSPEED) && defined(TIVA_I2CSC_PC_OFFSET)
|
||||
/* If the I2C peripheral is High-Speed enabled then choose the highest
|
||||
* speed that is less than or equal to 3.4 Mbps.
|
||||
*/
|
||||
|
||||
regval = tiva_i2c_getreg(priv, TIVA_I2CSC_PC_OFFSET);
|
||||
if ((regval & I2CSC_PC_HS) != 0)
|
||||
{
|
||||
tmp = (2 * 3 * 3400000);
|
||||
regval = (((SYSCLK_FREQUENCY + tmp - 1) / tmp) - 1) << I2CM_TPR_SHIFT;
|
||||
|
||||
tiva_i2c_putreg(priv, TIVA_I2CM_TPR_OFFSET, I2CM_TPR_HS | regval);
|
||||
}
|
||||
#endif
|
||||
|
||||
return frequency;
|
||||
}
|
||||
/************************************************************************************
|
||||
* Name: tiva_i2c_setfrequency
|
||||
*
|
||||
* Description:
|
||||
* Set the I2C frequency
|
||||
*
|
||||
************************************************************************************/
|
||||
/* Save the new I2C frequency */
|
||||
|
||||
static uint32_t tiva_i2c_setfrequency(struct i2c_master_s *dev, uint32_t frequency)
|
||||
{
|
||||
struct tiva_i2c_inst_s *inst = (struct tiva_i2c_inst_s *)dev;
|
||||
struct tiva_i2c_priv_s *priv;
|
||||
|
||||
DEBUGASSERT(inst && inst->priv);
|
||||
priv = inst->priv;
|
||||
|
||||
i2cvdbg("I2C%d: frequency: %u\n", inst->priv->config->devno, frequency);
|
||||
|
||||
/* Get exclusive access to the I2C device */
|
||||
|
||||
tiva_i2c_sem_wait(dev);
|
||||
|
||||
/* Set the clocking for the selected frequency */
|
||||
|
||||
inst->frequency = tiva_i2c_setclock(priv, frequency);
|
||||
|
||||
tiva_i2c_sem_post(dev);
|
||||
return frequency;
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
@@ -1935,9 +1908,14 @@ static int tiva_i2c_process(struct i2c_master_s *dev, struct i2c_msg_s *msgv, in
|
||||
tiva_i2c_tracereset(priv);
|
||||
tiva_i2c_tracenew(priv, 0);
|
||||
|
||||
/* Set I2C clock frequency */
|
||||
/* Set I2C clock frequency
|
||||
*
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
|
||||
tiva_i2c_setclock(priv, inst->frequency);
|
||||
tiva_i2c_setclock(priv, msgs->frequency);
|
||||
|
||||
/* Send the address, then the process moves into the ISR. I2C
|
||||
* interrupts will be enabled within tiva_i2c_waitdone().
|
||||
@@ -2012,7 +1990,7 @@ static int tiva_i2c_process(struct i2c_master_s *dev, struct i2c_msg_s *msgv, in
|
||||
|
||||
/* Reset and reinitialize the I2C hardware */
|
||||
|
||||
tiva_i2c_initialize(priv, inst->frequency);
|
||||
tiva_i2c_initialize(priv, priv->frequency);
|
||||
|
||||
/* Is the busy condition a consequence of some other error? */
|
||||
|
||||
@@ -2032,9 +2010,6 @@ static int tiva_i2c_process(struct i2c_master_s *dev, struct i2c_msg_s *msgv, in
|
||||
|
||||
priv->mcnt = 0;
|
||||
priv->mptr = NULL;
|
||||
|
||||
tiva_i2c_sem_post(dev);
|
||||
|
||||
return -errcode;
|
||||
}
|
||||
|
||||
@@ -2050,13 +2025,15 @@ static int tiva_i2c_transfer(struct i2c_master_s *dev, struct i2c_msg_s *msgv,
|
||||
int msgc)
|
||||
{
|
||||
struct tiva_i2c_inst_s *inst = (struct tiva_i2c_inst_s *)dev;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(inst && inst->priv && inst->priv->config);
|
||||
i2cvdbg("I2C%d: msgc=%d\n", inst->priv->config->devno, msgc);
|
||||
UNUSED(inst);
|
||||
|
||||
tiva_i2c_sem_wait(dev); /* Ensure that address or flags don't change meanwhile */
|
||||
return tiva_i2c_process(dev, msgv, msgc);
|
||||
ret = tiva_i2c_process(dev, msgv, msgc);
|
||||
tiva_i2c_sem_post(dev);
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
@@ -2172,7 +2149,6 @@ struct i2c_master_s *up_i2cinitialize(int port)
|
||||
|
||||
inst->ops = &tiva_i2c_ops;
|
||||
inst->priv = priv;
|
||||
inst->frequency = 100000;
|
||||
|
||||
/* Initialize private data for the first time, increment reference count,
|
||||
* power-up hardware and configure GPIOs.
|
||||
@@ -2360,7 +2336,7 @@ int up_i2creset(struct i2c_master_s *dev)
|
||||
|
||||
/* Re-init the port */
|
||||
|
||||
tiva_i2c_initialize(priv, inst->frequency);
|
||||
tiva_i2c_initialize(priv, priv->frequency);
|
||||
ret = OK;
|
||||
|
||||
out:
|
||||
|
||||
@@ -70,7 +70,6 @@ struct ez80_i2cdev_s
|
||||
{
|
||||
FAR const struct i2c_ops_s *ops; /* I2C vtable */
|
||||
uint32_t frequency; /* Currently selected I2C frequency */
|
||||
uint16_t ccr; /* Clock control register value */
|
||||
uint16_t addr; /* 7- or 10-bit address */
|
||||
uint8_t addr10 : 1; /* 1=Address is 10-bit */
|
||||
};
|
||||
@@ -93,11 +92,11 @@ static int ez80_i2c_read_transfer(FAR struct ez80_i2cdev_s *priv,
|
||||
FAR uint8_t *buffer, int buflen, uint8_t flags);
|
||||
static int ez80_i2c_write_transfer(FAR struct ez80_i2cdev_s *priv,
|
||||
FAR const uint8_t *buffer, int buflen, uint8_t flags);
|
||||
static void ez80_i2c_setfrequency(FAR struct ez80_i2cdev_s *priv,
|
||||
uint32_t frequency);
|
||||
|
||||
/* I2C methods */
|
||||
|
||||
static uint32_t ez80_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int ez80_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
|
||||
@@ -113,13 +112,11 @@ extern uint32_t get_freq(void);
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static uint8_t g_currccr; /* Current setting of I2C CCR register */
|
||||
static bool g_initialized; /* true:I2C has been initialized */
|
||||
static sem_t g_i2csem; /* Serialize I2C transfers */
|
||||
static bool g_initialized; /* true:I2C has been initialized */
|
||||
static sem_t g_i2csem; /* Serialize I2C transfers */
|
||||
|
||||
const struct i2c_ops_s g_ops =
|
||||
{
|
||||
ez80_i2c_setfrequency,
|
||||
ez80_i2c_transfer
|
||||
};
|
||||
|
||||
@@ -172,11 +169,7 @@ static void ez80_i2c_semtake(void)
|
||||
|
||||
static void ez80_i2c_setccr(uint16_t ccr)
|
||||
{
|
||||
if (g_currccr != ccr)
|
||||
{
|
||||
outp(EZ80_I2C_CCR, ccr);
|
||||
g_currccr = ccr;
|
||||
}
|
||||
outp(EZ80_I2C_CCR, ccr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -791,29 +784,26 @@ static int ez80_i2c_write_transfer(FAR struct ez80_i2cdev_s *priv,
|
||||
* frequency - The I2C frequency requested
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns the actual frequency selected
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t ez80_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency)
|
||||
static void ez80_i2c_setfrequency(FAR struct ez80_i2cdev_s *priv,
|
||||
uint32_t frequency)
|
||||
{
|
||||
FAR struct ez80_i2cdev_s *priv = (FAR struct ez80_i2cdev_s *)dev;
|
||||
uint16_t ccr;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
if (priv->frequency != frequency)
|
||||
{
|
||||
/* Calculate and save the BRG (we won't apply it until the first
|
||||
* transfer)
|
||||
*/
|
||||
/* Calculate and save the BRG and set the CCR */
|
||||
|
||||
ccr = ez80_i2c_getccr(frequency);
|
||||
ez80_i2c_setccr(ccr);
|
||||
|
||||
/* Save the new I2C frequency */
|
||||
|
||||
priv->ccr = ez80_i2c_getccr(frequency);
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
|
||||
/* TODO: Calculate and return the actual frequency */
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -853,9 +843,7 @@ static int ez80_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
|
||||
ez80_i2c_semtake();
|
||||
|
||||
/* Set the frequency */
|
||||
|
||||
ez80_i2c_setccr(priv->ccr);
|
||||
/* The process each message seqment */
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
@@ -863,6 +851,8 @@ static int ez80_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
|
||||
/* Set the I2C frequency and address */
|
||||
|
||||
ez80_i2c_setfrequency(priv, msg->frequency);
|
||||
|
||||
priv->addr = msg->addr;
|
||||
priv->addr10 = ((msg->flags & I2C_M_TEN) != 0);
|
||||
|
||||
@@ -975,7 +965,6 @@ FAR struct i2c_master_s *up_i2cinitialize(int port)
|
||||
/* Initialize the allocated instance */
|
||||
|
||||
i2c->ops = &g_ops;
|
||||
i2c->ccr = g_currccr;
|
||||
}
|
||||
|
||||
return (FAR struct i2c_master_s *)i2c;
|
||||
|
||||
+19
-26
@@ -87,11 +87,11 @@ static int z8_i2c_read_transfer(FAR struct z8_i2cdev_s *priv,
|
||||
FAR uint8_t *buffer, int buflen, uint8_t flags);
|
||||
static int z8_i2c_write_transfer(FAR struct z8_i2cdev_s *priv,
|
||||
FAR const uint8_t *buffer, int buflen, uint8_t flags);
|
||||
static void z8_i2c_setfrequency(FAR struct z8_i2cdev_s *priv,
|
||||
uint32_t frequency);
|
||||
|
||||
/* I2C methods */
|
||||
|
||||
static uint32_t z8_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency);
|
||||
static int z8_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
|
||||
@@ -107,13 +107,11 @@ extern uint32_t get_freq(void);
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static uint16_t g_currbrg; /* Current BRG setting */
|
||||
static bool g_initialized; /* true:I2C has been initialized */
|
||||
static sem_t g_i2csem; /* Serialize I2C transfers */
|
||||
static bool g_initialized; /* true:I2C has been initialized */
|
||||
static sem_t g_i2csem; /* Serialize I2C transfers */
|
||||
|
||||
const struct i2c_ops_s g_ops =
|
||||
{
|
||||
z8_i2c_setfrequency,
|
||||
z8_i2c_transfer,
|
||||
};
|
||||
|
||||
@@ -206,12 +204,8 @@ static void z8_i2c_waitrxavail(void)
|
||||
|
||||
static void z8_i2c_setbrg(uint16_t brg)
|
||||
{
|
||||
if (g_currbrg != brg)
|
||||
{
|
||||
I2CBRH = (uint8_t)(brg >> 8);
|
||||
I2CBRL = (uint8_t)(brg & 0xff);
|
||||
g_currbrg = brg;
|
||||
}
|
||||
I2CBRH = (uint8_t)(brg >> 8);
|
||||
I2CBRL = (uint8_t)(brg & 0xff);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -471,16 +465,14 @@ static int z8_i2c_write_transfer(FAR struct z8_i2cdev_s *priv,
|
||||
* frequency - The I2C frequency requested
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns the actual frequency selected
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t z8_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
uint32_t frequency)
|
||||
static void z8_i2c_setfrequency(FAR struct z8_i2cdev_s *priv,
|
||||
uint32_t frequency)
|
||||
{
|
||||
FAR struct z8_i2cdev_s *priv = (FAR struct z8_i2cdev_s *)dev;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
uint16_t brg;
|
||||
|
||||
/* Has the frequency changed? */
|
||||
|
||||
@@ -488,11 +480,13 @@ static uint32_t z8_i2c_setfrequency(FAR struct i2c_master_s *dev,
|
||||
{
|
||||
/* Calculate and save the BRG (we won't apply it until the first transfer) */
|
||||
|
||||
priv->brg = z8_i2c_getbrg(frequency);
|
||||
brg = z8_i2c_getbrg(frequency);
|
||||
z8_i2c_setbrg(brg);
|
||||
|
||||
/* Save the new I2C frequency */
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -532,15 +526,15 @@ static int z8_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
|
||||
z8_i2c_semtake();
|
||||
|
||||
/* Set the frequency */
|
||||
|
||||
z8_i2c_setbrg(priv->brg);
|
||||
/* The process each message seqment */
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
msg = &msgs[i];
|
||||
|
||||
/* Set the I2C address */
|
||||
/* Set the I2C frequency and address */
|
||||
|
||||
z8_i2c_setfrequency(priv, msg->frequency);
|
||||
|
||||
priv->addr = msg->addr;
|
||||
DEBUGASSERT((msg->flags & I2C_M_TEN) == 0);
|
||||
@@ -655,7 +649,6 @@ FAR struct i2c_master_s *up_i2cinitialize(int port)
|
||||
/* Initialize the allocated instance */
|
||||
|
||||
i2c->ops = &g_ops;
|
||||
i2c->brg = g_currbrg;
|
||||
}
|
||||
|
||||
return (FAR struct i2c_master_s *)i2c;
|
||||
|
||||
Reference in New Issue
Block a user