diff options
-rw-r--r-- | firmware/target/arm/imx233/i2c-imx233.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/firmware/target/arm/imx233/i2c-imx233.c b/firmware/target/arm/imx233/i2c-imx233.c index ee5ac1ccf6..f99cd97282 100644 --- a/firmware/target/arm/imx233/i2c-imx233.c +++ b/firmware/target/arm/imx233/i2c-imx233.c | |||
@@ -80,12 +80,18 @@ void INT_I2C_DMA(void) | |||
80 | semaphore_release(&i2c_sema); | 80 | semaphore_release(&i2c_sema); |
81 | } | 81 | } |
82 | 82 | ||
83 | void imx233_i2c_init(void) | 83 | void INT_I2C_ERROR(void) |
84 | { | ||
85 | /* reset dma channel on error */ | ||
86 | if(imx233_dma_is_channel_error_irq(APB_I2C)) | ||
87 | imx233_dma_reset_channel(APB_I2C); | ||
88 | /* clear irq flags */ | ||
89 | imx233_dma_clear_channel_interrupt(APB_I2C); | ||
90 | semaphore_release(&i2c_sema); | ||
91 | } | ||
92 | |||
93 | static void imx233_i2c_reset(void) | ||
84 | { | 94 | { |
85 | BF_SET(I2C_CTRL0, SFTRST); | ||
86 | /* setup pins (must be done when shutdown) */ | ||
87 | imx233_pinctrl_setup_vpin(VPIN_I2C_SCL, "i2c scl", PINCTRL_DRIVE_4mA, true); | ||
88 | imx233_pinctrl_setup_vpin(VPIN_I2C_SDA, "i2c sda", PINCTRL_DRIVE_4mA, true); | ||
89 | /* clear softreset */ | 95 | /* clear softreset */ |
90 | imx233_reset_block(&HW_I2C_CTRL0); | 96 | imx233_reset_block(&HW_I2C_CTRL0); |
91 | /* Errata (imx233): | 97 | /* Errata (imx233): |
@@ -103,7 +109,15 @@ void imx233_i2c_init(void) | |||
103 | HW_I2C_TIMING0 = 0x000F0007; /* tHIGH=0.6us, read at 0.3us */ | 109 | HW_I2C_TIMING0 = 0x000F0007; /* tHIGH=0.6us, read at 0.3us */ |
104 | HW_I2C_TIMING1 = 0x001F000F; /* tLOW=1.3us, write at 0.6us */ | 110 | HW_I2C_TIMING1 = 0x001F000F; /* tLOW=1.3us, write at 0.6us */ |
105 | HW_I2C_TIMING2 = 0x0015000D; | 111 | HW_I2C_TIMING2 = 0x0015000D; |
106 | 112 | } | |
113 | |||
114 | void imx233_i2c_init(void) | ||
115 | { | ||
116 | BF_SET(I2C_CTRL0, SFTRST); | ||
117 | /* setup pins (must be done when shutdown) */ | ||
118 | imx233_pinctrl_setup_vpin(VPIN_I2C_SCL, "i2c scl", PINCTRL_DRIVE_4mA, true); | ||
119 | imx233_pinctrl_setup_vpin(VPIN_I2C_SDA, "i2c sda", PINCTRL_DRIVE_4mA, true); | ||
120 | imx233_i2c_reset(); | ||
107 | mutex_init(&i2c_mutex); | 121 | mutex_init(&i2c_mutex); |
108 | semaphore_init(&i2c_sema, 1, 0); | 122 | semaphore_init(&i2c_sema, 1, 0); |
109 | } | 123 | } |
@@ -183,6 +197,7 @@ enum imx233_i2c_error_t imx233_i2c_end(unsigned timeout) | |||
183 | BF_CLR(I2C_CTRL1, ALL_IRQ); | 197 | BF_CLR(I2C_CTRL1, ALL_IRQ); |
184 | imx233_dma_reset_channel(APB_I2C); | 198 | imx233_dma_reset_channel(APB_I2C); |
185 | imx233_icoll_enable_interrupt(INT_SRC_I2C_DMA, true); | 199 | imx233_icoll_enable_interrupt(INT_SRC_I2C_DMA, true); |
200 | imx233_icoll_enable_interrupt(INT_SRC_I2C_ERROR, true); | ||
186 | imx233_dma_enable_channel_interrupt(APB_I2C, true); | 201 | imx233_dma_enable_channel_interrupt(APB_I2C, true); |
187 | imx233_dma_start_command(APB_I2C, &i2c_stage[0].dma); | 202 | imx233_dma_start_command(APB_I2C, &i2c_stage[0].dma); |
188 | 203 | ||
@@ -195,7 +210,13 @@ enum imx233_i2c_error_t imx233_i2c_end(unsigned timeout) | |||
195 | else if(BF_RD(I2C_CTRL1, MASTER_LOSS_IRQ)) | 210 | else if(BF_RD(I2C_CTRL1, MASTER_LOSS_IRQ)) |
196 | ret = I2C_MASTER_LOSS; | 211 | ret = I2C_MASTER_LOSS; |
197 | else if(BF_RD(I2C_CTRL1, NO_SLAVE_ACK_IRQ)) | 212 | else if(BF_RD(I2C_CTRL1, NO_SLAVE_ACK_IRQ)) |
213 | { | ||
214 | /* the core doesn't like this error, this is a workaround to prevent lock up */ | ||
215 | BF_SET(I2C_CTRL1, CLR_GOT_A_NAK); | ||
216 | imx233_dma_reset_channel(APB_I2C); | ||
217 | imx233_i2c_reset(); | ||
198 | ret= I2C_NO_SLAVE_ACK; | 218 | ret= I2C_NO_SLAVE_ACK; |
219 | } | ||
199 | else if(BF_RD(I2C_CTRL1, EARLY_TERM_IRQ)) | 220 | else if(BF_RD(I2C_CTRL1, EARLY_TERM_IRQ)) |
200 | ret = I2C_SLAVE_NAK; | 221 | ret = I2C_SLAVE_NAK; |
201 | else | 222 | else |