mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-09 21:22:39 -05:00
imx233: fix i2c issues
The i2c core has some bugs: it locks up when the slave doesn't NAK and prevent the dma channel from being resetted. Specifically handle this situation by setting CLR_GOT_A_NAK (workaround) and then reset dma and i2c block. Change-Id: I0e09d38d4301a0ad42dfad785cc934b43f2c4485
This commit is contained in:
parent
f40b15d0cb
commit
164876eaf1
1 changed files with 27 additions and 6 deletions
|
|
@ -80,12 +80,18 @@ void INT_I2C_DMA(void)
|
||||||
semaphore_release(&i2c_sema);
|
semaphore_release(&i2c_sema);
|
||||||
}
|
}
|
||||||
|
|
||||||
void imx233_i2c_init(void)
|
void INT_I2C_ERROR(void)
|
||||||
|
{
|
||||||
|
/* reset dma channel on error */
|
||||||
|
if(imx233_dma_is_channel_error_irq(APB_I2C))
|
||||||
|
imx233_dma_reset_channel(APB_I2C);
|
||||||
|
/* clear irq flags */
|
||||||
|
imx233_dma_clear_channel_interrupt(APB_I2C);
|
||||||
|
semaphore_release(&i2c_sema);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void imx233_i2c_reset(void)
|
||||||
{
|
{
|
||||||
BF_SET(I2C_CTRL0, SFTRST);
|
|
||||||
/* setup pins (must be done when shutdown) */
|
|
||||||
imx233_pinctrl_setup_vpin(VPIN_I2C_SCL, "i2c scl", PINCTRL_DRIVE_4mA, true);
|
|
||||||
imx233_pinctrl_setup_vpin(VPIN_I2C_SDA, "i2c sda", PINCTRL_DRIVE_4mA, true);
|
|
||||||
/* clear softreset */
|
/* clear softreset */
|
||||||
imx233_reset_block(&HW_I2C_CTRL0);
|
imx233_reset_block(&HW_I2C_CTRL0);
|
||||||
/* Errata (imx233):
|
/* Errata (imx233):
|
||||||
|
|
@ -103,7 +109,15 @@ void imx233_i2c_init(void)
|
||||||
HW_I2C_TIMING0 = 0x000F0007; /* tHIGH=0.6us, read at 0.3us */
|
HW_I2C_TIMING0 = 0x000F0007; /* tHIGH=0.6us, read at 0.3us */
|
||||||
HW_I2C_TIMING1 = 0x001F000F; /* tLOW=1.3us, write at 0.6us */
|
HW_I2C_TIMING1 = 0x001F000F; /* tLOW=1.3us, write at 0.6us */
|
||||||
HW_I2C_TIMING2 = 0x0015000D;
|
HW_I2C_TIMING2 = 0x0015000D;
|
||||||
|
}
|
||||||
|
|
||||||
|
void imx233_i2c_init(void)
|
||||||
|
{
|
||||||
|
BF_SET(I2C_CTRL0, SFTRST);
|
||||||
|
/* setup pins (must be done when shutdown) */
|
||||||
|
imx233_pinctrl_setup_vpin(VPIN_I2C_SCL, "i2c scl", PINCTRL_DRIVE_4mA, true);
|
||||||
|
imx233_pinctrl_setup_vpin(VPIN_I2C_SDA, "i2c sda", PINCTRL_DRIVE_4mA, true);
|
||||||
|
imx233_i2c_reset();
|
||||||
mutex_init(&i2c_mutex);
|
mutex_init(&i2c_mutex);
|
||||||
semaphore_init(&i2c_sema, 1, 0);
|
semaphore_init(&i2c_sema, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -183,6 +197,7 @@ enum imx233_i2c_error_t imx233_i2c_end(unsigned timeout)
|
||||||
BF_CLR(I2C_CTRL1, ALL_IRQ);
|
BF_CLR(I2C_CTRL1, ALL_IRQ);
|
||||||
imx233_dma_reset_channel(APB_I2C);
|
imx233_dma_reset_channel(APB_I2C);
|
||||||
imx233_icoll_enable_interrupt(INT_SRC_I2C_DMA, true);
|
imx233_icoll_enable_interrupt(INT_SRC_I2C_DMA, true);
|
||||||
|
imx233_icoll_enable_interrupt(INT_SRC_I2C_ERROR, true);
|
||||||
imx233_dma_enable_channel_interrupt(APB_I2C, true);
|
imx233_dma_enable_channel_interrupt(APB_I2C, true);
|
||||||
imx233_dma_start_command(APB_I2C, &i2c_stage[0].dma);
|
imx233_dma_start_command(APB_I2C, &i2c_stage[0].dma);
|
||||||
|
|
||||||
|
|
@ -195,7 +210,13 @@ enum imx233_i2c_error_t imx233_i2c_end(unsigned timeout)
|
||||||
else if(BF_RD(I2C_CTRL1, MASTER_LOSS_IRQ))
|
else if(BF_RD(I2C_CTRL1, MASTER_LOSS_IRQ))
|
||||||
ret = I2C_MASTER_LOSS;
|
ret = I2C_MASTER_LOSS;
|
||||||
else if(BF_RD(I2C_CTRL1, NO_SLAVE_ACK_IRQ))
|
else if(BF_RD(I2C_CTRL1, NO_SLAVE_ACK_IRQ))
|
||||||
|
{
|
||||||
|
/* the core doesn't like this error, this is a workaround to prevent lock up */
|
||||||
|
BF_SET(I2C_CTRL1, CLR_GOT_A_NAK);
|
||||||
|
imx233_dma_reset_channel(APB_I2C);
|
||||||
|
imx233_i2c_reset();
|
||||||
ret= I2C_NO_SLAVE_ACK;
|
ret= I2C_NO_SLAVE_ACK;
|
||||||
|
}
|
||||||
else if(BF_RD(I2C_CTRL1, EARLY_TERM_IRQ))
|
else if(BF_RD(I2C_CTRL1, EARLY_TERM_IRQ))
|
||||||
ret = I2C_SLAVE_NAK;
|
ret = I2C_SLAVE_NAK;
|
||||||
else
|
else
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue