diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-12-26 16:06:40 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-12-26 16:06:40 +0000 |
commit | eaea11230a09375970a10d59137f0af2601f9eb9 (patch) | |
tree | 52e6e5c4ad1e6707a40627f9ee316232c8f0903b /firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c | |
parent | 859ee227ba1d11e3a5080922b322adcc3973e892 (diff) | |
download | rockbox-eaea11230a09375970a10d59137f0af2601f9eb9.tar.gz rockbox-eaea11230a09375970a10d59137f0af2601f9eb9.zip |
imx31: Fix a couple small problems with the i2c driver that went unnoticed until FM. Reset addr_count always and stop resetting module before STOP is actually generated. Simplify a tiny bit and remove inactive preprocessor block.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19596 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c | 57 |
1 files changed, 28 insertions, 29 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c b/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c index ac0934b5f5..bf69afedb7 100644 --- a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c | |||
@@ -85,7 +85,7 @@ static void i2c_interrupt(enum i2c_module_number i2c) | |||
85 | struct i2c_map * const base = desc->base; | 85 | struct i2c_map * const base = desc->base; |
86 | uint16_t i2sr = base->i2sr; | 86 | uint16_t i2sr = base->i2sr; |
87 | 87 | ||
88 | base->i2sr = i2sr & ~I2C_I2SR_IIF; /* Clear IIF */ | 88 | base->i2sr = 0; /* Clear IIF */ |
89 | 89 | ||
90 | if (desc->addr_count >= 0) | 90 | if (desc->addr_count >= 0) |
91 | { | 91 | { |
@@ -116,14 +116,17 @@ static void i2c_interrupt(enum i2c_module_number i2c) | |||
116 | 116 | ||
117 | if (base->i2cr & I2C_I2CR_MTX) | 117 | if (base->i2cr & I2C_I2CR_MTX) |
118 | { | 118 | { |
119 | i2c_transmit: | ||
120 | /* Transmitting data */ | 119 | /* Transmitting data */ |
121 | if ((i2sr & I2C_I2SR_RXAK) == 0 && desc->data_count > 0) | 120 | if ((i2sr & I2C_I2SR_RXAK) == 0) |
122 | { | 121 | { |
123 | /* More bytes to send, got ACK from previous byte */ | 122 | i2c_transmit: |
124 | base->i2dr = *desc->data++; | 123 | if (desc->data_count > 0) |
125 | desc->data_count--; | 124 | { |
126 | return; | 125 | /* More bytes to send, got ACK from previous byte */ |
126 | base->i2dr = *desc->data++; | ||
127 | desc->data_count--; | ||
128 | return; | ||
129 | } | ||
127 | } | 130 | } |
128 | /* else done or no ACK received */ | 131 | /* else done or no ACK received */ |
129 | } | 132 | } |
@@ -184,6 +187,9 @@ static int i2c_transfer(struct i2c_node * const node, | |||
184 | int count = desc->data_count; | 187 | int count = desc->data_count; |
185 | uint16_t i2cr; | 188 | uint16_t i2cr; |
186 | 189 | ||
190 | /* Make sure bus is idle. */ | ||
191 | while (base->i2sr & I2C_I2SR_IBB); | ||
192 | |||
187 | /* Set speed */ | 193 | /* Set speed */ |
188 | base->ifdr = node->ifdr; | 194 | base->ifdr = node->ifdr; |
189 | 195 | ||
@@ -203,17 +209,24 @@ static int i2c_transfer(struct i2c_node * const node, | |||
203 | base->i2cr = i2cr; | 209 | base->i2cr = i2cr; |
204 | 210 | ||
205 | /* Generate START */ | 211 | /* Generate START */ |
206 | base->i2cr |= I2C_I2CR_MSTA; | 212 | base->i2cr = i2cr | I2C_I2CR_MSTA; |
207 | 213 | ||
208 | /* Address slave (first byte sent) and begin session. */ | 214 | /* Address slave (first byte sent) and begin session. */ |
209 | base->i2dr = desc->addr; | 215 | base->i2dr = desc->addr; |
210 | 216 | ||
211 | /* Wait for transfer to complete */ | 217 | /* Wait for transfer to complete */ |
212 | count = (wakeup_wait(&desc->w, HZ) != OBJ_WAIT_SUCCEEDED) ? | 218 | if (wakeup_wait(&desc->w, HZ) == OBJ_WAIT_SUCCEEDED) |
213 | -1 : (count - desc->data_count); | 219 | { |
214 | 220 | count -= desc->data_count; | |
215 | /* Disable module - generate STOP if timeout */ | 221 | } |
216 | base->i2cr = 0; | 222 | else |
223 | { | ||
224 | /* Generate STOP if timeout */ | ||
225 | base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN); | ||
226 | count = -1; | ||
227 | } | ||
228 | |||
229 | desc->addr_count = 0; | ||
217 | 230 | ||
218 | return count; | 231 | return count; |
219 | } | 232 | } |
@@ -242,8 +255,6 @@ int i2c_read(struct i2c_node *node, int reg, | |||
242 | 255 | ||
243 | data_count = i2c_transfer(node, desc); | 256 | data_count = i2c_transfer(node, desc); |
244 | 257 | ||
245 | desc->addr_count = 0; /* To eliminate zeroing elsewhere */ | ||
246 | |||
247 | mutex_unlock(&desc->m); | 258 | mutex_unlock(&desc->m); |
248 | 259 | ||
249 | return data_count; | 260 | return data_count; |
@@ -281,20 +292,6 @@ void i2c_init(void) | |||
281 | desc->base->i2cr = 0; | 292 | desc->base->i2cr = 0; |
282 | imx31_clkctl_module_clock_gating(desc->cg, CGM_OFF); | 293 | imx31_clkctl_module_clock_gating(desc->cg, CGM_OFF); |
283 | } | 294 | } |
284 | |||
285 | #if 0 | ||
286 | /* Pad config set up by OF bootloader doesn't agree with manual but | ||
287 | * TX works at the moment - probably would't do this here either */ | ||
288 | uint32_t reg = SW_PAD_CTL_CSI_PIXCLK_I2C_CLK_I2C_DAT; | ||
289 | reg &= ~0xfffff; | ||
290 | reg |= (1 << 19) | (3 << 17) | (1 << 15) | (1 << 14) | | ||
291 | (1 << 13) | (0 << 11); | ||
292 | |||
293 | reg |= (1 << 9) | (3 << 7) | (1 << 5) | (1 << 4) | | ||
294 | (1 << 3) | (0 << 1); | ||
295 | |||
296 | SW_PAD_CTL_CSI_PIXCLK_I2C_CLK_I2C_DAT = reg; | ||
297 | #endif | ||
298 | } | 295 | } |
299 | 296 | ||
300 | void i2c_enable_node(struct i2c_node *node, bool enable) | 297 | void i2c_enable_node(struct i2c_node *node, bool enable) |
@@ -317,6 +314,8 @@ void i2c_enable_node(struct i2c_node *node, bool enable) | |||
317 | if (desc->enable > 0 && --desc->enable == 0) | 314 | if (desc->enable > 0 && --desc->enable == 0) |
318 | { | 315 | { |
319 | /* Last enable */ | 316 | /* Last enable */ |
317 | while (desc->base->i2sr & I2C_I2SR_IBB); /* Wait for STOP */ | ||
318 | desc->base->i2cr &= ~I2C_I2CR_IEN; | ||
320 | avic_disable_int(desc->ints); | 319 | avic_disable_int(desc->ints); |
321 | imx31_clkctl_module_clock_gating(desc->cg, CGM_OFF); | 320 | imx31_clkctl_module_clock_gating(desc->cg, CGM_OFF); |
322 | } | 321 | } |