summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/pcf50606.c538
1 files changed, 0 insertions, 538 deletions
diff --git a/firmware/drivers/pcf50606.c b/firmware/drivers/pcf50606.c
deleted file mode 100644
index 28df295988..0000000000
--- a/firmware/drivers/pcf50606.c
+++ /dev/null
@@ -1,538 +0,0 @@
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 "cpu.h"
21#include <stdbool.h>
22#include "kernel.h"
23#include "system.h"
24#include "hwcompat.h"
25#include "logf.h"
26#include "string.h"
27
28/* TODO: merge all bit-banged I2C into a generic I2C driver */
29
30#define USE_ASM
31
32#define SDA ( 0x00002000 & GPIO1_READ)
33#define SDA_LO_OUT or_l( 0x00002000, &GPIO1_ENABLE)
34#define SDA_HI_IN and_l(~0x00002000, &GPIO1_ENABLE)
35
36#define SCL ( 0x00001000 & GPIO_READ)
37#define SCL_LO_OUT or_l( 0x00001000, &GPIO_ENABLE)
38#define SCL_HI_IN and_l(~0x00001000, &GPIO_ENABLE); while(!SCL);
39
40#define DELAY \
41 asm ( \
42 "move.l %[dly],%%d0 \n" \
43 "1: \n" \
44 "subq.l #1,%%d0 \n" \
45 "bhi.s 1b \n" \
46 : : [dly]"d"(i2c_delay) : "d0" );
47
48static int i2c_delay IDATA_ATTR = 44;
49
50void pcf50606_i2c_recalc_delay(int cpu_clock)
51{
52 i2c_delay = MAX(cpu_clock / (400000*2*3) - 7, 1);
53}
54
55inline void pcf50606_i2c_start(void)
56{
57#ifdef USE_ASM
58 asm (
59 "not.l %[sdab] \n" /* SDA_HI_IN */
60 "and.l %[sdab],(8,%[gpi1]) \n"
61 "not.l %[sdab] \n"
62
63 "not.l %[sclb] \n" /* SCL_HI_IN */
64 "and.l %[sclb],(8,%[gpio]) \n"
65 "not.l %[sclb] \n"
66 "1: \n"
67 "move.l (%[gpio]),%%d0 \n"
68 "btst.l #12,%%d0 \n"
69 "beq.s 1b \n"
70
71 "move.l %[dly],%%d0 \n" /* DELAY */
72 "1: \n"
73 "subq.l #1,%%d0 \n"
74 "bhi.s 1b \n"
75
76 "or.l %[sdab],(8,%[gpi1]) \n" /* SDA_LO_OUT */
77
78 "move.l %[dly],%%d0 \n" /* DELAY */
79 "1: \n"
80 "subq.l #1,%%d0 \n"
81 "bhi.s 1b \n"
82
83 "or.l %[sclb],(8,%[gpio]) \n" /* SCL_LO_OUT */
84 : /* outputs */
85 : /* inputs */
86 [gpio]"a"(&GPIO_READ),
87 [sclb]"d"(0x00001000),
88 [gpi1]"a"(&GPIO1_READ),
89 [sdab]"d"(0x00002000),
90 [dly] "d"(i2c_delay)
91 : /* clobbers */
92 "d0"
93 );
94#else
95 SDA_HI_IN;
96 SCL_HI_IN;
97 DELAY;
98 SDA_LO_OUT;
99 DELAY;
100 SCL_LO_OUT;
101#endif
102}
103
104inline void pcf50606_i2c_stop(void)
105{
106#ifdef USE_ASM
107 asm (
108 "or.l %[sdab],(8,%[gpi1]) \n" /* SDA_LO_OUT */
109
110 "not.l %[sclb] \n" /* SCL_HI_IN */
111 "and.l %[sclb],(8,%[gpio]) \n"
112 "not.l %[sclb] \n"
113 "1: \n"
114 "move.l (%[gpio]),%%d0 \n"
115 "btst.l #12,%%d0 \n"
116 "beq.s 1b \n"
117
118 "move.l %[dly],%%d0 \n" /* DELAY */
119 "1: \n"
120 "subq.l #1,%%d0 \n"
121 "bhi.s 1b \n"
122
123 "not.l %[sdab] \n" /* SDA_HI_IN */
124 "and.l %[sdab],(8,%[gpi1]) \n"
125 "not.l %[sdab] \n"
126 : /* outputs */
127 : /* inputs */
128 [gpio]"a"(&GPIO_READ),
129 [sclb]"d"(0x00001000),
130 [gpi1]"a"(&GPIO1_READ),
131 [sdab]"d"(0x00002000),
132 [dly] "d"(i2c_delay)
133 : /* clobbers */
134 "d0"
135 );
136#else
137 SDA_LO_OUT;
138 SCL_HI_IN;
139 DELAY;
140 SDA_HI_IN;
141#endif
142}
143
144inline void pcf50606_i2c_ack(bool ack)
145{
146#ifdef USE_ASM
147 asm (
148 "tst.b %[ack] \n" /* if (!ack) */
149 "bne.s 1f \n"
150
151 "not.l %[sdab] \n" /* SDA_HI_IN */
152 "and.l %[sdab],(8,%[gpi1]) \n"
153 "not.l %[sdab] \n"
154 ".word 0x51fb \n" /* trapf.l : else */
155 "1: \n"
156 "or.l %[sdab],(8,%[gpi1]) \n" /* SDA_LO_OUT */
157
158 "not.l %[sclb] \n" /* SCL_HI_IN */
159 "and.l %[sclb],(8,%[gpio]) \n"
160 "not.l %[sclb] \n"
161 "1: \n"
162 "move.l (%[gpio]),%%d0 \n"
163 "btst.l #12,%%d0 \n"
164 "beq.s 1b \n"
165
166 "move.l %[dly],%%d0 \n" /* DELAY */
167 "1: \n"
168 "subq.l #1,%%d0 \n"
169 "bhi.s 1b \n"
170
171 "or.l %[sclb],(8,%[gpio]) \n" /* SCL_LO_OUT */
172 : /* outputs */
173 : /* inputs */
174 [gpio]"a"(&GPIO_READ),
175 [sclb]"d"(0x00001000),
176 [gpi1]"a"(&GPIO1_READ),
177 [sdab]"d"(0x00002000),
178 [dly] "d"(i2c_delay),
179 [ack] "d"(ack)
180 : /* clobbers */
181 "d0"
182 );
183#else
184 if(ack)
185 SDA_LO_OUT;
186 else
187 SDA_HI_IN;
188
189 SCL_HI_IN;
190
191 DELAY;
192 SCL_LO_OUT;
193#endif
194}
195
196inline bool pcf50606_i2c_getack(void)
197{
198 bool ret;
199
200#ifdef USE_ASM
201 asm (
202 "not.l %[sdab] \n" /* SDA_HI_IN */
203 "and.l %[sdab],(8,%[gpi1]) \n"
204 "not.l %[sdab] \n"
205
206 "move.l %[dly],%%d0 \n" /* DELAY */
207 "1: \n"
208 "subq.l #1,%%d0 \n"
209 "bhi.s 1b \n"
210
211 "not.l %[sclb] \n" /* SCL_HI_IN */
212 "and.l %[sclb],(8,%[gpio]) \n"
213 "not.l %[sclb] \n"
214 "1: \n"
215 "move.l (%[gpio]),%%d0 \n"
216 "btst.l #12,%%d0 \n"
217 "beq.s 1b \n"
218
219 "move.l (%[gpi1]),%%d0 \n" /* ret = !SDA */
220 "btst.l #13,%%d0 \n"
221 "seq.b %[ret] \n"
222
223 "or.l %[sclb],(8,%[gpio]) \n" /* SCL_LO_OUT */
224
225 "move.l %[dly],%%d0 \n" /* DELAY */
226 "1: \n"
227 "subq.l #1,%%d0 \n"
228 "bhi.s 1b \n"
229 : /* outputs */
230 [ret]"=&d"(ret)
231 : /* inputs */
232 [gpio]"a"(&GPIO_READ),
233 [sclb]"d"(0x00001000),
234 [gpi1]"a"(&GPIO1_READ),
235 [sdab]"d"(0x00002000),
236 [dly] "d"(i2c_delay)
237 : /* clobbers */
238 "d0"
239 );
240#else
241 SDA_HI_IN;
242 DELAY;
243 SCL_HI_IN;
244
245 ret = !SDA;
246
247 SCL_LO_OUT;
248 DELAY;
249#endif
250
251 return ret;
252}
253
254void pcf50606_i2c_outb(unsigned char byte)
255{
256#ifdef USE_ASM
257 asm volatile (
258 "moveq.l #24,%%d0 \n" /* byte <<= 24 */
259 "lsl.l %%d0,%[byte] \n"
260 "moveq.l #8,%%d1 \n" /* i = 8 */
261
262 "2: \n" /* do */
263 "lsl.l #1,%[byte] \n" /* if ((byte <<= 1) carry) */
264 "bcc.s 1f \n"
265
266 "not.l %[sdab] \n" /* SDA_HI_IN */
267 "and.l %[sdab],(8,%[gpi1]) \n"
268 "not.l %[sdab] \n"
269 ".word 0x51fb \n" /* trapf.l; else */
270 "1: \n"
271 "or.l %[sdab],(8,%[gpi1]) \n" /* SDA_LO_OUT */
272
273 "move.l %[dly],%%d0 \n" /* DELAY */
274 "1: \n"
275 "subq.l #1,%%d0 \n"
276 "bhi.s 1b \n"
277
278 "not.l %[sclb] \n" /* SCL_HI_IN */
279 "and.l %[sclb],(8,%[gpio]) \n"
280 "not.l %[sclb] \n"
281 "1: \n"
282 "move.l (%[gpio]),%%d0 \n"
283 "btst.l #12,%%d0 \n"
284 "beq.s 1b \n"
285
286 "move.l %[dly],%%d0 \n" /* DELAY */
287 "1: \n"
288 "subq.l #1,%%d0 \n"
289 "bhi.s 1b \n"
290
291 "or.l %[sclb],(8,%[gpio]) \n" /* SCL_LO_OUT */
292
293 "subq.l #1,%%d1 \n" /* i-- */
294 "bne.s 2b \n" /* while (i != 0) */
295 : /* outputs */
296 [byte]"+d"(byte)
297 : /* inputs */
298 [gpio]"a"(&GPIO_READ),
299 [sclb]"d"(0x00001000),
300 [gpi1]"a"(&GPIO1_READ),
301 [sdab]"d"(0x00002000),
302 [dly] "d"(i2c_delay)
303 : /* clobbers */
304 "d0", "d1"
305 );
306#else
307 int i;
308
309 /* clock out each bit, MSB first */
310 for ( i=0x80; i; i>>=1 )
311 {
312 if ( i & byte )
313 SDA_HI_IN;
314 else
315 SDA_LO_OUT;
316 DELAY;
317 SCL_HI_IN;
318 DELAY;
319 SCL_LO_OUT;
320 }
321#endif
322}
323
324unsigned char pcf50606_i2c_inb(bool ack)
325{
326 unsigned char byte = 0;
327
328#ifdef USE_ASM
329 asm (
330 "not.l %[sdab] \n" /* SDA_HI_IN */
331 "and.l %[sdab],(8,%[gpi1]) \n"
332 "not.l %[sdab] \n"
333
334 "moveq.l #8,%%d1 \n" /* i = 8 */
335 "clr.l %[byte] \n" /* byte = 0 */
336
337 "2: \n" /* do */
338 "not.l %[sclb] \n" /* SCL_HI_IN */
339 "and.l %[sclb],(8,%[gpio]) \n"
340 "not.l %[sclb] \n"
341 "1: \n"
342 "move.l (%[gpio]),%%d0 \n"
343 "btst.l #12,%%d0 \n"
344 "beq.s 1b \n"
345
346 "move.l %[dly],%%d0 \n" /* DELAY */
347 "1: \n"
348 "subq.l #1,%%d0 \n"
349 "bhi.s 1b \n"
350
351 "lsl.l #1,%[byte] \n" /* byte <<= 1 */
352 "move.l (%[gpi1]),%%d0 \n" /* if (SDA) */
353 "btst.l #13,%%d0 \n"
354 "beq.s 1f \n"
355 "addq.l #1,%[byte] \n" /* byte++ */
356 "1: \n"
357
358 "or.l %[sclb],(8,%[gpio]) \n" /* SCL_LO_OUT */
359
360 "move.l %[dly],%%d0 \n" /* DELAY */
361 "1: \n"
362 "subq.l #1,%%d0 \n"
363 "bhi.s 1b \n"
364
365 "subq.l #1,%%d1 \n" /* i-- */
366 "bne.s 2b \n" /* while (i != 0) */
367 : /* outputs */
368 [byte]"=&d"(byte)
369 : /* inputs */
370 [gpio]"a"(&GPIO_READ),
371 [sclb]"d"(0x00001000),
372 [gpi1]"a"(&GPIO1_READ),
373 [sdab]"d"(0x00002000),
374 [dly] "d"(i2c_delay)
375 : /* clobbers */
376 "d0", "d1"
377 );
378#else
379 int i;
380
381 /* clock in each bit, MSB first */
382 SDA_HI_IN;
383 for ( i=0x80; i; i>>=1 )
384 {
385 SCL_HI_IN;
386 DELAY;
387 if ( SDA )
388 byte |= i;
389 SCL_LO_OUT;
390 DELAY;
391 }
392#endif
393
394 pcf50606_i2c_ack(ack);
395
396 return byte;
397}
398
399int pcf50606_i2c_write(int address, const unsigned char* buf, int count)
400{
401 int i,x=0;
402
403 pcf50606_i2c_start();
404 pcf50606_i2c_outb(address & 0xfe);
405 if (pcf50606_i2c_getack())
406 {
407 for (i=0; i<count; i++)
408 {
409 pcf50606_i2c_outb(buf[i]);
410 if (!pcf50606_i2c_getack())
411 {
412 x=-2;
413 break;
414 }
415 }
416 }
417 else
418 {
419 logf("pcf50606_i2c_write() - no ack\n");
420 x=-1;
421 }
422 return x;
423}
424
425int pcf50606_read_multiple(int address, unsigned char* buf, int count)
426{
427 int i=0;
428 int ret = 0;
429 unsigned char obuf[1];
430
431 obuf[0] = address;
432
433 /* send read command */
434 if (pcf50606_i2c_write(0x10, obuf, 1) >= 0)
435 {
436 pcf50606_i2c_start();
437 pcf50606_i2c_outb(0x11);
438 if (pcf50606_i2c_getack())
439 {
440 for(i = 0;i < count-1;i++)
441 buf[i] = pcf50606_i2c_inb(true);
442
443 buf[i] = pcf50606_i2c_inb(false);
444 }
445 else
446 {
447 ret = -1;
448 }
449 }
450
451 pcf50606_i2c_stop();
452
453 return ret;
454}
455
456int pcf50606_read(int address)
457{
458 int ret;
459 unsigned char c;
460
461 ret = pcf50606_read_multiple(address, &c, 1);
462 if(ret >= 0)
463 return c;
464 else
465 return ret;
466}
467
468int pcf50606_write_multiple(int address, const unsigned char* buf, int count)
469{
470 unsigned char obuf[1];
471 int i;
472 int ret = 0;
473
474 obuf[0] = address;
475
476 /* send write command */
477 if (pcf50606_i2c_write(0x10, obuf, 1) >= 0)
478 {
479 for (i=0; i<count; i++)
480 {
481 pcf50606_i2c_outb(buf[i]);
482 if (!pcf50606_i2c_getack())
483 {
484 ret = -2;
485 break;
486 }
487 }
488 }
489 else
490 {
491 ret = -1;
492 }
493
494 pcf50606_i2c_stop();
495 return ret;
496}
497
498int pcf50606_write(int address, unsigned char val)
499{
500 return pcf50606_write_multiple(address, &val, 1);
501}
502
503
504/* These voltages were determined by measuring the output of the PCF50606
505 on a running H300, and verified by disassembling the original firmware */
506static void set_voltages(void)
507{
508 static const unsigned char buf[5] =
509 {
510 0xf4, /* IOREGC = 2.9V, ON in all states */
511 0xef, /* D1REGC = 2.4V, ON in all states */
512 0x18, /* D2REGC = 3.3V, OFF in all states */
513 0xf0, /* D3REGC = 2.5V, ON in all states */
514 0xef, /* LPREGC1 = 2.4V, ON in all states */
515 };
516
517 pcf50606_write_multiple(0x23, buf, 5);
518}
519
520void pcf50606_init(void)
521{
522 /* Bit banged I2C */
523 or_l(0x00002000, &GPIO1_FUNCTION);
524 or_l(0x00001000, &GPIO_FUNCTION);
525 and_l(~0x00002000, &GPIO1_OUT);
526 and_l(~0x00001000, &GPIO_OUT);
527 and_l(~0x00002000, &GPIO1_ENABLE);
528 and_l(~0x00001000, &GPIO_ENABLE);
529
530 set_voltages();
531
532 pcf50606_write(0x08, 0x60); /* Wake on USB and charger insertion */
533 pcf50606_write(0x09, 0x05); /* USB and ON key debounce: 14ms */
534 pcf50606_write(0x29, 0x1C); /* Disable the unused MBC module */
535
536 pcf50606_write(0x35, 0x13); /* Backlight PWM = 512Hz 50/50 */
537 pcf50606_write(0x3a, 0x3b); /* PWM output on GPOOD1 */
538}