summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2007-10-15 16:45:46 +0000
committerJens Arnold <amiconn@rockbox.org>2007-10-15 16:45:46 +0000
commit3a5509a8d7829d731dd2c20a44588b8c15b2a540 (patch)
tree20e6f9e4d78019d5d73c52836d6fd1503f69f3b4
parent52040a05a24bef3889ef01729280416923663697 (diff)
downloadrockbox-3a5509a8d7829d731dd2c20a44588b8c15b2a540.tar.gz
rockbox-3a5509a8d7829d731dd2c20a44588b8c15b2a540.zip
Fix coldfire PCF50606 I2C driver, and iriver FM radio I2C driver. Both drivers had wrong timing, discovered while experimenting with buffered writes.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15122 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/fmradio_i2c.c83
-rw-r--r--firmware/target/coldfire/pcf50606-coldfire.c40
2 files changed, 60 insertions, 63 deletions
diff --git a/firmware/drivers/fmradio_i2c.c b/firmware/drivers/fmradio_i2c.c
index 0a1d0c1fd7..9f890ca34a 100644
--- a/firmware/drivers/fmradio_i2c.c
+++ b/firmware/drivers/fmradio_i2c.c
@@ -49,11 +49,10 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
49#ifdef IRIVER_H300_SERIES 49#ifdef IRIVER_H300_SERIES
50 50
51/* SDA is GPIO57 */ 51/* SDA is GPIO57 */
52#define SDA_LO and_l(~0x02000000, &GPIO1_OUT) 52#define SDA_OUTINIT and_l(~0x02000000, &GPIO1_OUT)
53#define SDA_HI or_l( 0x02000000, &GPIO1_OUT) 53#define SDA_HI_IN and_l(~0x02000000, &GPIO1_ENABLE)
54#define SDA_INPUT and_l(~0x02000000, &GPIO1_ENABLE) 54#define SDA_LO_OUT or_l( 0x02000000, &GPIO1_ENABLE)
55#define SDA_OUTPUT or_l( 0x02000000, &GPIO1_ENABLE) 55#define SDA ( 0x02000000 & GPIO1_READ)
56#define SDA ( 0x02000000 & GPIO1_READ)
57 56
58/* SCL is GPIO56 */ 57/* SCL is GPIO56 */
59#define SCL_INPUT and_l(~0x01000000, &GPIO1_ENABLE) 58#define SCL_INPUT and_l(~0x01000000, &GPIO1_ENABLE)
@@ -65,11 +64,10 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
65#else 64#else
66 65
67/* SDA is GPIO55 */ 66/* SDA is GPIO55 */
68#define SDA_LO and_l(~0x00800000, &GPIO1_OUT) 67#define SDA_OUTINIT and_l(~0x00800000, &GPIO1_OUT)
69#define SDA_HI or_l( 0x00800000, &GPIO1_OUT) 68#define SDA_HI_IN and_l(~0x00800000, &GPIO1_ENABLE)
70#define SDA_INPUT and_l(~0x00800000, &GPIO1_ENABLE) 69#define SDA_LO_OUT or_l( 0x00800000, &GPIO1_ENABLE)
71#define SDA_OUTPUT or_l( 0x00800000, &GPIO1_ENABLE) 70#define SDA ( 0x00800000 & GPIO1_READ)
72#define SDA ( 0x00800000 & GPIO1_READ)
73 71
74/* SCL is GPIO3 */ 72/* SCL is GPIO3 */
75#define SCL_INPUT and_l(~0x00000008, &GPIO_ENABLE) 73#define SCL_INPUT and_l(~0x00000008, &GPIO_ENABLE)
@@ -94,22 +92,23 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
94 92
95static void fmradio_i2c_start(void) 93static void fmradio_i2c_start(void)
96{ 94{
97 SDA_OUTPUT;
98 SCL_OUTPUT;
99 SDA_HI;
100 SCL_HI; 95 SCL_HI;
96 SCL_OUTPUT;
97 SDA_HI_IN;
98 SDA_OUTINIT;
101 DELAY; 99 DELAY;
102 SDA_LO; 100 SDA_LO_OUT;
103 DELAY; 101 DELAY;
104 SCL_LO; 102 SCL_LO;
105} 103}
106 104
107static void fmradio_i2c_stop(void) 105static void fmradio_i2c_stop(void)
108{ 106{
109 SDA_LO; 107 SDA_LO_OUT;
108 DELAY;
110 SCL_HI; 109 SCL_HI;
111 DELAY; 110 DELAY;
112 SDA_HI; 111 SDA_HI_IN;
113} 112}
114 113
115/* Generate ACK or NACK */ 114/* Generate ACK or NACK */
@@ -123,23 +122,21 @@ static void fmradio_i2c_ack(bool nack)
123 In their infinite wisdom, iriver didn't pull up the SCL line, so 122 In their infinite wisdom, iriver didn't pull up the SCL line, so
124 we have to drive the SCL high repeatedly to simulate a pullup. */ 123 we have to drive the SCL high repeatedly to simulate a pullup. */
125 124
126 SCL_LO; /* Set the clock low */
127
128 if (nack) 125 if (nack)
129 SDA_HI; 126 SDA_HI_IN;
130 else 127 else
131 SDA_LO; 128 SDA_LO_OUT;
132 129 DELAY;
133 SCL_INPUT; /* Set the clock to input */ 130
134 while(!SCL) /* and wait for the slave to release it */ 131 SCL_HI;
132 do
135 { 133 {
136 SCL_HI;
137 SCL_OUTPUT; /* Set the clock to output */ 134 SCL_OUTPUT; /* Set the clock to output */
138 SCL_INPUT; /* Set the clock to input */ 135 SCL_INPUT; /* Set the clock to input */
139 DELAY; 136 DELAY;
140 } 137 }
138 while(!SCL); /* and wait for the slave to release it */
141 139
142 DELAY;
143 SCL_OUTPUT; 140 SCL_OUTPUT;
144 SCL_LO; 141 SCL_LO;
145} 142}
@@ -156,24 +153,23 @@ static int fmradio_i2c_getack(void)
156 In their infinite wisdom, iriver didn't pull up the SCL line, so 153 In their infinite wisdom, iriver didn't pull up the SCL line, so
157 we have to drive the SCL high repeatedly to simulate a pullup. */ 154 we have to drive the SCL high repeatedly to simulate a pullup. */
158 155
159 SDA_INPUT; /* And set to input */ 156 SDA_HI_IN;
160 SCL_INPUT; /* Set the clock to input */ 157 DELAY;
161 while(!SCL) /* and wait for the slave to release it */ 158
159 SCL_HI; /* set clock to high */
160 do
162 { 161 {
163 SCL_HI;
164 SCL_OUTPUT; /* Set the clock to output */ 162 SCL_OUTPUT; /* Set the clock to output */
165 SCL_INPUT; /* Set the clock to input */ 163 SCL_INPUT; /* Set the clock to input */
166 DELAY; 164 DELAY;
167 } 165 }
166 while(!SCL); /* and wait for the slave to release it */
168 167
169 if (SDA) 168 if (SDA)
170 /* ack failed */ 169 ret = 0; /* ack failed */
171 ret = 0;
172 170
173 SCL_OUTPUT; 171 SCL_OUTPUT;
174 SCL_LO; 172 SCL_LO;
175 SDA_HI;
176 SDA_OUTPUT;
177 173
178 return ret; 174 return ret;
179} 175}
@@ -185,20 +181,14 @@ static void fmradio_i2c_outb(unsigned char byte)
185 /* clock out each bit, MSB first */ 181 /* clock out each bit, MSB first */
186 for ( i=0x80; i; i>>=1 ) { 182 for ( i=0x80; i; i>>=1 ) {
187 if ( i & byte ) 183 if ( i & byte )
188 { 184 SDA_HI_IN;
189 SDA_HI;
190 }
191 else 185 else
192 { 186 SDA_LO_OUT;
193 SDA_LO;
194 }
195 DELAY; 187 DELAY;
196 SCL_HI; 188 SCL_HI;
197 DELAY; 189 DELAY;
198 SCL_LO; 190 SCL_LO;
199 } 191 }
200
201 SDA_HI;
202} 192}
203 193
204static unsigned char fmradio_i2c_inb(void) 194static unsigned char fmradio_i2c_inb(void)
@@ -206,18 +196,15 @@ static unsigned char fmradio_i2c_inb(void)
206 int i; 196 int i;
207 unsigned char byte = 0; 197 unsigned char byte = 0;
208 198
199 SDA_HI_IN;
209 /* clock in each bit, MSB first */ 200 /* clock in each bit, MSB first */
210 for ( i=0x80; i; i>>=1 ) { 201 for ( i=0x80; i; i>>=1 ) {
211 SDA_INPUT; /* And set to input */
212 DELAY; 202 DELAY;
203 SCL_HI;
213 DELAY; 204 DELAY;
214 if ( SDA ) 205 if ( SDA )
215 byte |= i; 206 byte |= i;
216 SCL_HI;
217 DELAY;
218 SCL_LO; 207 SCL_LO;
219 DELAY;
220 SDA_OUTPUT;
221 } 208 }
222 209
223 return byte; 210 return byte;
@@ -278,14 +265,14 @@ int fmradio_i2c_read(int address, unsigned char* buf, int count)
278#define SDA_HI or_b(0x10, &PBDRL) 265#define SDA_HI or_b(0x10, &PBDRL)
279#define SDA_INPUT and_b(~0x10, &PBIORL) 266#define SDA_INPUT and_b(~0x10, &PBIORL)
280#define SDA_OUTPUT or_b(0x10, &PBIORL) 267#define SDA_OUTPUT or_b(0x10, &PBIORL)
281#define SDA (PBDR & 0x0010) 268#define SDA (PBDR & 0x0010)
282 269
283/* SCL is PB1 */ 270/* SCL is PB1 */
284#define SCL_INPUT and_b(~0x02, &PBIORL) 271#define SCL_INPUT and_b(~0x02, &PBIORL)
285#define SCL_OUTPUT or_b(0x02, &PBIORL) 272#define SCL_OUTPUT or_b(0x02, &PBIORL)
286#define SCL_LO and_b(~0x02, &PBDRL) 273#define SCL_LO and_b(~0x02, &PBDRL)
287#define SCL_HI or_b(0x02, &PBDRL) 274#define SCL_HI or_b(0x02, &PBDRL)
288#define SCL (PBDR & 0x0002) 275#define SCL (PBDR & 0x0002)
289 276
290/* arbitrary delay loop */ 277/* arbitrary delay loop */
291#define DELAY do { int _x; for(_x=0;_x<20;_x++);} while (0) 278#define DELAY do { int _x; for(_x=0;_x<20;_x++);} while (0)
diff --git a/firmware/target/coldfire/pcf50606-coldfire.c b/firmware/target/coldfire/pcf50606-coldfire.c
index d777b41cb1..d57b249f0d 100644
--- a/firmware/target/coldfire/pcf50606-coldfire.c
+++ b/firmware/target/coldfire/pcf50606-coldfire.c
@@ -140,6 +140,11 @@ inline void pcf50606_i2c_stop(void)
140 asm ( 140 asm (
141 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */ 141 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
142 142
143 "move.l %[dly],%%d0 \n" /* DELAY */
144 "1: \n"
145 "subq.l #1,%%d0 \n"
146 "bhi.s 1b \n"
147
143 "not.l %[sclb] \n" /* SCL_HI_IN */ 148 "not.l %[sclb] \n" /* SCL_HI_IN */
144 "and.l %[sclb],(8,%[sclrd]) \n" 149 "and.l %[sclb],(8,%[sclrd]) \n"
145 "not.l %[sclb] \n" 150 "not.l %[sclb] \n"
@@ -169,6 +174,7 @@ inline void pcf50606_i2c_stop(void)
169 ); 174 );
170#else 175#else
171 SDA_LO_OUT; 176 SDA_LO_OUT;
177 DELAY;
172 SCL_HI_IN; 178 SCL_HI_IN;
173 DELAY; 179 DELAY;
174 SDA_HI_IN; 180 SDA_HI_IN;
@@ -189,6 +195,11 @@ inline void pcf50606_i2c_ack(bool ack)
189 "1: \n" 195 "1: \n"
190 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */ 196 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
191 197
198 "move.l %[dly],%%d0 \n" /* DELAY */
199 "1: \n"
200 "subq.l #1,%%d0 \n"
201 "bhi.s 1b \n"
202
192 "not.l %[sclb] \n" /* SCL_HI_IN */ 203 "not.l %[sclb] \n" /* SCL_HI_IN */
193 "and.l %[sclb],(8,%[sclrd]) \n" 204 "and.l %[sclb],(8,%[sclrd]) \n"
194 "not.l %[sclb] \n" 205 "not.l %[sclb] \n"
@@ -220,9 +231,8 @@ inline void pcf50606_i2c_ack(bool ack)
220 SDA_LO_OUT; 231 SDA_LO_OUT;
221 else 232 else
222 SDA_HI_IN; 233 SDA_HI_IN;
223 234 DELAY;
224 SCL_HI_IN; 235 SCL_HI_IN;
225
226 DELAY; 236 DELAY;
227 SCL_LO_OUT; 237 SCL_LO_OUT;
228#endif 238#endif
@@ -251,16 +261,16 @@ inline bool pcf50606_i2c_getack(void)
251 "btst.l %[sclbnum],%%d0 \n" 261 "btst.l %[sclbnum],%%d0 \n"
252 "beq.s 1b \n" 262 "beq.s 1b \n"
253 263
264 "move.l %[dly],%%d0 \n" /* DELAY */
265 "1: \n"
266 "subq.l #1,%%d0 \n"
267 "bhi.s 1b \n"
268
254 "move.l (%[sdard]),%%d0 \n" /* ret = !SDA */ 269 "move.l (%[sdard]),%%d0 \n" /* ret = !SDA */
255 "btst.l %[sdabnum],%%d0 \n" 270 "btst.l %[sdabnum],%%d0 \n"
256 "seq.b %[ret] \n" 271 "seq.b %[ret] \n"
257 272
258 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */ 273 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
259
260 "move.l %[dly],%%d0 \n" /* DELAY */
261 "1: \n"
262 "subq.l #1,%%d0 \n"
263 "bhi.s 1b \n"
264 : /* outputs */ 274 : /* outputs */
265 [ret] "=&d"(ret) 275 [ret] "=&d"(ret)
266 : /* inputs */ 276 : /* inputs */
@@ -278,11 +288,11 @@ inline bool pcf50606_i2c_getack(void)
278 SDA_HI_IN; 288 SDA_HI_IN;
279 DELAY; 289 DELAY;
280 SCL_HI_IN; 290 SCL_HI_IN;
291 DELAY;
281 292
282 ret = !SDA; 293 ret = !SDA;
283 294
284 SCL_LO_OUT; 295 SCL_LO_OUT;
285 DELAY;
286#endif 296#endif
287 return ret; 297 return ret;
288} 298}
@@ -372,6 +382,11 @@ unsigned char pcf50606_i2c_inb(bool ack)
372 "clr.l %[byte] \n" /* byte = 0 */ 382 "clr.l %[byte] \n" /* byte = 0 */
373 383
374 "2: \n" /* do */ 384 "2: \n" /* do */
385 "move.l %[dly],%%d0 \n" /* DELAY */
386 "1: \n"
387 "subq.l #1,%%d0 \n"
388 "bhi.s 1b \n"
389
375 "not.l %[sclb] \n" /* SCL_HI_IN */ 390 "not.l %[sclb] \n" /* SCL_HI_IN */
376 "and.l %[sclb],(8,%[sclrd]) \n" 391 "and.l %[sclb],(8,%[sclrd]) \n"
377 "not.l %[sclb] \n" 392 "not.l %[sclb] \n"
@@ -394,11 +409,6 @@ unsigned char pcf50606_i2c_inb(bool ack)
394 409
395 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */ 410 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
396 411
397 "move.l %[dly],%%d0 \n" /* DELAY */
398 "1: \n"
399 "subq.l #1,%%d0 \n"
400 "bhi.s 1b \n"
401
402 "subq.l #1,%%d1 \n" /* i-- */ 412 "subq.l #1,%%d1 \n" /* i-- */
403 "bne.s 2b \n" /* while (i != 0) */ 413 "bne.s 2b \n" /* while (i != 0) */
404 : /* outputs */ 414 : /* outputs */
@@ -421,12 +431,12 @@ unsigned char pcf50606_i2c_inb(bool ack)
421 SDA_HI_IN; 431 SDA_HI_IN;
422 for ( i=0x80; i; i>>=1 ) 432 for ( i=0x80; i; i>>=1 )
423 { 433 {
434 DELAY;
424 SCL_HI_IN; 435 SCL_HI_IN;
425 DELAY; 436 DELAY;
426 if ( SDA ) 437 if ( SDA )
427 byte |= i; 438 byte |= i;
428 SCL_LO_OUT; 439 SCL_LO_OUT;
429 DELAY;
430 } 440 }
431#endif 441#endif
432 442