summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-12-26 16:06:40 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-12-26 16:06:40 +0000
commiteaea11230a09375970a10d59137f0af2601f9eb9 (patch)
tree52e6e5c4ad1e6707a40627f9ee316232c8f0903b
parent859ee227ba1d11e3a5080922b322adcc3973e892 (diff)
downloadrockbox-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
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c57
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 {
119i2c_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 */ 122i2c_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
300void i2c_enable_node(struct i2c_node *node, bool enable) 297void 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 }