summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2006-10-25 23:24:07 +0000
committerMichael Sevakis <jethead71@rockbox.org>2006-10-25 23:24:07 +0000
commit784dd787456b8c1f52a98559d645714760cd0ad4 (patch)
treee6d60a5790d4bbc9689b9d1d5f71799415a2c77a
parent0642451446f3bbaae53948f5fa41485177e3f35e (diff)
downloadrockbox-784dd787456b8c1f52a98559d645714760cd0ad4.tar.gz
rockbox-784dd787456b8c1f52a98559d645714760cd0ad4.zip
Moved pcf50606 stuff to target directory.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11348 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/SOURCES6
-rw-r--r--firmware/export/pcf50606.h7
-rw-r--r--firmware/powermgmt.c14
-rw-r--r--firmware/target/coldfire/iaudio/x5/pcf50606-x5.c518
-rw-r--r--firmware/target/coldfire/iriver/h300/pcf50606-h300.c52
-rw-r--r--firmware/target/coldfire/pcf50606-coldfire.c540
6 files changed, 609 insertions, 528 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 92a41cdead..171cd6db12 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -138,9 +138,6 @@ drivers/i2c.c
138#if CONFIG_CODEC != SWCODEC 138#if CONFIG_CODEC != SWCODEC
139drivers/mas.c 139drivers/mas.c
140#endif 140#endif
141#ifdef IRIVER_H300_SERIES
142drivers/pcf50606.c
143#endif
144#ifdef HAVE_EEPROM 141#ifdef HAVE_EEPROM
145drivers/eeprom_24cxx.c 142drivers/eeprom_24cxx.c
146#ifdef HAVE_EEPROM_SETTINGS 143#ifdef HAVE_EEPROM_SETTINGS
@@ -242,6 +239,7 @@ target/coldfire/iaudio/x5/power-x5.c
242target/coldfire/iaudio/x5/button-x5.c 239target/coldfire/iaudio/x5/button-x5.c
243target/coldfire/iaudio/x5/lcd-as-x5.S 240target/coldfire/iaudio/x5/lcd-as-x5.S
244target/coldfire/iaudio/x5/lcd-x5.c 241target/coldfire/iaudio/x5/lcd-x5.c
242target/coldfire/pcf50606-coldfire.c
245target/coldfire/iaudio/x5/pcf50606-x5.c 243target/coldfire/iaudio/x5/pcf50606-x5.c
246target/coldfire/iaudio/x5/adc-x5.c 244target/coldfire/iaudio/x5/adc-x5.c
247target/coldfire/iaudio/x5/ata-x5.c 245target/coldfire/iaudio/x5/ata-x5.c
@@ -256,6 +254,8 @@ target/coldfire/iaudio/x5/lcd-remote-x5.c
256#ifdef IRIVER_H300_SERIES 254#ifdef IRIVER_H300_SERIES
257#ifndef SIMULATOR 255#ifndef SIMULATOR
258target/coldfire/iriver/h300/lcd-as-h300.S 256target/coldfire/iriver/h300/lcd-as-h300.S
257target/coldfire/pcf50606-coldfire.c
258target/coldfire/iriver/h300/pcf50606-h300.c
259#endif 259#endif
260#endif 260#endif
261 261
diff --git a/firmware/export/pcf50606.h b/firmware/export/pcf50606.h
index 3e567c963c..1f4b6ba3ad 100644
--- a/firmware/export/pcf50606.h
+++ b/firmware/export/pcf50606.h
@@ -20,13 +20,14 @@
20#define PCF50606_H 20#define PCF50606_H
21 21
22void pcf50606_init(void); 22void pcf50606_init(void);
23void pcf50606_i2c_recalc_delay(int cpu_clock);
24int pcf50606_write_multiple(int address, const unsigned char* buf, int count); 23int pcf50606_write_multiple(int address, const unsigned char* buf, int count);
25int pcf50606_write(int address, unsigned char val); 24int pcf50606_write(int address, unsigned char val);
26int pcf50606_read_multiple(int address, unsigned char* buf, int count); 25int pcf50606_read_multiple(int address, unsigned char* buf, int count);
27int pcf50606_read(int address); 26int pcf50606_read(int address);
28 27
29/* internal low level calls used by the eeprom driver for h300 */ 28/* internal low level calls used by the eeprom driver for h300 */
29void pcf50606_i2c_init(void);
30void pcf50606_i2c_recalc_delay(int cpu_clock);
30void pcf50606_i2c_start(void); 31void pcf50606_i2c_start(void);
31void pcf50606_i2c_stop(void); 32void pcf50606_i2c_stop(void);
32void pcf50606_i2c_ack(bool ack); 33void pcf50606_i2c_ack(bool ack);
@@ -34,4 +35,8 @@ bool pcf50606_i2c_getack(void);
34void pcf50606_i2c_outb(unsigned char byte); 35void pcf50606_i2c_outb(unsigned char byte);
35unsigned char pcf50606_i2c_inb(bool ack); 36unsigned char pcf50606_i2c_inb(bool ack);
36 37
38#if defined(IAUDIO_X5) && !defined(SIMULATOR)
39void pcf50606_reset_timeout(void);
37#endif 40#endif
41
42#endif /* PCF50606_H */
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index ca68fb168a..50b734bbbd 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -59,10 +59,8 @@
59#include <time.h> 59#include <time.h>
60#endif 60#endif
61 61
62#ifdef IAUDIO_X5 62#if defined(IAUDIO_X5) && !defined (SIMULATOR)
63#ifndef SIMULATOR 63#include "pcf50606.h"
64extern void pcf50606_reset_timeout(void);
65#endif
66#endif 64#endif
67 65
68/* 66/*
@@ -1033,13 +1031,11 @@ void cancel_shutdown(void)
1033{ 1031{
1034 logf("sys_cancel_shutdown()"); 1032 logf("sys_cancel_shutdown()");
1035 1033
1036#ifdef IAUDIO_X5 1034#if defined(IAUDIO_X5) && !defined (SIMULATOR)
1037#ifndef SIMULATOR
1038 /* TODO: Move some things to target/ tree */ 1035 /* TODO: Move some things to target/ tree */
1039 if (shutdown_timeout) 1036 if (shutdown_timeout)
1040 pcf50606_reset_timeout(); 1037 pcf50606_reset_timeout();
1041#endif 1038#endif
1042#endif
1043 1039
1044 shutdown_timeout = 0; 1040 shutdown_timeout = 0;
1045} 1041}
@@ -1076,10 +1072,8 @@ void shutdown_hw(void)
1076 backlight_set_fade_out(0); 1072 backlight_set_fade_out(0);
1077#endif 1073#endif
1078 backlight_off(); 1074 backlight_off();
1079#endif /* IAUDIO_X5 */
1080#ifndef IAUDIO_X5
1081 lcd_set_contrast(0); 1075 lcd_set_contrast(0);
1082#endif 1076#endif /* IAUDIO_X5 */
1083#ifdef HAVE_REMOTE_LCD 1077#ifdef HAVE_REMOTE_LCD
1084 remote_backlight_off(); 1078 remote_backlight_off();
1085 lcd_remote_set_contrast(0); 1079 lcd_remote_set_contrast(0);
diff --git a/firmware/target/coldfire/iaudio/x5/pcf50606-x5.c b/firmware/target/coldfire/iaudio/x5/pcf50606-x5.c
index 59ecdb612c..58ff5d5cb0 100644
--- a/firmware/target/coldfire/iaudio/x5/pcf50606-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/pcf50606-x5.c
@@ -17,515 +17,11 @@
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include "config.h" 19#include "config.h"
20#include "cpu.h"
21#include <stdbool.h>
22#include "kernel.h"
23#include "system.h" 20#include "system.h"
24#include "hwcompat.h" 21#include "kernel.h"
25#include "logf.h" 22#include "pcf50606.h"
26#include "debug.h"
27#include "string.h"
28#include "generic_i2c.h"
29#include "powermgmt.h" 23#include "powermgmt.h"
30 24
31#define USE_ASM
32
33/* Data */
34#define SDA_BITNUM 12 /* SDA1/RXD1/GPIO44 */
35#define SDA_GPIO_READ GPIO1_READ /* MBAR2 + 0x0b0 */
36#define SDA_GPIO_OUT GPIO1_OUT /* MBAR2 + 0x0b4 */
37#define SDA_GPIO_ENABLE GPIO1_ENABLE /* MBAR2 + 0x0b8 */
38#define SDA_GPIO_FUNCTION GPIO1_FUNCTION /* MBAR2 + 0x0bc */
39
40/* Clock */
41#define SCL_BITNUM 10 /* SCL1/TXD1/GPIO10 */
42#define SCL_GPIO_READ GPIO_READ /* MBAR2 + 0x000 */
43#define SCL_GPIO_OUT GPIO_OUT /* MBAR2 + 0x004 */
44#define SCL_GPIO_ENABLE GPIO_ENABLE /* MBAR2 + 0x008 */
45#define SCL_GPIO_FUNCTION GPIO_FUNCTION /* MBAR2 + 0x00c */
46
47#define PCF50606_ADDR 0x10
48#define SCL_BIT (1ul << SCL_BITNUM)
49#define SDA_BIT (1ul << SDA_BITNUM)
50
51#define SDA ( SDA_BIT & SDA_GPIO_READ)
52#define SDA_LO_OUT or_l( SDA_BIT, &SDA_GPIO_ENABLE)
53#define SDA_HI_IN and_l(~SDA_BIT, &SDA_GPIO_ENABLE)
54
55#define SCL ( SCL_BIT & SCL_GPIO_READ)
56#define SCL_LO_OUT or_l( SCL_BIT, &SCL_GPIO_ENABLE)
57#define SCL_HI_IN and_l(~SCL_BIT, &SCL_GPIO_ENABLE); while(!SCL);
58
59#define DELAY \
60 asm ( \
61 "move.l %[dly],%%d0 \n" \
62 "1: \n" \
63 "subq.l #1,%%d0 \n" \
64 "bhi.s 1b \n" \
65 : : [dly]"d"(i2c_delay) : "d0" );
66
67static int i2c_delay IDATA_ATTR = 44;
68
69void pcf50606_i2c_recalc_delay(int cpu_clock)
70{
71 i2c_delay = MAX(cpu_clock / (400000*2*3) - 7, 1);
72}
73
74inline void pcf50606_i2c_start(void)
75{
76#ifdef USE_ASM
77 asm (
78 "not.l %[sdab] \n" /* SDA_HI_IN */
79 "and.l %[sdab],(8,%[sdard]) \n"
80 "not.l %[sdab] \n"
81
82 "not.l %[sclb] \n" /* SCL_HI_IN */
83 "and.l %[sclb],(8,%[sclrd]) \n"
84 "not.l %[sclb] \n"
85 "1: \n"
86 "move.l (%[sclrd]),%%d0 \n"
87 "btst.l %[sclbnum], %%d0 \n"
88 "beq.s 1b \n"
89
90 "move.l %[dly],%%d0 \n" /* DELAY */
91 "1: \n"
92 "subq.l #1,%%d0 \n"
93 "bhi.s 1b \n"
94
95 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
96
97 "move.l %[dly],%%d0 \n" /* DELAY */
98 "1: \n"
99 "subq.l #1,%%d0 \n"
100 "bhi.s 1b \n"
101
102 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
103 : /* outputs */
104 : /* inputs */
105 [sclrd] "a"(&SCL_GPIO_READ),
106 [sclb] "d"(SCL_BIT),
107 [sclbnum] "i"(SCL_BITNUM),
108 [sdard] "a"(&SDA_GPIO_READ),
109 [sdab] "d"(SDA_BIT),
110 [dly] "d"(i2c_delay)
111 : /* clobbers */
112 "d0"
113 );
114#else
115 SDA_HI_IN;
116 SCL_HI_IN;
117 DELAY;
118 SDA_LO_OUT;
119 DELAY;
120 SCL_LO_OUT;
121#endif
122}
123
124inline void pcf50606_i2c_stop(void)
125{
126#ifdef USE_ASM
127 asm (
128 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
129
130 "not.l %[sclb] \n" /* SCL_HI_IN */
131 "and.l %[sclb],(8,%[sclrd]) \n"
132 "not.l %[sclb] \n"
133 "1: \n"
134 "move.l (%[sclrd]),%%d0 \n"
135 "btst.l %[sclbnum],%%d0 \n"
136 "beq.s 1b \n"
137
138 "move.l %[dly],%%d0 \n" /* DELAY */
139 "1: \n"
140 "subq.l #1,%%d0 \n"
141 "bhi.s 1b \n"
142
143 "not.l %[sdab] \n" /* SDA_HI_IN */
144 "and.l %[sdab],(8,%[sdard]) \n"
145 "not.l %[sdab] \n"
146 : /* outputs */
147 : /* inputs */
148 [sclrd] "a"(&SCL_GPIO_READ),
149 [sclb] "d"(SCL_BIT),
150 [sclbnum] "i"(SCL_BITNUM),
151 [sdard] "a"(&SDA_GPIO_READ),
152 [sdab] "d"(SDA_BIT),
153 [dly] "d"(i2c_delay)
154 : /* clobbers */
155 "d0"
156 );
157#else
158 SDA_LO_OUT;
159 SCL_HI_IN;
160 DELAY;
161 SDA_HI_IN;
162#endif
163}
164
165inline void pcf50606_i2c_ack(bool ack)
166{
167#ifdef USE_ASM
168 asm (
169 "tst.b %[ack] \n" /* if (!ack) */
170 "bne.s 1f \n"
171
172 "not.l %[sdab] \n" /* SDA_HI_IN */
173 "and.l %[sdab],(8,%[sdard]) \n"
174 "not.l %[sdab] \n"
175 ".word 0x51fb \n" /* trapf.l : else */
176 "1: \n"
177 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
178
179 "not.l %[sclb] \n" /* SCL_HI_IN */
180 "and.l %[sclb],(8,%[sclrd]) \n"
181 "not.l %[sclb] \n"
182 "1: \n"
183 "move.l (%[sclrd]),%%d0 \n"
184 "btst.l %[sclbnum],%%d0 \n"
185 "beq.s 1b \n"
186
187 "move.l %[dly],%%d0 \n" /* DELAY */
188 "1: \n"
189 "subq.l #1,%%d0 \n"
190 "bhi.s 1b \n"
191
192 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
193 : /* outputs */
194 : /* inputs */
195 [sclrd] "a"(&SCL_GPIO_READ),
196 [sclb] "d"(SCL_BIT),
197 [sclbnum] "i"(SCL_BITNUM),
198 [sdard] "a"(&SDA_GPIO_READ),
199 [sdab] "d"(SDA_BIT),
200 [dly] "d"(i2c_delay),
201 [ack] "d"(ack)
202 : /* clobbers */
203 "d0"
204 );
205#else
206 if(ack)
207 SDA_LO_OUT;
208 else
209 SDA_HI_IN;
210
211 SCL_HI_IN;
212
213 DELAY;
214 SCL_LO_OUT;
215#endif
216}
217
218inline bool pcf50606_i2c_getack(void)
219{
220 bool ret;
221
222#ifdef USE_ASM
223 asm (
224 "not.l %[sdab] \n" /* SDA_HI_IN */
225 "and.l %[sdab],(8,%[sdard]) \n"
226 "not.l %[sdab] \n"
227
228 "move.l %[dly],%%d0 \n" /* DELAY */
229 "1: \n"
230 "subq.l #1,%%d0 \n"
231 "bhi.s 1b \n"
232
233 "not.l %[sclb] \n" /* SCL_HI_IN */
234 "and.l %[sclb],(8,%[sclrd]) \n"
235 "not.l %[sclb] \n"
236 "1: \n"
237 "move.l (%[sclrd]),%%d0 \n"
238 "btst.l %[sclbnum],%%d0 \n"
239 "beq.s 1b \n"
240
241 "move.l (%[sdard]),%%d0 \n" /* ret = !SDA */
242 "btst.l %[sdabnum],%%d0 \n"
243 "seq.b %[ret] \n"
244
245 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
246
247 "move.l %[dly],%%d0 \n" /* DELAY */
248 "1: \n"
249 "subq.l #1,%%d0 \n"
250 "bhi.s 1b \n"
251 : /* outputs */
252 [ret] "=&d"(ret)
253 : /* inputs */
254 [sclrd] "a"(&SCL_GPIO_READ),
255 [sclb] "d"(SCL_BIT),
256 [sclbnum] "i"(SCL_BITNUM),
257 [sdard] "a"(&SDA_GPIO_READ),
258 [sdab] "d"(SDA_BIT),
259 [sdabnum] "i"(SDA_BITNUM),
260 [dly] "d"(i2c_delay)
261 : /* clobbers */
262 "d0"
263 );
264#else
265 SDA_HI_IN;
266 DELAY;
267 SCL_HI_IN;
268
269 ret = !SDA;
270
271 SCL_LO_OUT;
272 DELAY;
273#endif
274 return ret;
275}
276
277void pcf50606_i2c_outb(unsigned char byte)
278{
279#ifdef USE_ASM
280 asm volatile (
281 "moveq.l #24,%%d0 \n" /* byte <<= 24 */
282 "lsl.l %%d0,%[byte] \n"
283 "moveq.l #8,%%d1 \n" /* i = 8 */
284
285 "2: \n" /* do */
286 "lsl.l #1,%[byte] \n" /* if ((byte <<= 1) carry) */
287 "bcc.s 1f \n"
288
289 "not.l %[sdab] \n" /* SDA_HI_IN */
290 "and.l %[sdab],(8,%[sdard]) \n"
291 "not.l %[sdab] \n"
292 ".word 0x51fb \n" /* trapf.l; else */
293 "1: \n"
294 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
295
296 "move.l %[dly],%%d0 \n" /* DELAY */
297 "1: \n"
298 "subq.l #1,%%d0 \n"
299 "bhi.s 1b \n"
300
301 "not.l %[sclb] \n" /* SCL_HI_IN */
302 "and.l %[sclb],(8,%[sclrd]) \n"
303 "not.l %[sclb] \n"
304 "1: \n"
305 "move.l (%[sclrd]),%%d0 \n"
306 "btst.l %[sclbnum],%%d0 \n"
307 "beq.s 1b \n"
308
309 "move.l %[dly],%%d0 \n" /* DELAY */
310 "1: \n"
311 "subq.l #1,%%d0 \n"
312 "bhi.s 1b \n"
313
314 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
315
316 "subq.l #1,%%d1 \n" /* i-- */
317 "bne.s 2b \n" /* while (i != 0) */
318 : /* outputs */
319 [byte] "+d"(byte)
320 : /* inputs */
321 [sclrd] "a"(&SCL_GPIO_READ),
322 [sclb] "d"(SCL_BIT),
323 [sclbnum] "i"(SCL_BITNUM),
324 [sdard] "a"(&SDA_GPIO_READ),
325 [sdab] "d"(SDA_BIT),
326 [dly] "d"(i2c_delay)
327 : /* clobbers */
328 "d0", "d1"
329 );
330#else
331 int i;
332
333 /* clock out each bit, MSB first */
334 for ( i=0x80; i; i>>=1 )
335 {
336 if ( i & byte )
337 SDA_HI_IN;
338 else
339 SDA_LO_OUT;
340 DELAY;
341 SCL_HI_IN;
342 DELAY;
343 SCL_LO_OUT;
344 }
345#endif
346}
347
348unsigned char pcf50606_i2c_inb(bool ack)
349{
350 unsigned char byte = 0;
351
352#ifdef USE_ASM
353 asm (
354 "not.l %[sdab] \n" /* SDA_HI_IN */
355 "and.l %[sdab],(8,%[sdard]) \n"
356 "not.l %[sdab] \n"
357
358 "moveq.l #8,%%d1 \n" /* i = 8 */
359 "clr.l %[byte] \n" /* byte = 0 */
360
361 "2: \n" /* do */
362 "not.l %[sclb] \n" /* SCL_HI_IN */
363 "and.l %[sclb],(8,%[sclrd]) \n"
364 "not.l %[sclb] \n"
365 "1: \n"
366 "move.l (%[sclrd]),%%d0 \n"
367 "btst.l %[sclbnum],%%d0 \n"
368 "beq.s 1b \n"
369
370 "move.l %[dly],%%d0 \n" /* DELAY */
371 "1: \n"
372 "subq.l #1,%%d0 \n"
373 "bhi.s 1b \n"
374
375 "lsl.l #1,%[byte] \n" /* byte <<= 1 */
376 "move.l (%[sdard]),%%d0 \n" /* if (SDA) */
377 "btst.l %[sdabnum],%%d0 \n"
378 "beq.s 1f \n"
379 "addq.l #1,%[byte] \n" /* byte++ */
380 "1: \n"
381
382 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
383
384 "move.l %[dly],%%d0 \n" /* DELAY */
385 "1: \n"
386 "subq.l #1,%%d0 \n"
387 "bhi.s 1b \n"
388
389 "subq.l #1,%%d1 \n" /* i-- */
390 "bne.s 2b \n" /* while (i != 0) */
391 : /* outputs */
392 [byte] "=&d"(byte)
393 : /* inputs */
394 [sclrd] "a"(&SCL_GPIO_READ),
395 [sclb] "d"(SCL_BIT),
396 [sclbnum] "i"(SCL_BITNUM),
397 [sdard] "a"(&SDA_GPIO_READ),
398 [sdab] "d"(SDA_BIT),
399 [sdabnum] "i"(SDA_BITNUM),
400 [dly] "d"(i2c_delay)
401 : /* clobbers */
402 "d0", "d1"
403 );
404#else
405 int i;
406
407 /* clock in each bit, MSB first */
408 SDA_HI_IN;
409 for ( i=0x80; i; i>>=1 )
410 {
411 SCL_HI_IN;
412 DELAY;
413 if ( SDA )
414 byte |= i;
415 SCL_LO_OUT;
416 DELAY;
417 }
418#endif
419
420 pcf50606_i2c_ack(ack);
421
422 return byte;
423}
424
425int pcf50606_i2c_write(int address, const unsigned char* buf, int count)
426{
427 int i,x=0;
428
429 pcf50606_i2c_start();
430 pcf50606_i2c_outb(address & 0xfe);
431 if (pcf50606_i2c_getack())
432 {
433 for (i=0; i<count; i++)
434 {
435 pcf50606_i2c_outb(buf[i]);
436 if (!pcf50606_i2c_getack())
437 {
438 x=-2;
439 break;
440 }
441 }
442 }
443 else
444 {
445 logf("pcf50606_i2c_write() - no ack\n");
446 x=-1;
447 }
448 return x;
449}
450
451int pcf50606_read_multiple(int address, unsigned char* buf, int count)
452{
453 int i=0;
454 int ret = 0;
455 unsigned char obuf[1];
456
457 obuf[0] = address;
458
459 /* send read command */
460 if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
461 {
462 pcf50606_i2c_start();
463 pcf50606_i2c_outb(0x11);
464 if (pcf50606_i2c_getack())
465 {
466 for(i = 0;i < count-1;i++)
467 buf[i] = pcf50606_i2c_inb(true);
468
469 buf[i] = pcf50606_i2c_inb(false);
470 }
471 else
472 {
473 ret = -1;
474 }
475 }
476
477 pcf50606_i2c_stop();
478
479 return ret;
480}
481
482int pcf50606_read(int address)
483{
484 int ret;
485 unsigned char c;
486
487 ret = pcf50606_read_multiple(address, &c, 1);
488 if(ret >= 0)
489 return c;
490 else
491 return ret;
492}
493
494int pcf50606_write_multiple(int address, const unsigned char* buf, int count)
495{
496 unsigned char obuf[1];
497 int i;
498 int ret = 0;
499
500 obuf[0] = address;
501
502 /* send write command */
503 if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
504 {
505 for (i=0; i<count; i++)
506 {
507 pcf50606_i2c_outb(buf[i]);
508 if (!pcf50606_i2c_getack())
509 {
510 ret = -2;
511 break;
512 }
513 }
514 }
515 else
516 {
517 ret = -1;
518 }
519
520 pcf50606_i2c_stop();
521 return ret;
522}
523
524int pcf50606_write(int address, unsigned char val)
525{
526 return pcf50606_write_multiple(address, &val, 1);
527}
528
529/* These voltages were determined by measuring the output of the PCF50606 25/* These voltages were determined by measuring the output of the PCF50606
530 on a running X5, and verified by disassembling the original firmware */ 26 on a running X5, and verified by disassembling the original firmware */
531static void set_voltages(void) 27static void set_voltages(void)
@@ -572,13 +68,7 @@ static inline void enable_pmu_interrupts(void)
572 68
573void pcf50606_init(void) 69void pcf50606_init(void)
574{ 70{
575 /* Bit banged I2C */ 71 pcf50606_i2c_init();
576 or_l(SDA_BIT, &SDA_GPIO_FUNCTION);
577 or_l(SCL_BIT, &SCL_GPIO_FUNCTION);
578 and_l(~SDA_BIT, &SDA_GPIO_OUT);
579 and_l(~SCL_BIT, &SCL_GPIO_OUT);
580 and_l(~SDA_BIT, &SDA_GPIO_ENABLE);
581 and_l(~SCL_BIT, &SCL_GPIO_ENABLE);
582 72
583 /* initialize pmu interrupts but don't service them yet */ 73 /* initialize pmu interrupts but don't service them yet */
584 init_pmu_interrupts(); 74 init_pmu_interrupts();
@@ -611,7 +101,7 @@ void pcf50606_reset_timeout(void)
611void GPI0(void) __attribute__ ((interrupt_handler, section(".text"))); 101void GPI0(void) __attribute__ ((interrupt_handler, section(".text")));
612void GPI0(void) 102void GPI0(void)
613{ 103{
614 char read[3]; /* 0 = INT1, 1 = INT2, 2 = INT3 */ 104 unsigned char read[3]; /* 0 = INT1, 1 = INT2, 2 = INT3 */
615 105
616 /* clear pending interrupts from pcf50606 */ 106 /* clear pending interrupts from pcf50606 */
617 pcf50606_read_multiple(0x02, read, 3); 107 pcf50606_read_multiple(0x02, read, 3);
diff --git a/firmware/target/coldfire/iriver/h300/pcf50606-h300.c b/firmware/target/coldfire/iriver/h300/pcf50606-h300.c
new file mode 100644
index 0000000000..c990f5ddcb
--- /dev/null
+++ b/firmware/target/coldfire/iriver/h300/pcf50606-h300.c
@@ -0,0 +1,52 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20#include "system.h"
21#include "kernel.h"
22#include "pcf50606.h"
23
24/* These voltages were determined by measuring the output of the PCF50606
25 on a running H300, and verified by disassembling the original firmware */
26static void set_voltages(void)
27{
28 static const unsigned char buf[5] =
29 {
30 0xf4, /* IOREGC = 2.9V, ON in all states */
31 0xef, /* D1REGC = 2.4V, ON in all states */
32 0x18, /* D2REGC = 3.3V, OFF in all states */
33 0xf0, /* D3REGC = 2.5V, ON in all states */
34 0xef, /* LPREGC1 = 2.4V, ON in all states */
35 };
36
37 pcf50606_write_multiple(0x23, buf, 5);
38}
39
40void pcf50606_init(void)
41{
42 pcf50606_i2c_init();
43
44 set_voltages();
45
46 pcf50606_write(0x08, 0x60); /* Wake on USB and charger insertion */
47 pcf50606_write(0x09, 0x05); /* USB and ON key debounce: 14ms */
48 pcf50606_write(0x29, 0x1C); /* Disable the unused MBC module */
49
50 pcf50606_write(0x35, 0x13); /* Backlight PWM = 512Hz 50/50 */
51 pcf50606_write(0x3a, 0x3b); /* PWM output on GPOOD1 */
52}
diff --git a/firmware/target/coldfire/pcf50606-coldfire.c b/firmware/target/coldfire/pcf50606-coldfire.c
new file mode 100644
index 0000000000..ecc9e0ee72
--- /dev/null
+++ b/firmware/target/coldfire/pcf50606-coldfire.c
@@ -0,0 +1,540 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20#include "system.h"
21#include "logf.h"
22#include "kernel.h"
23#include "pcf50606.h"
24
25#define USE_ASM
26
27/* Define the approprate bits for SDA and SCL being the only difference in
28 config between each player. */
29#if defined(IRIVER_H300_SERIES)
30#define SDA_BITNUM 13 /* LRCK3/GPIO45 */
31#define SCL_BITNUM 12 /* SWE/GPIO12 */
32#elif defined(IAUDIO_X5)
33#define SDA_BITNUM 12 /* SDA1/RXD1/GPIO44 */
34#define SCL_BITNUM 10 /* SCL1/TXD1/GPIO10 */
35#endif
36
37/* Data */
38#define SDA_GPIO_READ GPIO1_READ /* MBAR2 + 0x0b0 */
39#define SDA_GPIO_OUT GPIO1_OUT /* MBAR2 + 0x0b4 */
40#define SDA_GPIO_ENABLE GPIO1_ENABLE /* MBAR2 + 0x0b8 */
41#define SDA_GPIO_FUNCTION GPIO1_FUNCTION /* MBAR2 + 0x0bc */
42
43/* Clock */
44#define SCL_GPIO_READ GPIO_READ /* MBAR2 + 0x000 */
45#define SCL_GPIO_OUT GPIO_OUT /* MBAR2 + 0x004 */
46#define SCL_GPIO_ENABLE GPIO_ENABLE /* MBAR2 + 0x008 */
47#define SCL_GPIO_FUNCTION GPIO_FUNCTION /* MBAR2 + 0x00c */
48
49#define PCF50606_ADDR 0x10
50#define SCL_BIT (1ul << SCL_BITNUM)
51#define SDA_BIT (1ul << SDA_BITNUM)
52
53#define SDA ( SDA_BIT & SDA_GPIO_READ)
54#define SDA_LO_OUT or_l( SDA_BIT, &SDA_GPIO_ENABLE)
55#define SDA_HI_IN and_l(~SDA_BIT, &SDA_GPIO_ENABLE)
56
57#define SCL ( SCL_BIT & SCL_GPIO_READ)
58#define SCL_LO_OUT or_l( SCL_BIT, &SCL_GPIO_ENABLE)
59#define SCL_HI_IN and_l(~SCL_BIT, &SCL_GPIO_ENABLE); while(!SCL);
60
61#define DELAY \
62 asm ( \
63 "move.l %[dly],%%d0 \n" \
64 "1: \n" \
65 "subq.l #1,%%d0 \n" \
66 "bhi.s 1b \n" \
67 : : [dly]"d"(i2c_delay) : "d0" );
68
69void pcf50606_i2c_init(void)
70{
71 /* Bit banged I2C */
72 or_l(SDA_BIT, &SDA_GPIO_FUNCTION);
73 or_l(SCL_BIT, &SCL_GPIO_FUNCTION);
74 and_l(~SDA_BIT, &SDA_GPIO_OUT);
75 and_l(~SCL_BIT, &SCL_GPIO_OUT);
76 and_l(~SDA_BIT, &SDA_GPIO_ENABLE);
77 and_l(~SCL_BIT, &SCL_GPIO_ENABLE);
78}
79
80static int i2c_delay IDATA_ATTR = 44;
81
82void pcf50606_i2c_recalc_delay(int cpu_clock)
83{
84 i2c_delay = MAX(cpu_clock / (400000*2*3) - 7, 1);
85}
86
87inline void pcf50606_i2c_start(void)
88{
89#ifdef USE_ASM
90 asm (
91 "not.l %[sdab] \n" /* SDA_HI_IN */
92 "and.l %[sdab],(8,%[sdard]) \n"
93 "not.l %[sdab] \n"
94
95 "not.l %[sclb] \n" /* SCL_HI_IN */
96 "and.l %[sclb],(8,%[sclrd]) \n"
97 "not.l %[sclb] \n"
98 "1: \n"
99 "move.l (%[sclrd]),%%d0 \n"
100 "btst.l %[sclbnum], %%d0 \n"
101 "beq.s 1b \n"
102
103 "move.l %[dly],%%d0 \n" /* DELAY */
104 "1: \n"
105 "subq.l #1,%%d0 \n"
106 "bhi.s 1b \n"
107
108 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
109
110 "move.l %[dly],%%d0 \n" /* DELAY */
111 "1: \n"
112 "subq.l #1,%%d0 \n"
113 "bhi.s 1b \n"
114
115 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
116 : /* outputs */
117 : /* inputs */
118 [sclrd] "a"(&SCL_GPIO_READ),
119 [sclb] "d"(SCL_BIT),
120 [sclbnum] "i"(SCL_BITNUM),
121 [sdard] "a"(&SDA_GPIO_READ),
122 [sdab] "d"(SDA_BIT),
123 [dly] "d"(i2c_delay)
124 : /* clobbers */
125 "d0"
126 );
127#else
128 SDA_HI_IN;
129 SCL_HI_IN;
130 DELAY;
131 SDA_LO_OUT;
132 DELAY;
133 SCL_LO_OUT;
134#endif
135}
136
137inline void pcf50606_i2c_stop(void)
138{
139#ifdef USE_ASM
140 asm (
141 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
142
143 "not.l %[sclb] \n" /* SCL_HI_IN */
144 "and.l %[sclb],(8,%[sclrd]) \n"
145 "not.l %[sclb] \n"
146 "1: \n"
147 "move.l (%[sclrd]),%%d0 \n"
148 "btst.l %[sclbnum],%%d0 \n"
149 "beq.s 1b \n"
150
151 "move.l %[dly],%%d0 \n" /* DELAY */
152 "1: \n"
153 "subq.l #1,%%d0 \n"
154 "bhi.s 1b \n"
155
156 "not.l %[sdab] \n" /* SDA_HI_IN */
157 "and.l %[sdab],(8,%[sdard]) \n"
158 "not.l %[sdab] \n"
159 : /* outputs */
160 : /* inputs */
161 [sclrd] "a"(&SCL_GPIO_READ),
162 [sclb] "d"(SCL_BIT),
163 [sclbnum] "i"(SCL_BITNUM),
164 [sdard] "a"(&SDA_GPIO_READ),
165 [sdab] "d"(SDA_BIT),
166 [dly] "d"(i2c_delay)
167 : /* clobbers */
168 "d0"
169 );
170#else
171 SDA_LO_OUT;
172 SCL_HI_IN;
173 DELAY;
174 SDA_HI_IN;
175#endif
176}
177
178inline void pcf50606_i2c_ack(bool ack)
179{
180#ifdef USE_ASM
181 asm (
182 "tst.b %[ack] \n" /* if (!ack) */
183 "bne.s 1f \n"
184
185 "not.l %[sdab] \n" /* SDA_HI_IN */
186 "and.l %[sdab],(8,%[sdard]) \n"
187 "not.l %[sdab] \n"
188 ".word 0x51fb \n" /* trapf.l : else */
189 "1: \n"
190 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
191
192 "not.l %[sclb] \n" /* SCL_HI_IN */
193 "and.l %[sclb],(8,%[sclrd]) \n"
194 "not.l %[sclb] \n"
195 "1: \n"
196 "move.l (%[sclrd]),%%d0 \n"
197 "btst.l %[sclbnum],%%d0 \n"
198 "beq.s 1b \n"
199
200 "move.l %[dly],%%d0 \n" /* DELAY */
201 "1: \n"
202 "subq.l #1,%%d0 \n"
203 "bhi.s 1b \n"
204
205 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
206 : /* outputs */
207 : /* inputs */
208 [sclrd] "a"(&SCL_GPIO_READ),
209 [sclb] "d"(SCL_BIT),
210 [sclbnum] "i"(SCL_BITNUM),
211 [sdard] "a"(&SDA_GPIO_READ),
212 [sdab] "d"(SDA_BIT),
213 [dly] "d"(i2c_delay),
214 [ack] "d"(ack)
215 : /* clobbers */
216 "d0"
217 );
218#else
219 if(ack)
220 SDA_LO_OUT;
221 else
222 SDA_HI_IN;
223
224 SCL_HI_IN;
225
226 DELAY;
227 SCL_LO_OUT;
228#endif
229}
230
231inline bool pcf50606_i2c_getack(void)
232{
233 bool ret;
234
235#ifdef USE_ASM
236 asm (
237 "not.l %[sdab] \n" /* SDA_HI_IN */
238 "and.l %[sdab],(8,%[sdard]) \n"
239 "not.l %[sdab] \n"
240
241 "move.l %[dly],%%d0 \n" /* DELAY */
242 "1: \n"
243 "subq.l #1,%%d0 \n"
244 "bhi.s 1b \n"
245
246 "not.l %[sclb] \n" /* SCL_HI_IN */
247 "and.l %[sclb],(8,%[sclrd]) \n"
248 "not.l %[sclb] \n"
249 "1: \n"
250 "move.l (%[sclrd]),%%d0 \n"
251 "btst.l %[sclbnum],%%d0 \n"
252 "beq.s 1b \n"
253
254 "move.l (%[sdard]),%%d0 \n" /* ret = !SDA */
255 "btst.l %[sdabnum],%%d0 \n"
256 "seq.b %[ret] \n"
257
258 "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 */
265 [ret] "=&d"(ret)
266 : /* inputs */
267 [sclrd] "a"(&SCL_GPIO_READ),
268 [sclb] "d"(SCL_BIT),
269 [sclbnum] "i"(SCL_BITNUM),
270 [sdard] "a"(&SDA_GPIO_READ),
271 [sdab] "d"(SDA_BIT),
272 [sdabnum] "i"(SDA_BITNUM),
273 [dly] "d"(i2c_delay)
274 : /* clobbers */
275 "d0"
276 );
277#else
278 SDA_HI_IN;
279 DELAY;
280 SCL_HI_IN;
281
282 ret = !SDA;
283
284 SCL_LO_OUT;
285 DELAY;
286#endif
287 return ret;
288}
289
290void pcf50606_i2c_outb(unsigned char byte)
291{
292#ifdef USE_ASM
293 asm volatile (
294 "moveq.l #24,%%d0 \n" /* byte <<= 24 */
295 "lsl.l %%d0,%[byte] \n"
296 "moveq.l #8,%%d1 \n" /* i = 8 */
297
298 "2: \n" /* do */
299 "lsl.l #1,%[byte] \n" /* if ((byte <<= 1) carry) */
300 "bcc.s 1f \n"
301
302 "not.l %[sdab] \n" /* SDA_HI_IN */
303 "and.l %[sdab],(8,%[sdard]) \n"
304 "not.l %[sdab] \n"
305 ".word 0x51fb \n" /* trapf.l; else */
306 "1: \n"
307 "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
308
309 "move.l %[dly],%%d0 \n" /* DELAY */
310 "1: \n"
311 "subq.l #1,%%d0 \n"
312 "bhi.s 1b \n"
313
314 "not.l %[sclb] \n" /* SCL_HI_IN */
315 "and.l %[sclb],(8,%[sclrd]) \n"
316 "not.l %[sclb] \n"
317 "1: \n"
318 "move.l (%[sclrd]),%%d0 \n"
319 "btst.l %[sclbnum],%%d0 \n"
320 "beq.s 1b \n"
321
322 "move.l %[dly],%%d0 \n" /* DELAY */
323 "1: \n"
324 "subq.l #1,%%d0 \n"
325 "bhi.s 1b \n"
326
327 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
328
329 "subq.l #1,%%d1 \n" /* i-- */
330 "bne.s 2b \n" /* while (i != 0) */
331 : /* outputs */
332 [byte] "+d"(byte)
333 : /* inputs */
334 [sclrd] "a"(&SCL_GPIO_READ),
335 [sclb] "d"(SCL_BIT),
336 [sclbnum] "i"(SCL_BITNUM),
337 [sdard] "a"(&SDA_GPIO_READ),
338 [sdab] "d"(SDA_BIT),
339 [dly] "d"(i2c_delay)
340 : /* clobbers */
341 "d0", "d1"
342 );
343#else
344 int i;
345
346 /* clock out each bit, MSB first */
347 for ( i=0x80; i; i>>=1 )
348 {
349 if ( i & byte )
350 SDA_HI_IN;
351 else
352 SDA_LO_OUT;
353 DELAY;
354 SCL_HI_IN;
355 DELAY;
356 SCL_LO_OUT;
357 }
358#endif
359}
360
361unsigned char pcf50606_i2c_inb(bool ack)
362{
363 unsigned char byte = 0;
364
365#ifdef USE_ASM
366 asm (
367 "not.l %[sdab] \n" /* SDA_HI_IN */
368 "and.l %[sdab],(8,%[sdard]) \n"
369 "not.l %[sdab] \n"
370
371 "moveq.l #8,%%d1 \n" /* i = 8 */
372 "clr.l %[byte] \n" /* byte = 0 */
373
374 "2: \n" /* do */
375 "not.l %[sclb] \n" /* SCL_HI_IN */
376 "and.l %[sclb],(8,%[sclrd]) \n"
377 "not.l %[sclb] \n"
378 "1: \n"
379 "move.l (%[sclrd]),%%d0 \n"
380 "btst.l %[sclbnum],%%d0 \n"
381 "beq.s 1b \n"
382
383 "move.l %[dly],%%d0 \n" /* DELAY */
384 "1: \n"
385 "subq.l #1,%%d0 \n"
386 "bhi.s 1b \n"
387
388 "lsl.l #1,%[byte] \n" /* byte <<= 1 */
389 "move.l (%[sdard]),%%d0 \n" /* if (SDA) */
390 "btst.l %[sdabnum],%%d0 \n"
391 "beq.s 1f \n"
392 "addq.l #1,%[byte] \n" /* byte++ */
393 "1: \n"
394
395 "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
396
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-- */
403 "bne.s 2b \n" /* while (i != 0) */
404 : /* outputs */
405 [byte] "=&d"(byte)
406 : /* inputs */
407 [sclrd] "a"(&SCL_GPIO_READ),
408 [sclb] "d"(SCL_BIT),
409 [sclbnum] "i"(SCL_BITNUM),
410 [sdard] "a"(&SDA_GPIO_READ),
411 [sdab] "d"(SDA_BIT),
412 [sdabnum] "i"(SDA_BITNUM),
413 [dly] "d"(i2c_delay)
414 : /* clobbers */
415 "d0", "d1"
416 );
417#else
418 int i;
419
420 /* clock in each bit, MSB first */
421 SDA_HI_IN;
422 for ( i=0x80; i; i>>=1 )
423 {
424 SCL_HI_IN;
425 DELAY;
426 if ( SDA )
427 byte |= i;
428 SCL_LO_OUT;
429 DELAY;
430 }
431#endif
432
433 pcf50606_i2c_ack(ack);
434
435 return byte;
436}
437
438int pcf50606_i2c_write(int address, const unsigned char* buf, int count)
439{
440 int i,x=0;
441
442 pcf50606_i2c_start();
443 pcf50606_i2c_outb(address & 0xfe);
444 if (pcf50606_i2c_getack())
445 {
446 for (i=0; i<count; i++)
447 {
448 pcf50606_i2c_outb(buf[i]);
449 if (!pcf50606_i2c_getack())
450 {
451 x=-2;
452 break;
453 }
454 }
455 }
456 else
457 {
458 logf("pcf50606_i2c_write() - no ack\n");
459 x=-1;
460 }
461 return x;
462}
463
464int pcf50606_read_multiple(int address, unsigned char* buf, int count)
465{
466 int i=0;
467 int ret = 0;
468 unsigned char obuf[1];
469
470 obuf[0] = address;
471
472 /* send read command */
473 if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
474 {
475 pcf50606_i2c_start();
476 pcf50606_i2c_outb(0x11);
477 if (pcf50606_i2c_getack())
478 {
479 for(i = 0;i < count-1;i++)
480 buf[i] = pcf50606_i2c_inb(true);
481
482 buf[i] = pcf50606_i2c_inb(false);
483 }
484 else
485 {
486 ret = -1;
487 }
488 }
489
490 pcf50606_i2c_stop();
491
492 return ret;
493}
494
495int pcf50606_read(int address)
496{
497 int ret;
498 unsigned char c;
499
500 ret = pcf50606_read_multiple(address, &c, 1);
501 if(ret >= 0)
502 return c;
503 else
504 return ret;
505}
506
507int pcf50606_write_multiple(int address, const unsigned char* buf, int count)
508{
509 unsigned char obuf[1];
510 int i;
511 int ret = 0;
512
513 obuf[0] = address;
514
515 /* send write command */
516 if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
517 {
518 for (i=0; i<count; i++)
519 {
520 pcf50606_i2c_outb(buf[i]);
521 if (!pcf50606_i2c_getack())
522 {
523 ret = -2;
524 break;
525 }
526 }
527 }
528 else
529 {
530 ret = -1;
531 }
532
533 pcf50606_i2c_stop();
534 return ret;
535}
536
537int pcf50606_write(int address, unsigned char val)
538{
539 return pcf50606_write_multiple(address, &val, 1);
540}