diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2006-10-25 23:24:07 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2006-10-25 23:24:07 +0000 |
commit | 784dd787456b8c1f52a98559d645714760cd0ad4 (patch) | |
tree | e6d60a5790d4bbc9689b9d1d5f71799415a2c77a /firmware | |
parent | 0642451446f3bbaae53948f5fa41485177e3f35e (diff) | |
download | rockbox-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
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 6 | ||||
-rw-r--r-- | firmware/export/pcf50606.h | 7 | ||||
-rw-r--r-- | firmware/powermgmt.c | 14 | ||||
-rw-r--r-- | firmware/target/coldfire/iaudio/x5/pcf50606-x5.c | 518 | ||||
-rw-r--r-- | firmware/target/coldfire/iriver/h300/pcf50606-h300.c | 52 | ||||
-rw-r--r-- | firmware/target/coldfire/pcf50606-coldfire.c | 540 |
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 |
139 | drivers/mas.c | 139 | drivers/mas.c |
140 | #endif | 140 | #endif |
141 | #ifdef IRIVER_H300_SERIES | ||
142 | drivers/pcf50606.c | ||
143 | #endif | ||
144 | #ifdef HAVE_EEPROM | 141 | #ifdef HAVE_EEPROM |
145 | drivers/eeprom_24cxx.c | 142 | drivers/eeprom_24cxx.c |
146 | #ifdef HAVE_EEPROM_SETTINGS | 143 | #ifdef HAVE_EEPROM_SETTINGS |
@@ -242,6 +239,7 @@ target/coldfire/iaudio/x5/power-x5.c | |||
242 | target/coldfire/iaudio/x5/button-x5.c | 239 | target/coldfire/iaudio/x5/button-x5.c |
243 | target/coldfire/iaudio/x5/lcd-as-x5.S | 240 | target/coldfire/iaudio/x5/lcd-as-x5.S |
244 | target/coldfire/iaudio/x5/lcd-x5.c | 241 | target/coldfire/iaudio/x5/lcd-x5.c |
242 | target/coldfire/pcf50606-coldfire.c | ||
245 | target/coldfire/iaudio/x5/pcf50606-x5.c | 243 | target/coldfire/iaudio/x5/pcf50606-x5.c |
246 | target/coldfire/iaudio/x5/adc-x5.c | 244 | target/coldfire/iaudio/x5/adc-x5.c |
247 | target/coldfire/iaudio/x5/ata-x5.c | 245 | target/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 |
258 | target/coldfire/iriver/h300/lcd-as-h300.S | 256 | target/coldfire/iriver/h300/lcd-as-h300.S |
257 | target/coldfire/pcf50606-coldfire.c | ||
258 | target/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 | ||
22 | void pcf50606_init(void); | 22 | void pcf50606_init(void); |
23 | void pcf50606_i2c_recalc_delay(int cpu_clock); | ||
24 | int pcf50606_write_multiple(int address, const unsigned char* buf, int count); | 23 | int pcf50606_write_multiple(int address, const unsigned char* buf, int count); |
25 | int pcf50606_write(int address, unsigned char val); | 24 | int pcf50606_write(int address, unsigned char val); |
26 | int pcf50606_read_multiple(int address, unsigned char* buf, int count); | 25 | int pcf50606_read_multiple(int address, unsigned char* buf, int count); |
27 | int pcf50606_read(int address); | 26 | int 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 */ |
29 | void pcf50606_i2c_init(void); | ||
30 | void pcf50606_i2c_recalc_delay(int cpu_clock); | ||
30 | void pcf50606_i2c_start(void); | 31 | void pcf50606_i2c_start(void); |
31 | void pcf50606_i2c_stop(void); | 32 | void pcf50606_i2c_stop(void); |
32 | void pcf50606_i2c_ack(bool ack); | 33 | void pcf50606_i2c_ack(bool ack); |
@@ -34,4 +35,8 @@ bool pcf50606_i2c_getack(void); | |||
34 | void pcf50606_i2c_outb(unsigned char byte); | 35 | void pcf50606_i2c_outb(unsigned char byte); |
35 | unsigned char pcf50606_i2c_inb(bool ack); | 36 | unsigned char pcf50606_i2c_inb(bool ack); |
36 | 37 | ||
38 | #if defined(IAUDIO_X5) && !defined(SIMULATOR) | ||
39 | void 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" |
64 | extern 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 | |||
67 | static int i2c_delay IDATA_ATTR = 44; | ||
68 | |||
69 | void pcf50606_i2c_recalc_delay(int cpu_clock) | ||
70 | { | ||
71 | i2c_delay = MAX(cpu_clock / (400000*2*3) - 7, 1); | ||
72 | } | ||
73 | |||
74 | inline 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 | |||
124 | inline 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 | |||
165 | inline 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 | |||
218 | inline 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 | |||
277 | void 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 | |||
348 | unsigned 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 | |||
425 | int 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 | |||
451 | int 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 | |||
482 | int 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 | |||
494 | int 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 | |||
524 | int 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 */ |
531 | static void set_voltages(void) | 27 | static void set_voltages(void) |
@@ -572,13 +68,7 @@ static inline void enable_pmu_interrupts(void) | |||
572 | 68 | ||
573 | void pcf50606_init(void) | 69 | void 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) | |||
611 | void GPI0(void) __attribute__ ((interrupt_handler, section(".text"))); | 101 | void GPI0(void) __attribute__ ((interrupt_handler, section(".text"))); |
612 | void GPI0(void) | 102 | void 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 */ | ||
26 | static 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 | |||
40 | void 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 | |||
69 | void 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 | |||
80 | static int i2c_delay IDATA_ATTR = 44; | ||
81 | |||
82 | void pcf50606_i2c_recalc_delay(int cpu_clock) | ||
83 | { | ||
84 | i2c_delay = MAX(cpu_clock / (400000*2*3) - 7, 1); | ||
85 | } | ||
86 | |||
87 | inline 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 | |||
137 | inline 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 | |||
178 | inline 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 | |||
231 | inline 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 | |||
290 | void 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 | |||
361 | unsigned 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 | |||
438 | int 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 | |||
464 | int 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 | |||
495 | int 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 | |||
507 | int 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 | |||
537 | int pcf50606_write(int address, unsigned char val) | ||
538 | { | ||
539 | return pcf50606_write_multiple(address, &val, 1); | ||
540 | } | ||