Initial maemo platform support
[maemo-rb.git] / firmware / target / coldfire / pcf50606-coldfire.c
blob6206ae4debc563f036eff17a8234c2a576f71d08
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h"
22 #include "system.h"
23 #include "logf.h"
24 #include "kernel.h"
25 #include "pcf50606.h"
27 #define USE_ASM
29 /* Define the approprate bits for SDA and SCL being the only difference in
30 config between each player. */
31 #if defined(IRIVER_H300_SERIES)
32 #define SDA_BITNUM 13 /* LRCK3/GPIO45 */
33 #define SCL_BITNUM 12 /* SWE/GPIO12 */
34 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
35 #define SDA_BITNUM 12 /* SDA1/RXD1/GPIO44 */
36 #define SCL_BITNUM 10 /* SCL1/TXD1/GPIO10 */
37 #endif
39 /* Data */
40 #define SDA_GPIO_READ GPIO1_READ /* MBAR2 + 0x0b0 */
41 #define SDA_GPIO_OUT GPIO1_OUT /* MBAR2 + 0x0b4 */
42 #define SDA_GPIO_ENABLE GPIO1_ENABLE /* MBAR2 + 0x0b8 */
43 #define SDA_GPIO_FUNCTION GPIO1_FUNCTION /* MBAR2 + 0x0bc */
45 /* Clock */
46 #define SCL_GPIO_READ GPIO_READ /* MBAR2 + 0x000 */
47 #define SCL_GPIO_OUT GPIO_OUT /* MBAR2 + 0x004 */
48 #define SCL_GPIO_ENABLE GPIO_ENABLE /* MBAR2 + 0x008 */
49 #define SCL_GPIO_FUNCTION GPIO_FUNCTION /* MBAR2 + 0x00c */
51 #define PCF50606_ADDR 0x10
52 #define SCL_BIT (1ul << SCL_BITNUM)
53 #define SDA_BIT (1ul << SDA_BITNUM)
55 #define SDA ( SDA_BIT & SDA_GPIO_READ)
56 #define SDA_LO_OUT or_l( SDA_BIT, &SDA_GPIO_ENABLE)
57 #define SDA_HI_IN and_l(~SDA_BIT, &SDA_GPIO_ENABLE)
59 #define SCL ( SCL_BIT & SCL_GPIO_READ)
60 #define SCL_LO_OUT or_l( SCL_BIT, &SCL_GPIO_ENABLE)
61 #define SCL_HI_IN and_l(~SCL_BIT, &SCL_GPIO_ENABLE); while(!SCL);
63 #define DELAY \
64 asm volatile ( \
65 "move.l %[dly],%%d0 \n" \
66 "1: \n" \
67 "subq.l #1,%%d0 \n" \
68 "bhi.s 1b \n" \
69 : : [dly]"d"(i2c_delay) : "d0" );
71 void pcf50606_i2c_init(void)
73 /* Bit banged I2C */
74 or_l(SDA_BIT, &SDA_GPIO_FUNCTION);
75 or_l(SCL_BIT, &SCL_GPIO_FUNCTION);
76 and_l(~SDA_BIT, &SDA_GPIO_OUT);
77 and_l(~SCL_BIT, &SCL_GPIO_OUT);
78 and_l(~SDA_BIT, &SDA_GPIO_ENABLE);
79 and_l(~SCL_BIT, &SCL_GPIO_ENABLE);
82 static int i2c_delay IDATA_ATTR = 44;
84 void pcf50606_i2c_recalc_delay(int cpu_clock)
86 i2c_delay = MAX(cpu_clock / (400000*2*3) - 7, 1);
89 inline void pcf50606_i2c_start(void)
91 #ifdef USE_ASM
92 asm volatile (
93 "not.l %[sdab] \n" /* SDA_HI_IN */
94 "and.l %[sdab],(8,%[sdard]) \n"
95 "not.l %[sdab] \n"
97 "not.l %[sclb] \n" /* SCL_HI_IN */
98 "and.l %[sclb],(8,%[sclrd]) \n"
99 "not.l %[sclb] \n"
100 "1: \n"
101 "move.l (%[sclrd]),%%d0 \n"
102 "btst.l %[sclbnum], %%d0 \n"
103 "beq.s 1b \n"
105 "move.l %[dly],%%d0 \n" /* DELAY */
106 "1: \n"
107 "subq.l #1,%%d0 \n"
108 "bhi.s 1b \n"
110 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
112 "move.l %[dly],%%d0 \n" /* DELAY */
113 "1: \n"
114 "subq.l #1,%%d0 \n"
115 "bhi.s 1b \n"
117 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
118 : /* outputs */
119 : /* inputs */
120 [sclrd] "a"(&SCL_GPIO_READ),
121 [sclb] "d"(SCL_BIT),
122 [sclbnum] "i"(SCL_BITNUM),
123 [sdard] "a"(&SDA_GPIO_READ),
124 [sdab] "d"(SDA_BIT),
125 [dly] "d"(i2c_delay)
126 : /* clobbers */
127 "d0"
129 #else
130 SDA_HI_IN;
131 SCL_HI_IN;
132 DELAY;
133 SDA_LO_OUT;
134 DELAY;
135 SCL_LO_OUT;
136 #endif
139 inline void pcf50606_i2c_stop(void)
141 #ifdef USE_ASM
142 asm volatile (
143 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
145 "move.l %[dly],%%d0 \n" /* DELAY */
146 "1: \n"
147 "subq.l #1,%%d0 \n"
148 "bhi.s 1b \n"
150 "not.l %[sclb] \n" /* SCL_HI_IN */
151 "and.l %[sclb],(8,%[sclrd]) \n"
152 "not.l %[sclb] \n"
153 "1: \n"
154 "move.l (%[sclrd]),%%d0 \n"
155 "btst.l %[sclbnum],%%d0 \n"
156 "beq.s 1b \n"
158 "move.l %[dly],%%d0 \n" /* DELAY */
159 "1: \n"
160 "subq.l #1,%%d0 \n"
161 "bhi.s 1b \n"
163 "not.l %[sdab] \n" /* SDA_HI_IN */
164 "and.l %[sdab],(8,%[sdard]) \n"
165 "not.l %[sdab] \n"
166 : /* outputs */
167 : /* inputs */
168 [sclrd] "a"(&SCL_GPIO_READ),
169 [sclb] "d"(SCL_BIT),
170 [sclbnum] "i"(SCL_BITNUM),
171 [sdard] "a"(&SDA_GPIO_READ),
172 [sdab] "d"(SDA_BIT),
173 [dly] "d"(i2c_delay)
174 : /* clobbers */
175 "d0"
177 #else
178 SDA_LO_OUT;
179 DELAY;
180 SCL_HI_IN;
181 DELAY;
182 SDA_HI_IN;
183 #endif
186 inline void pcf50606_i2c_ack(bool ack)
188 #ifdef USE_ASM
189 asm volatile (
190 "tst.b %[ack] \n" /* if (!ack) */
191 "bne.s 1f \n"
193 "not.l %[sdab] \n" /* SDA_HI_IN */
194 "and.l %[sdab],(8,%[sdard]) \n"
195 "not.l %[sdab] \n"
196 ".word 0x51fb \n" /* trapf.l : else */
197 "1: \n"
198 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
200 "move.l %[dly],%%d0 \n" /* DELAY */
201 "1: \n"
202 "subq.l #1,%%d0 \n"
203 "bhi.s 1b \n"
205 "not.l %[sclb] \n" /* SCL_HI_IN */
206 "and.l %[sclb],(8,%[sclrd]) \n"
207 "not.l %[sclb] \n"
208 "1: \n"
209 "move.l (%[sclrd]),%%d0 \n"
210 "btst.l %[sclbnum],%%d0 \n"
211 "beq.s 1b \n"
213 "move.l %[dly],%%d0 \n" /* DELAY */
214 "1: \n"
215 "subq.l #1,%%d0 \n"
216 "bhi.s 1b \n"
218 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
219 : /* outputs */
220 : /* inputs */
221 [sclrd] "a"(&SCL_GPIO_READ),
222 [sclb] "d"(SCL_BIT),
223 [sclbnum] "i"(SCL_BITNUM),
224 [sdard] "a"(&SDA_GPIO_READ),
225 [sdab] "d"(SDA_BIT),
226 [dly] "d"(i2c_delay),
227 [ack] "d"(ack)
228 : /* clobbers */
229 "d0"
231 #else
232 if(ack)
233 SDA_LO_OUT;
234 else
235 SDA_HI_IN;
236 DELAY;
237 SCL_HI_IN;
238 DELAY;
239 SCL_LO_OUT;
240 #endif
243 inline bool pcf50606_i2c_getack(void)
245 bool ret;
247 #ifdef USE_ASM
248 asm volatile (
249 "not.l %[sdab] \n" /* SDA_HI_IN */
250 "and.l %[sdab],(8,%[sdard]) \n"
251 "not.l %[sdab] \n"
253 "move.l %[dly],%%d0 \n" /* DELAY */
254 "1: \n"
255 "subq.l #1,%%d0 \n"
256 "bhi.s 1b \n"
258 "not.l %[sclb] \n" /* SCL_HI_IN */
259 "and.l %[sclb],(8,%[sclrd]) \n"
260 "not.l %[sclb] \n"
261 "1: \n"
262 "move.l (%[sclrd]),%%d0 \n"
263 "btst.l %[sclbnum],%%d0 \n"
264 "beq.s 1b \n"
266 "move.l %[dly],%%d0 \n" /* DELAY */
267 "1: \n"
268 "subq.l #1,%%d0 \n"
269 "bhi.s 1b \n"
271 "move.l (%[sdard]),%%d0 \n" /* ret = !SDA */
272 "btst.l %[sdabnum],%%d0 \n"
273 "seq.b %[ret] \n"
275 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
276 : /* outputs */
277 [ret] "=&d"(ret)
278 : /* inputs */
279 [sclrd] "a"(&SCL_GPIO_READ),
280 [sclb] "d"(SCL_BIT),
281 [sclbnum] "i"(SCL_BITNUM),
282 [sdard] "a"(&SDA_GPIO_READ),
283 [sdab] "d"(SDA_BIT),
284 [sdabnum] "i"(SDA_BITNUM),
285 [dly] "d"(i2c_delay)
286 : /* clobbers */
287 "d0"
289 #else
290 SDA_HI_IN;
291 DELAY;
292 SCL_HI_IN;
293 DELAY;
295 ret = !SDA;
297 SCL_LO_OUT;
298 #endif
299 return ret;
302 void pcf50606_i2c_outb(unsigned char byte)
304 #ifdef USE_ASM
305 asm volatile (
306 "moveq.l #24,%%d0 \n" /* byte <<= 24 */
307 "lsl.l %%d0,%[byte] \n"
308 "moveq.l #8,%%d1 \n" /* i = 8 */
310 "2: \n" /* do */
311 "lsl.l #1,%[byte] \n" /* if ((byte <<= 1) carry) */
312 "bcc.s 1f \n"
314 "not.l %[sdab] \n" /* SDA_HI_IN */
315 "and.l %[sdab],(8,%[sdard]) \n"
316 "not.l %[sdab] \n"
317 ".word 0x51fb \n" /* trapf.l; else */
318 "1: \n"
319 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
321 "move.l %[dly],%%d0 \n" /* DELAY */
322 "1: \n"
323 "subq.l #1,%%d0 \n"
324 "bhi.s 1b \n"
326 "not.l %[sclb] \n" /* SCL_HI_IN */
327 "and.l %[sclb],(8,%[sclrd]) \n"
328 "not.l %[sclb] \n"
329 "1: \n"
330 "move.l (%[sclrd]),%%d0 \n"
331 "btst.l %[sclbnum],%%d0 \n"
332 "beq.s 1b \n"
334 "move.l %[dly],%%d0 \n" /* DELAY */
335 "1: \n"
336 "subq.l #1,%%d0 \n"
337 "bhi.s 1b \n"
339 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
341 "subq.l #1,%%d1 \n" /* i-- */
342 "bne.s 2b \n" /* while (i != 0) */
343 : /* outputs */
344 [byte] "+d"(byte)
345 : /* inputs */
346 [sclrd] "a"(&SCL_GPIO_READ),
347 [sclb] "d"(SCL_BIT),
348 [sclbnum] "i"(SCL_BITNUM),
349 [sdard] "a"(&SDA_GPIO_READ),
350 [sdab] "d"(SDA_BIT),
351 [dly] "d"(i2c_delay)
352 : /* clobbers */
353 "d0", "d1"
355 #else
356 int i;
358 /* clock out each bit, MSB first */
359 for ( i=0x80; i; i>>=1 )
361 if ( i & byte )
362 SDA_HI_IN;
363 else
364 SDA_LO_OUT;
365 DELAY;
366 SCL_HI_IN;
367 DELAY;
368 SCL_LO_OUT;
370 #endif
373 unsigned char pcf50606_i2c_inb(bool ack)
375 unsigned char byte = 0;
377 #ifdef USE_ASM
378 asm volatile (
379 "not.l %[sdab] \n" /* SDA_HI_IN */
380 "and.l %[sdab],(8,%[sdard]) \n"
381 "not.l %[sdab] \n"
383 "moveq.l #8,%%d1 \n" /* i = 8 */
384 "clr.l %[byte] \n" /* byte = 0 */
386 "2: \n" /* do */
387 "move.l %[dly],%%d0 \n" /* DELAY */
388 "1: \n"
389 "subq.l #1,%%d0 \n"
390 "bhi.s 1b \n"
392 "not.l %[sclb] \n" /* SCL_HI_IN */
393 "and.l %[sclb],(8,%[sclrd]) \n"
394 "not.l %[sclb] \n"
395 "1: \n"
396 "move.l (%[sclrd]),%%d0 \n"
397 "btst.l %[sclbnum],%%d0 \n"
398 "beq.s 1b \n"
400 "move.l %[dly],%%d0 \n" /* DELAY */
401 "1: \n"
402 "subq.l #1,%%d0 \n"
403 "bhi.s 1b \n"
405 "lsl.l #1,%[byte] \n" /* byte <<= 1 */
406 "move.l (%[sdard]),%%d0 \n" /* if (SDA) */
407 "btst.l %[sdabnum],%%d0 \n"
408 "beq.s 1f \n"
409 "addq.l #1,%[byte] \n" /* byte++ */
410 "1: \n"
412 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
414 "subq.l #1,%%d1 \n" /* i-- */
415 "bne.s 2b \n" /* while (i != 0) */
416 : /* outputs */
417 [byte] "=&d"(byte)
418 : /* inputs */
419 [sclrd] "a"(&SCL_GPIO_READ),
420 [sclb] "d"(SCL_BIT),
421 [sclbnum] "i"(SCL_BITNUM),
422 [sdard] "a"(&SDA_GPIO_READ),
423 [sdab] "d"(SDA_BIT),
424 [sdabnum] "i"(SDA_BITNUM),
425 [dly] "d"(i2c_delay)
426 : /* clobbers */
427 "d0", "d1"
429 #else
430 int i;
432 /* clock in each bit, MSB first */
433 SDA_HI_IN;
434 for ( i=0x80; i; i>>=1 )
436 DELAY;
437 SCL_HI_IN;
438 DELAY;
439 if ( SDA )
440 byte |= i;
441 SCL_LO_OUT;
443 #endif
445 pcf50606_i2c_ack(ack);
447 return byte;
450 static int pcf50606_i2c_write(int address, const unsigned char* buf, int count)
452 int i,x=0;
454 pcf50606_i2c_start();
455 pcf50606_i2c_outb(address & 0xfe);
456 if (pcf50606_i2c_getack())
458 for (i=0; i<count; i++)
460 pcf50606_i2c_outb(buf[i]);
461 if (!pcf50606_i2c_getack())
463 x=-2;
464 break;
468 else
470 logf("pcf50606_i2c_write() - no ack\n");
471 x=-1;
473 return x;
476 int pcf50606_read_multiple(int address, unsigned char* buf, int count)
478 int i=0;
479 int ret = 0;
480 unsigned char obuf[1];
482 obuf[0] = address;
484 /* send read command */
485 if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
487 pcf50606_i2c_start();
488 pcf50606_i2c_outb(0x11);
489 if (pcf50606_i2c_getack())
491 for(i = 0;i < count-1;i++)
492 buf[i] = pcf50606_i2c_inb(true);
494 buf[i] = pcf50606_i2c_inb(false);
496 else
498 ret = -1;
502 pcf50606_i2c_stop();
504 return ret;
507 int pcf50606_read(int address)
509 int ret;
510 unsigned char c;
512 ret = pcf50606_read_multiple(address, &c, 1);
513 if(ret >= 0)
514 return c;
515 else
516 return ret;
519 int pcf50606_write_multiple(int address, const unsigned char* buf, int count)
521 unsigned char obuf[1];
522 int i;
523 int ret = 0;
525 obuf[0] = address;
527 /* send write command */
528 if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
530 for (i=0; i<count; i++)
532 pcf50606_i2c_outb(buf[i]);
533 if (!pcf50606_i2c_getack())
535 ret = -2;
536 break;
540 else
542 ret = -1;
545 pcf50606_i2c_stop();
546 return ret;
549 int pcf50606_write(int address, unsigned char val)
551 return pcf50606_write_multiple(address, &val, 1);