I2C: Remove the setfrequency method from the interface

This commit is contained in:
Gregory Nutt
2016-02-01 16:30:29 -06:00
parent bec6f373a7
commit 0693e76be8
15 changed files with 777 additions and 920 deletions
+45 -55
View File
@@ -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:
+66 -59
View File
@@ -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
+57 -50
View File
@@ -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
+57 -50
View File
@@ -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
+49 -41
View File
@@ -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;
}
+63 -48
View File
@@ -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 */
}
+54 -81
View File
@@ -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);
}
/****************************************************************************
+43 -76
View File
@@ -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 */
+43 -76
View File
@@ -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 */
+76 -90
View File
@@ -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.
+76 -90
View File
@@ -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.
+68 -82
View File
@@ -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.
+43 -67
View File
@@ -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:
+18 -29
View File
@@ -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
View File
@@ -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;