blob: 8ee38840d665ac65ecb5e7d818ff4cc7c84bd8f6 [file] [log] [blame]
Michael Sevakis784dd782006-10-25 23:24:07 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Michael Sevakis784dd782006-10-25 23:24:07 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "system.h"
23#include "logf.h"
24#include "kernel.h"
25#include "pcf50606.h"
26
27#define USE_ASM
28
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 */
Jens Arnoldb4994a02007-03-04 14:09:21 +000034#elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
Michael Sevakis784dd782006-10-25 23:24:07 +000035#define SDA_BITNUM 12 /* SDA1/RXD1/GPIO44 */
36#define SCL_BITNUM 10 /* SCL1/TXD1/GPIO10 */
37#endif
38
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 */
44
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 */
50
51#define PCF50606_ADDR 0x10
52#define SCL_BIT (1ul << SCL_BITNUM)
53#define SDA_BIT (1ul << SDA_BITNUM)
54
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)
58
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);
62
63#define DELAY \
64 asm ( \
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" );
70
71void pcf50606_i2c_init(void)
72{
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);
80}
81
82static int i2c_delay IDATA_ATTR = 44;
83
84void pcf50606_i2c_recalc_delay(int cpu_clock)
85{
Jens Arnold3674af62007-10-17 20:45:13 +000086 i2c_delay = MAX(cpu_clock / (400000*2*3) - 7, 1);
Michael Sevakis784dd782006-10-25 23:24:07 +000087}
88
89inline void pcf50606_i2c_start(void)
90{
91#ifdef USE_ASM
92 asm (
93 "not.l %[sdab] \n" /* SDA_HI_IN */
94 "and.l %[sdab],(8,%[sdard]) \n"
95 "not.l %[sdab] \n"
96
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"
104
105 "move.l %[dly],%%d0 \n" /* DELAY */
106 "1: \n"
107 "subq.l #1,%%d0 \n"
108 "bhi.s 1b \n"
109
110 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
111
112 "move.l %[dly],%%d0 \n" /* DELAY */
113 "1: \n"
114 "subq.l #1,%%d0 \n"
115 "bhi.s 1b \n"
116
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"
128 );
129#else
130 SDA_HI_IN;
131 SCL_HI_IN;
132 DELAY;
133 SDA_LO_OUT;
134 DELAY;
135 SCL_LO_OUT;
136#endif
137}
138
139inline void pcf50606_i2c_stop(void)
140{
141#ifdef USE_ASM
142 asm (
143 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
144
Jens Arnold3a5509a2007-10-15 16:45:46 +0000145 "move.l %[dly],%%d0 \n" /* DELAY */
146 "1: \n"
147 "subq.l #1,%%d0 \n"
148 "bhi.s 1b \n"
149
Michael Sevakis784dd782006-10-25 23:24:07 +0000150 "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"
157
158 "move.l %[dly],%%d0 \n" /* DELAY */
159 "1: \n"
160 "subq.l #1,%%d0 \n"
161 "bhi.s 1b \n"
162
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"
176 );
177#else
178 SDA_LO_OUT;
Jens Arnold3a5509a2007-10-15 16:45:46 +0000179 DELAY;
Michael Sevakis784dd782006-10-25 23:24:07 +0000180 SCL_HI_IN;
181 DELAY;
182 SDA_HI_IN;
183#endif
184}
185
186inline void pcf50606_i2c_ack(bool ack)
187{
188#ifdef USE_ASM
189 asm (
190 "tst.b %[ack] \n" /* if (!ack) */
191 "bne.s 1f \n"
192
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 */
199
Jens Arnold3a5509a2007-10-15 16:45:46 +0000200 "move.l %[dly],%%d0 \n" /* DELAY */
201 "1: \n"
202 "subq.l #1,%%d0 \n"
203 "bhi.s 1b \n"
204
Michael Sevakis784dd782006-10-25 23:24:07 +0000205 "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"
212
213 "move.l %[dly],%%d0 \n" /* DELAY */
214 "1: \n"
215 "subq.l #1,%%d0 \n"
216 "bhi.s 1b \n"
217
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"
230 );
231#else
232 if(ack)
233 SDA_LO_OUT;
234 else
235 SDA_HI_IN;
Jens Arnold3a5509a2007-10-15 16:45:46 +0000236 DELAY;
Michael Sevakis784dd782006-10-25 23:24:07 +0000237 SCL_HI_IN;
Michael Sevakis784dd782006-10-25 23:24:07 +0000238 DELAY;
239 SCL_LO_OUT;
240#endif
241}
242
243inline bool pcf50606_i2c_getack(void)
244{
245 bool ret;
246
247#ifdef USE_ASM
248 asm (
249 "not.l %[sdab] \n" /* SDA_HI_IN */
250 "and.l %[sdab],(8,%[sdard]) \n"
251 "not.l %[sdab] \n"
252
253 "move.l %[dly],%%d0 \n" /* DELAY */
254 "1: \n"
255 "subq.l #1,%%d0 \n"
256 "bhi.s 1b \n"
257
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"
265
Jens Arnold3a5509a2007-10-15 16:45:46 +0000266 "move.l %[dly],%%d0 \n" /* DELAY */
267 "1: \n"
268 "subq.l #1,%%d0 \n"
269 "bhi.s 1b \n"
270
Michael Sevakis784dd782006-10-25 23:24:07 +0000271 "move.l (%[sdard]),%%d0 \n" /* ret = !SDA */
272 "btst.l %[sdabnum],%%d0 \n"
273 "seq.b %[ret] \n"
274
275 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
Michael Sevakis784dd782006-10-25 23:24:07 +0000276 : /* 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"
288 );
289#else
290 SDA_HI_IN;
291 DELAY;
292 SCL_HI_IN;
Jens Arnold3a5509a2007-10-15 16:45:46 +0000293 DELAY;
Michael Sevakis784dd782006-10-25 23:24:07 +0000294
295 ret = !SDA;
Jens Arnold3a5509a2007-10-15 16:45:46 +0000296
Michael Sevakis784dd782006-10-25 23:24:07 +0000297 SCL_LO_OUT;
Michael Sevakis784dd782006-10-25 23:24:07 +0000298#endif
299 return ret;
300}
301
302void pcf50606_i2c_outb(unsigned char byte)
303{
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 */
309
310 "2: \n" /* do */
311 "lsl.l #1,%[byte] \n" /* if ((byte <<= 1) carry) */
312 "bcc.s 1f \n"
313
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 */
320
321 "move.l %[dly],%%d0 \n" /* DELAY */
322 "1: \n"
323 "subq.l #1,%%d0 \n"
324 "bhi.s 1b \n"
325
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"
333
334 "move.l %[dly],%%d0 \n" /* DELAY */
335 "1: \n"
336 "subq.l #1,%%d0 \n"
337 "bhi.s 1b \n"
338
339 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
340
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"
354 );
355#else
356 int i;
357
358 /* clock out each bit, MSB first */
359 for ( i=0x80; i; i>>=1 )
360 {
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;
369 }
370#endif
371}
372
373unsigned char pcf50606_i2c_inb(bool ack)
374{
375 unsigned char byte = 0;
376
377#ifdef USE_ASM
378 asm (
379 "not.l %[sdab] \n" /* SDA_HI_IN */
380 "and.l %[sdab],(8,%[sdard]) \n"
381 "not.l %[sdab] \n"
382
383 "moveq.l #8,%%d1 \n" /* i = 8 */
384 "clr.l %[byte] \n" /* byte = 0 */
385
386 "2: \n" /* do */
Jens Arnold3a5509a2007-10-15 16:45:46 +0000387 "move.l %[dly],%%d0 \n" /* DELAY */
388 "1: \n"
389 "subq.l #1,%%d0 \n"
390 "bhi.s 1b \n"
391
Michael Sevakis784dd782006-10-25 23:24:07 +0000392 "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"
399
400 "move.l %[dly],%%d0 \n" /* DELAY */
401 "1: \n"
402 "subq.l #1,%%d0 \n"
403 "bhi.s 1b \n"
404
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"
411
412 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
413
Michael Sevakis784dd782006-10-25 23:24:07 +0000414 "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"
428 );
429#else
430 int i;
431
432 /* clock in each bit, MSB first */
433 SDA_HI_IN;
434 for ( i=0x80; i; i>>=1 )
435 {
Jens Arnold3a5509a2007-10-15 16:45:46 +0000436 DELAY;
Michael Sevakis784dd782006-10-25 23:24:07 +0000437 SCL_HI_IN;
438 DELAY;
439 if ( SDA )
440 byte |= i;
441 SCL_LO_OUT;
Michael Sevakis784dd782006-10-25 23:24:07 +0000442 }
443#endif
444
445 pcf50606_i2c_ack(ack);
446
447 return byte;
448}
449
450int pcf50606_i2c_write(int address, const unsigned char* buf, int count)
451{
452 int i,x=0;
453
454 pcf50606_i2c_start();
455 pcf50606_i2c_outb(address & 0xfe);
456 if (pcf50606_i2c_getack())
457 {
458 for (i=0; i<count; i++)
459 {
460 pcf50606_i2c_outb(buf[i]);
461 if (!pcf50606_i2c_getack())
462 {
463 x=-2;
464 break;
465 }
466 }
467 }
468 else
469 {
470 logf("pcf50606_i2c_write() - no ack\n");
471 x=-1;
472 }
473 return x;
474}
475
476int pcf50606_read_multiple(int address, unsigned char* buf, int count)
477{
478 int i=0;
479 int ret = 0;
480 unsigned char obuf[1];
481
482 obuf[0] = address;
483
484 /* send read command */
485 if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
486 {
487 pcf50606_i2c_start();
488 pcf50606_i2c_outb(0x11);
489 if (pcf50606_i2c_getack())
490 {
491 for(i = 0;i < count-1;i++)
492 buf[i] = pcf50606_i2c_inb(true);
493
494 buf[i] = pcf50606_i2c_inb(false);
495 }
496 else
497 {
498 ret = -1;
499 }
500 }
501
502 pcf50606_i2c_stop();
503
504 return ret;
505}
506
507int pcf50606_read(int address)
508{
509 int ret;
510 unsigned char c;
511
512 ret = pcf50606_read_multiple(address, &c, 1);
513 if(ret >= 0)
514 return c;
515 else
516 return ret;
517}
518
519int pcf50606_write_multiple(int address, const unsigned char* buf, int count)
520{
521 unsigned char obuf[1];
522 int i;
523 int ret = 0;
524
525 obuf[0] = address;
526
527 /* send write command */
528 if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
529 {
530 for (i=0; i<count; i++)
531 {
532 pcf50606_i2c_outb(buf[i]);
533 if (!pcf50606_i2c_getack())
534 {
535 ret = -2;
536 break;
537 }
538 }
539 }
540 else
541 {
542 ret = -1;
543 }
544
545 pcf50606_i2c_stop();
546 return ret;
547}
548
549int pcf50606_write(int address, unsigned char val)
550{
551 return pcf50606_write_multiple(address, &val, 1);
552}