summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
#if CONFIG_CODEC != SWCODEC
drivers/mas.c
#endif
-#ifdef IRIVER_H300_SERIES
-drivers/pcf50606.c
-#endif
#ifdef HAVE_EEPROM
drivers/eeprom_24cxx.c
#ifdef HAVE_EEPROM_SETTINGS
@@ -242,6 +239,7 @@ target/coldfire/iaudio/x5/power-x5.c
target/coldfire/iaudio/x5/button-x5.c
target/coldfire/iaudio/x5/lcd-as-x5.S
target/coldfire/iaudio/x5/lcd-x5.c
+target/coldfire/pcf50606-coldfire.c
target/coldfire/iaudio/x5/pcf50606-x5.c
target/coldfire/iaudio/x5/adc-x5.c
target/coldfire/iaudio/x5/ata-x5.c
@@ -256,6 +254,8 @@ target/coldfire/iaudio/x5/lcd-remote-x5.c
#ifdef IRIVER_H300_SERIES
#ifndef SIMULATOR
target/coldfire/iriver/h300/lcd-as-h300.S
+target/coldfire/pcf50606-coldfire.c
+target/coldfire/iriver/h300/pcf50606-h300.c
#endif
#endif
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 @@
#define PCF50606_H
void pcf50606_init(void);
-void pcf50606_i2c_recalc_delay(int cpu_clock);
int pcf50606_write_multiple(int address, const unsigned char* buf, int count);
int pcf50606_write(int address, unsigned char val);
int pcf50606_read_multiple(int address, unsigned char* buf, int count);
int pcf50606_read(int address);
/* internal low level calls used by the eeprom driver for h300 */
+void pcf50606_i2c_init(void);
+void pcf50606_i2c_recalc_delay(int cpu_clock);
void pcf50606_i2c_start(void);
void pcf50606_i2c_stop(void);
void pcf50606_i2c_ack(bool ack);
@@ -34,4 +35,8 @@ bool pcf50606_i2c_getack(void);
void pcf50606_i2c_outb(unsigned char byte);
unsigned char pcf50606_i2c_inb(bool ack);
+#if defined(IAUDIO_X5) && !defined(SIMULATOR)
+void pcf50606_reset_timeout(void);
#endif
+
+#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 @@
#include <time.h>
#endif
-#ifdef IAUDIO_X5
-#ifndef SIMULATOR
-extern void pcf50606_reset_timeout(void);
-#endif
+#if defined(IAUDIO_X5) && !defined (SIMULATOR)
+#include "pcf50606.h"
#endif
/*
@@ -1033,13 +1031,11 @@ void cancel_shutdown(void)
{
logf("sys_cancel_shutdown()");
-#ifdef IAUDIO_X5
-#ifndef SIMULATOR
+#if defined(IAUDIO_X5) && !defined (SIMULATOR)
/* TODO: Move some things to target/ tree */
if (shutdown_timeout)
pcf50606_reset_timeout();
#endif
-#endif
shutdown_timeout = 0;
}
@@ -1076,10 +1072,8 @@ void shutdown_hw(void)
backlight_set_fade_out(0);
#endif
backlight_off();
-#endif /* IAUDIO_X5 */
-#ifndef IAUDIO_X5
lcd_set_contrast(0);
-#endif
+#endif /* IAUDIO_X5 */
#ifdef HAVE_REMOTE_LCD
remote_backlight_off();
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 @@
*
****************************************************************************/
#include "config.h"
-#include "cpu.h"
-#include <stdbool.h>
-#include "kernel.h"
#include "system.h"
-#include "hwcompat.h"
-#include "logf.h"
-#include "debug.h"
-#include "string.h"
-#include "generic_i2c.h"
+#include "kernel.h"
+#include "pcf50606.h"
#include "powermgmt.h"
-#define USE_ASM
-
-/* Data */
-#define SDA_BITNUM 12 /* SDA1/RXD1/GPIO44 */
-#define SDA_GPIO_READ GPIO1_READ /* MBAR2 + 0x0b0 */
-#define SDA_GPIO_OUT GPIO1_OUT /* MBAR2 + 0x0b4 */
-#define SDA_GPIO_ENABLE GPIO1_ENABLE /* MBAR2 + 0x0b8 */
-#define SDA_GPIO_FUNCTION GPIO1_FUNCTION /* MBAR2 + 0x0bc */
-
-/* Clock */
-#define SCL_BITNUM 10 /* SCL1/TXD1/GPIO10 */
-#define SCL_GPIO_READ GPIO_READ /* MBAR2 + 0x000 */
-#define SCL_GPIO_OUT GPIO_OUT /* MBAR2 + 0x004 */
-#define SCL_GPIO_ENABLE GPIO_ENABLE /* MBAR2 + 0x008 */
-#define SCL_GPIO_FUNCTION GPIO_FUNCTION /* MBAR2 + 0x00c */
-
-#define PCF50606_ADDR 0x10
-#define SCL_BIT (1ul << SCL_BITNUM)
-#define SDA_BIT (1ul << SDA_BITNUM)
-
-#define SDA ( SDA_BIT & SDA_GPIO_READ)
-#define SDA_LO_OUT or_l( SDA_BIT, &SDA_GPIO_ENABLE)
-#define SDA_HI_IN and_l(~SDA_BIT, &SDA_GPIO_ENABLE)
-
-#define SCL ( SCL_BIT & SCL_GPIO_READ)
-#define SCL_LO_OUT or_l( SCL_BIT, &SCL_GPIO_ENABLE)
-#define SCL_HI_IN and_l(~SCL_BIT, &SCL_GPIO_ENABLE); while(!SCL);
-
-#define DELAY \
- asm ( \
- "move.l %[dly],%%d0 \n" \
- "1: \n" \
- "subq.l #1,%%d0 \n" \
- "bhi.s 1b \n" \
- : : [dly]"d"(i2c_delay) : "d0" );
-
-static int i2c_delay IDATA_ATTR = 44;
-
-void pcf50606_i2c_recalc_delay(int cpu_clock)
-{
- i2c_delay = MAX(cpu_clock / (400000*2*3) - 7, 1);
-}
-
-inline void pcf50606_i2c_start(void)
-{
-#ifdef USE_ASM
- asm (
- "not.l %[sdab] \n" /* SDA_HI_IN */
- "and.l %[sdab],(8,%[sdard]) \n"
- "not.l %[sdab] \n"
-
- "not.l %[sclb] \n" /* SCL_HI_IN */
- "and.l %[sclb],(8,%[sclrd]) \n"
- "not.l %[sclb] \n"
- "1: \n"
- "move.l (%[sclrd]),%%d0 \n"
- "btst.l %[sclbnum], %%d0 \n"
- "beq.s 1b \n"
-
- "move.l %[dly],%%d0 \n" /* DELAY */
- "1: \n"
- "subq.l #1,%%d0 \n"
- "bhi.s 1b \n"
-
- "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
-
- "move.l %[dly],%%d0 \n" /* DELAY */
- "1: \n"
- "subq.l #1,%%d0 \n"
- "bhi.s 1b \n"
-
- "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
- : /* outputs */
- : /* inputs */
- [sclrd] "a"(&SCL_GPIO_READ),
- [sclb] "d"(SCL_BIT),
- [sclbnum] "i"(SCL_BITNUM),
- [sdard] "a"(&SDA_GPIO_READ),
- [sdab] "d"(SDA_BIT),
- [dly] "d"(i2c_delay)
- : /* clobbers */
- "d0"
- );
-#else
- SDA_HI_IN;
- SCL_HI_IN;
- DELAY;
- SDA_LO_OUT;
- DELAY;
- SCL_LO_OUT;
-#endif
-}
-
-inline void pcf50606_i2c_stop(void)
-{
-#ifdef USE_ASM
- asm (
- "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
-
- "not.l %[sclb] \n" /* SCL_HI_IN */
- "and.l %[sclb],(8,%[sclrd]) \n"
- "not.l %[sclb] \n"
- "1: \n"
- "move.l (%[sclrd]),%%d0 \n"
- "btst.l %[sclbnum],%%d0 \n"
- "beq.s 1b \n"
-
- "move.l %[dly],%%d0 \n" /* DELAY */
- "1: \n"
- "subq.l #1,%%d0 \n"
- "bhi.s 1b \n"
-
- "not.l %[sdab] \n" /* SDA_HI_IN */
- "and.l %[sdab],(8,%[sdard]) \n"
- "not.l %[sdab] \n"
- : /* outputs */
- : /* inputs */
- [sclrd] "a"(&SCL_GPIO_READ),
- [sclb] "d"(SCL_BIT),
- [sclbnum] "i"(SCL_BITNUM),
- [sdard] "a"(&SDA_GPIO_READ),
- [sdab] "d"(SDA_BIT),
- [dly] "d"(i2c_delay)
- : /* clobbers */
- "d0"
- );
-#else
- SDA_LO_OUT;
- SCL_HI_IN;
- DELAY;
- SDA_HI_IN;
-#endif
-}
-
-inline void pcf50606_i2c_ack(bool ack)
-{
-#ifdef USE_ASM
- asm (
- "tst.b %[ack] \n" /* if (!ack) */
- "bne.s 1f \n"
-
- "not.l %[sdab] \n" /* SDA_HI_IN */
- "and.l %[sdab],(8,%[sdard]) \n"
- "not.l %[sdab] \n"
- ".word 0x51fb \n" /* trapf.l : else */
- "1: \n"
- "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
-
- "not.l %[sclb] \n" /* SCL_HI_IN */
- "and.l %[sclb],(8,%[sclrd]) \n"
- "not.l %[sclb] \n"
- "1: \n"
- "move.l (%[sclrd]),%%d0 \n"
- "btst.l %[sclbnum],%%d0 \n"
- "beq.s 1b \n"
-
- "move.l %[dly],%%d0 \n" /* DELAY */
- "1: \n"
- "subq.l #1,%%d0 \n"
- "bhi.s 1b \n"
-
- "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
- : /* outputs */
- : /* inputs */
- [sclrd] "a"(&SCL_GPIO_READ),
- [sclb] "d"(SCL_BIT),
- [sclbnum] "i"(SCL_BITNUM),
- [sdard] "a"(&SDA_GPIO_READ),
- [sdab] "d"(SDA_BIT),
- [dly] "d"(i2c_delay),
- [ack] "d"(ack)
- : /* clobbers */
- "d0"
- );
-#else
- if(ack)
- SDA_LO_OUT;
- else
- SDA_HI_IN;
-
- SCL_HI_IN;
-
- DELAY;
- SCL_LO_OUT;
-#endif
-}
-
-inline bool pcf50606_i2c_getack(void)
-{
- bool ret;
-
-#ifdef USE_ASM
- asm (
- "not.l %[sdab] \n" /* SDA_HI_IN */
- "and.l %[sdab],(8,%[sdard]) \n"
- "not.l %[sdab] \n"
-
- "move.l %[dly],%%d0 \n" /* DELAY */
- "1: \n"
- "subq.l #1,%%d0 \n"
- "bhi.s 1b \n"
-
- "not.l %[sclb] \n" /* SCL_HI_IN */
- "and.l %[sclb],(8,%[sclrd]) \n"
- "not.l %[sclb] \n"
- "1: \n"
- "move.l (%[sclrd]),%%d0 \n"
- "btst.l %[sclbnum],%%d0 \n"
- "beq.s 1b \n"
-
- "move.l (%[sdard]),%%d0 \n" /* ret = !SDA */
- "btst.l %[sdabnum],%%d0 \n"
- "seq.b %[ret] \n"
-
- "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
-
- "move.l %[dly],%%d0 \n" /* DELAY */
- "1: \n"
- "subq.l #1,%%d0 \n"
- "bhi.s 1b \n"
- : /* outputs */
- [ret] "=&d"(ret)
- : /* inputs */
- [sclrd] "a"(&SCL_GPIO_READ),
- [sclb] "d"(SCL_BIT),
- [sclbnum] "i"(SCL_BITNUM),
- [sdard] "a"(&SDA_GPIO_READ),
- [sdab] "d"(SDA_BIT),
- [sdabnum] "i"(SDA_BITNUM),
- [dly] "d"(i2c_delay)
- : /* clobbers */
- "d0"
- );
-#else
- SDA_HI_IN;
- DELAY;
- SCL_HI_IN;
-
- ret = !SDA;
-
- SCL_LO_OUT;
- DELAY;
-#endif
- return ret;
-}
-
-void pcf50606_i2c_outb(unsigned char byte)
-{
-#ifdef USE_ASM
- asm volatile (
- "moveq.l #24,%%d0 \n" /* byte <<= 24 */
- "lsl.l %%d0,%[byte] \n"
- "moveq.l #8,%%d1 \n" /* i = 8 */
-
- "2: \n" /* do */
- "lsl.l #1,%[byte] \n" /* if ((byte <<= 1) carry) */
- "bcc.s 1f \n"
-
- "not.l %[sdab] \n" /* SDA_HI_IN */
- "and.l %[sdab],(8,%[sdard]) \n"
- "not.l %[sdab] \n"
- ".word 0x51fb \n" /* trapf.l; else */
- "1: \n"
- "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
-
- "move.l %[dly],%%d0 \n" /* DELAY */
- "1: \n"
- "subq.l #1,%%d0 \n"
- "bhi.s 1b \n"
-
- "not.l %[sclb] \n" /* SCL_HI_IN */
- "and.l %[sclb],(8,%[sclrd]) \n"
- "not.l %[sclb] \n"
- "1: \n"
- "move.l (%[sclrd]),%%d0 \n"
- "btst.l %[sclbnum],%%d0 \n"
- "beq.s 1b \n"
-
- "move.l %[dly],%%d0 \n" /* DELAY */
- "1: \n"
- "subq.l #1,%%d0 \n"
- "bhi.s 1b \n"
-
- "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
-
- "subq.l #1,%%d1 \n" /* i-- */
- "bne.s 2b \n" /* while (i != 0) */
- : /* outputs */
- [byte] "+d"(byte)
- : /* inputs */
- [sclrd] "a"(&SCL_GPIO_READ),
- [sclb] "d"(SCL_BIT),
- [sclbnum] "i"(SCL_BITNUM),
- [sdard] "a"(&SDA_GPIO_READ),
- [sdab] "d"(SDA_BIT),
- [dly] "d"(i2c_delay)
- : /* clobbers */
- "d0", "d1"
- );
-#else
- int i;
-
- /* clock out each bit, MSB first */
- for ( i=0x80; i; i>>=1 )
- {
- if ( i & byte )
- SDA_HI_IN;
- else
- SDA_LO_OUT;
- DELAY;
- SCL_HI_IN;
- DELAY;
- SCL_LO_OUT;
- }
-#endif
-}
-
-unsigned char pcf50606_i2c_inb(bool ack)
-{
- unsigned char byte = 0;
-
-#ifdef USE_ASM
- asm (
- "not.l %[sdab] \n" /* SDA_HI_IN */
- "and.l %[sdab],(8,%[sdard]) \n"
- "not.l %[sdab] \n"
-
- "moveq.l #8,%%d1 \n" /* i = 8 */
- "clr.l %[byte] \n" /* byte = 0 */
-
- "2: \n" /* do */
- "not.l %[sclb] \n" /* SCL_HI_IN */
- "and.l %[sclb],(8,%[sclrd]) \n"
- "not.l %[sclb] \n"
- "1: \n"
- "move.l (%[sclrd]),%%d0 \n"
- "btst.l %[sclbnum],%%d0 \n"
- "beq.s 1b \n"
-
- "move.l %[dly],%%d0 \n" /* DELAY */
- "1: \n"
- "subq.l #1,%%d0 \n"
- "bhi.s 1b \n"
-
- "lsl.l #1,%[byte] \n" /* byte <<= 1 */
- "move.l (%[sdard]),%%d0 \n" /* if (SDA) */
- "btst.l %[sdabnum],%%d0 \n"
- "beq.s 1f \n"
- "addq.l #1,%[byte] \n" /* byte++ */
- "1: \n"
-
- "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
-
- "move.l %[dly],%%d0 \n" /* DELAY */
- "1: \n"
- "subq.l #1,%%d0 \n"
- "bhi.s 1b \n"
-
- "subq.l #1,%%d1 \n" /* i-- */
- "bne.s 2b \n" /* while (i != 0) */
- : /* outputs */
- [byte] "=&d"(byte)
- : /* inputs */
- [sclrd] "a"(&SCL_GPIO_READ),
- [sclb] "d"(SCL_BIT),
- [sclbnum] "i"(SCL_BITNUM),
- [sdard] "a"(&SDA_GPIO_READ),
- [sdab] "d"(SDA_BIT),
- [sdabnum] "i"(SDA_BITNUM),
- [dly] "d"(i2c_delay)
- : /* clobbers */
- "d0", "d1"
- );
-#else
- int i;
-
- /* clock in each bit, MSB first */
- SDA_HI_IN;
- for ( i=0x80; i; i>>=1 )
- {
- SCL_HI_IN;
- DELAY;
- if ( SDA )
- byte |= i;
- SCL_LO_OUT;
- DELAY;
- }
-#endif
-
- pcf50606_i2c_ack(ack);
-
- return byte;
-}
-
-int pcf50606_i2c_write(int address, const unsigned char* buf, int count)
-{
- int i,x=0;
-
- pcf50606_i2c_start();
- pcf50606_i2c_outb(address & 0xfe);
- if (pcf50606_i2c_getack())
- {
- for (i=0; i<count; i++)
- {
- pcf50606_i2c_outb(buf[i]);
- if (!pcf50606_i2c_getack())
- {
- x=-2;
- break;
- }
- }
- }
- else
- {
- logf("pcf50606_i2c_write() - no ack\n");
- x=-1;
- }
- return x;
-}
-
-int pcf50606_read_multiple(int address, unsigned char* buf, int count)
-{
- int i=0;
- int ret = 0;
- unsigned char obuf[1];
-
- obuf[0] = address;
-
- /* send read command */
- if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
- {
- pcf50606_i2c_start();
- pcf50606_i2c_outb(0x11);
- if (pcf50606_i2c_getack())
- {
- for(i = 0;i < count-1;i++)
- buf[i] = pcf50606_i2c_inb(true);
-
- buf[i] = pcf50606_i2c_inb(false);
- }
- else
- {
- ret = -1;
- }
- }
-
- pcf50606_i2c_stop();
-
- return ret;
-}
-
-int pcf50606_read(int address)
-{
- int ret;
- unsigned char c;
-
- ret = pcf50606_read_multiple(address, &c, 1);
- if(ret >= 0)
- return c;
- else
- return ret;
-}
-
-int pcf50606_write_multiple(int address, const unsigned char* buf, int count)
-{
- unsigned char obuf[1];
- int i;
- int ret = 0;
-
- obuf[0] = address;
-
- /* send write command */
- if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
- {
- for (i=0; i<count; i++)
- {
- pcf50606_i2c_outb(buf[i]);
- if (!pcf50606_i2c_getack())
- {
- ret = -2;
- break;
- }
- }
- }
- else
- {
- ret = -1;
- }
-
- pcf50606_i2c_stop();
- return ret;
-}
-
-int pcf50606_write(int address, unsigned char val)
-{
- return pcf50606_write_multiple(address, &val, 1);
-}
-
/* These voltages were determined by measuring the output of the PCF50606
on a running X5, and verified by disassembling the original firmware */
static void set_voltages(void)
@@ -572,13 +68,7 @@ static inline void enable_pmu_interrupts(void)
void pcf50606_init(void)
{
- /* Bit banged I2C */
- or_l(SDA_BIT, &SDA_GPIO_FUNCTION);
- or_l(SCL_BIT, &SCL_GPIO_FUNCTION);
- and_l(~SDA_BIT, &SDA_GPIO_OUT);
- and_l(~SCL_BIT, &SCL_GPIO_OUT);
- and_l(~SDA_BIT, &SDA_GPIO_ENABLE);
- and_l(~SCL_BIT, &SCL_GPIO_ENABLE);
+ pcf50606_i2c_init();
/* initialize pmu interrupts but don't service them yet */
init_pmu_interrupts();
@@ -611,7 +101,7 @@ void pcf50606_reset_timeout(void)
void GPI0(void) __attribute__ ((interrupt_handler, section(".text")));
void GPI0(void)
{
- char read[3]; /* 0 = INT1, 1 = INT2, 2 = INT3 */
+ unsigned char read[3]; /* 0 = INT1, 1 = INT2, 2 = INT3 */
/* clear pending interrupts from pcf50606 */
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 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Linus Nielsen Feltzing
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include "system.h"
+#include "kernel.h"
+#include "pcf50606.h"
+
+/* These voltages were determined by measuring the output of the PCF50606
+ on a running H300, and verified by disassembling the original firmware */
+static void set_voltages(void)
+{
+ static const unsigned char buf[5] =
+ {
+ 0xf4, /* IOREGC = 2.9V, ON in all states */
+ 0xef, /* D1REGC = 2.4V, ON in all states */
+ 0x18, /* D2REGC = 3.3V, OFF in all states */
+ 0xf0, /* D3REGC = 2.5V, ON in all states */
+ 0xef, /* LPREGC1 = 2.4V, ON in all states */
+ };
+
+ pcf50606_write_multiple(0x23, buf, 5);
+}
+
+void pcf50606_init(void)
+{
+ pcf50606_i2c_init();
+
+ set_voltages();
+
+ pcf50606_write(0x08, 0x60); /* Wake on USB and charger insertion */
+ pcf50606_write(0x09, 0x05); /* USB and ON key debounce: 14ms */
+ pcf50606_write(0x29, 0x1C); /* Disable the unused MBC module */
+
+ pcf50606_write(0x35, 0x13); /* Backlight PWM = 512Hz 50/50 */
+ pcf50606_write(0x3a, 0x3b); /* PWM output on GPOOD1 */
+}
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 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 by Linus Nielsen Feltzing
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include "system.h"
+#include "logf.h"
+#include "kernel.h"
+#include "pcf50606.h"
+
+#define USE_ASM
+
+/* Define the approprate bits for SDA and SCL being the only difference in
+ config between each player. */
+#if defined(IRIVER_H300_SERIES)
+#define SDA_BITNUM 13 /* LRCK3/GPIO45 */
+#define SCL_BITNUM 12 /* SWE/GPIO12 */
+#elif defined(IAUDIO_X5)
+#define SDA_BITNUM 12 /* SDA1/RXD1/GPIO44 */
+#define SCL_BITNUM 10 /* SCL1/TXD1/GPIO10 */
+#endif
+
+/* Data */
+#define SDA_GPIO_READ GPIO1_READ /* MBAR2 + 0x0b0 */
+#define SDA_GPIO_OUT GPIO1_OUT /* MBAR2 + 0x0b4 */
+#define SDA_GPIO_ENABLE GPIO1_ENABLE /* MBAR2 + 0x0b8 */
+#define SDA_GPIO_FUNCTION GPIO1_FUNCTION /* MBAR2 + 0x0bc */
+
+/* Clock */
+#define SCL_GPIO_READ GPIO_READ /* MBAR2 + 0x000 */
+#define SCL_GPIO_OUT GPIO_OUT /* MBAR2 + 0x004 */
+#define SCL_GPIO_ENABLE GPIO_ENABLE /* MBAR2 + 0x008 */
+#define SCL_GPIO_FUNCTION GPIO_FUNCTION /* MBAR2 + 0x00c */
+
+#define PCF50606_ADDR 0x10
+#define SCL_BIT (1ul << SCL_BITNUM)
+#define SDA_BIT (1ul << SDA_BITNUM)
+
+#define SDA ( SDA_BIT & SDA_GPIO_READ)
+#define SDA_LO_OUT or_l( SDA_BIT, &SDA_GPIO_ENABLE)
+#define SDA_HI_IN and_l(~SDA_BIT, &SDA_GPIO_ENABLE)
+
+#define SCL ( SCL_BIT & SCL_GPIO_READ)
+#define SCL_LO_OUT or_l( SCL_BIT, &SCL_GPIO_ENABLE)
+#define SCL_HI_IN and_l(~SCL_BIT, &SCL_GPIO_ENABLE); while(!SCL);
+
+#define DELAY \
+ asm ( \
+ "move.l %[dly],%%d0 \n" \
+ "1: \n" \
+ "subq.l #1,%%d0 \n" \
+ "bhi.s 1b \n" \
+ : : [dly]"d"(i2c_delay) : "d0" );
+
+void pcf50606_i2c_init(void)
+{
+ /* Bit banged I2C */
+ or_l(SDA_BIT, &SDA_GPIO_FUNCTION);
+ or_l(SCL_BIT, &SCL_GPIO_FUNCTION);
+ and_l(~SDA_BIT, &SDA_GPIO_OUT);
+ and_l(~SCL_BIT, &SCL_GPIO_OUT);
+ and_l(~SDA_BIT, &SDA_GPIO_ENABLE);
+ and_l(~SCL_BIT, &SCL_GPIO_ENABLE);
+}
+
+static int i2c_delay IDATA_ATTR = 44;
+
+void pcf50606_i2c_recalc_delay(int cpu_clock)
+{
+ i2c_delay = MAX(cpu_clock / (400000*2*3) - 7, 1);
+}
+
+inline void pcf50606_i2c_start(void)
+{
+#ifdef USE_ASM
+ asm (
+ "not.l %[sdab] \n" /* SDA_HI_IN */
+ "and.l %[sdab],(8,%[sdard]) \n"
+ "not.l %[sdab] \n"
+
+ "not.l %[sclb] \n" /* SCL_HI_IN */
+ "and.l %[sclb],(8,%[sclrd]) \n"
+ "not.l %[sclb] \n"
+ "1: \n"
+ "move.l (%[sclrd]),%%d0 \n"
+ "btst.l %[sclbnum], %%d0 \n"
+ "beq.s 1b \n"
+
+ "move.l %[dly],%%d0 \n" /* DELAY */
+ "1: \n"
+ "subq.l #1,%%d0 \n"
+ "bhi.s 1b \n"
+
+ "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
+
+ "move.l %[dly],%%d0 \n" /* DELAY */
+ "1: \n"
+ "subq.l #1,%%d0 \n"
+ "bhi.s 1b \n"
+
+ "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
+ : /* outputs */
+ : /* inputs */
+ [sclrd] "a"(&SCL_GPIO_READ),
+ [sclb] "d"(SCL_BIT),
+ [sclbnum] "i"(SCL_BITNUM),
+ [sdard] "a"(&SDA_GPIO_READ),
+ [sdab] "d"(SDA_BIT),
+ [dly] "d"(i2c_delay)
+ : /* clobbers */
+ "d0"
+ );
+#else
+ SDA_HI_IN;
+ SCL_HI_IN;
+ DELAY;
+ SDA_LO_OUT;
+ DELAY;
+ SCL_LO_OUT;
+#endif
+}
+
+inline void pcf50606_i2c_stop(void)
+{
+#ifdef USE_ASM
+ asm (
+ "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
+
+ "not.l %[sclb] \n" /* SCL_HI_IN */
+ "and.l %[sclb],(8,%[sclrd]) \n"
+ "not.l %[sclb] \n"
+ "1: \n"
+ "move.l (%[sclrd]),%%d0 \n"
+ "btst.l %[sclbnum],%%d0 \n"
+ "beq.s 1b \n"
+
+ "move.l %[dly],%%d0 \n" /* DELAY */
+ "1: \n"
+ "subq.l #1,%%d0 \n"
+ "bhi.s 1b \n"
+
+ "not.l %[sdab] \n" /* SDA_HI_IN */
+ "and.l %[sdab],(8,%[sdard]) \n"
+ "not.l %[sdab] \n"
+ : /* outputs */
+ : /* inputs */
+ [sclrd] "a"(&SCL_GPIO_READ),
+ [sclb] "d"(SCL_BIT),
+ [sclbnum] "i"(SCL_BITNUM),
+ [sdard] "a"(&SDA_GPIO_READ),
+ [sdab] "d"(SDA_BIT),
+ [dly] "d"(i2c_delay)
+ : /* clobbers */
+ "d0"
+ );
+#else
+ SDA_LO_OUT;
+ SCL_HI_IN;
+ DELAY;
+ SDA_HI_IN;
+#endif
+}
+
+inline void pcf50606_i2c_ack(bool ack)
+{
+#ifdef USE_ASM
+ asm (
+ "tst.b %[ack] \n" /* if (!ack) */
+ "bne.s 1f \n"
+
+ "not.l %[sdab] \n" /* SDA_HI_IN */
+ "and.l %[sdab],(8,%[sdard]) \n"
+ "not.l %[sdab] \n"
+ ".word 0x51fb \n" /* trapf.l : else */
+ "1: \n"
+ "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
+
+ "not.l %[sclb] \n" /* SCL_HI_IN */
+ "and.l %[sclb],(8,%[sclrd]) \n"
+ "not.l %[sclb] \n"
+ "1: \n"
+ "move.l (%[sclrd]),%%d0 \n"
+ "btst.l %[sclbnum],%%d0 \n"
+ "beq.s 1b \n"
+
+ "move.l %[dly],%%d0 \n" /* DELAY */
+ "1: \n"
+ "subq.l #1,%%d0 \n"
+ "bhi.s 1b \n"
+
+ "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
+ : /* outputs */
+ : /* inputs */
+ [sclrd] "a"(&SCL_GPIO_READ),
+ [sclb] "d"(SCL_BIT),
+ [sclbnum] "i"(SCL_BITNUM),
+ [sdard] "a"(&SDA_GPIO_READ),
+ [sdab] "d"(SDA_BIT),
+ [dly] "d"(i2c_delay),
+ [ack] "d"(ack)
+ : /* clobbers */
+ "d0"
+ );
+#else
+ if(ack)
+ SDA_LO_OUT;
+ else
+ SDA_HI_IN;
+
+ SCL_HI_IN;
+
+ DELAY;
+ SCL_LO_OUT;
+#endif
+}
+
+inline bool pcf50606_i2c_getack(void)
+{
+ bool ret;
+
+#ifdef USE_ASM
+ asm (
+ "not.l %[sdab] \n" /* SDA_HI_IN */
+ "and.l %[sdab],(8,%[sdard]) \n"
+ "not.l %[sdab] \n"
+
+ "move.l %[dly],%%d0 \n" /* DELAY */
+ "1: \n"
+ "subq.l #1,%%d0 \n"
+ "bhi.s 1b \n"
+
+ "not.l %[sclb] \n" /* SCL_HI_IN */
+ "and.l %[sclb],(8,%[sclrd]) \n"
+ "not.l %[sclb] \n"
+ "1: \n"
+ "move.l (%[sclrd]),%%d0 \n"
+ "btst.l %[sclbnum],%%d0 \n"
+ "beq.s 1b \n"
+
+ "move.l (%[sdard]),%%d0 \n" /* ret = !SDA */
+ "btst.l %[sdabnum],%%d0 \n"
+ "seq.b %[ret] \n"
+
+ "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
+
+ "move.l %[dly],%%d0 \n" /* DELAY */
+ "1: \n"
+ "subq.l #1,%%d0 \n"
+ "bhi.s 1b \n"
+ : /* outputs */
+ [ret] "=&d"(ret)
+ : /* inputs */
+ [sclrd] "a"(&SCL_GPIO_READ),
+ [sclb] "d"(SCL_BIT),
+ [sclbnum] "i"(SCL_BITNUM),
+ [sdard] "a"(&SDA_GPIO_READ),
+ [sdab] "d"(SDA_BIT),
+ [sdabnum] "i"(SDA_BITNUM),
+ [dly] "d"(i2c_delay)
+ : /* clobbers */
+ "d0"
+ );
+#else
+ SDA_HI_IN;
+ DELAY;
+ SCL_HI_IN;
+
+ ret = !SDA;
+
+ SCL_LO_OUT;
+ DELAY;
+#endif
+ return ret;
+}
+
+void pcf50606_i2c_outb(unsigned char byte)
+{
+#ifdef USE_ASM
+ asm volatile (
+ "moveq.l #24,%%d0 \n" /* byte <<= 24 */
+ "lsl.l %%d0,%[byte] \n"
+ "moveq.l #8,%%d1 \n" /* i = 8 */
+
+ "2: \n" /* do */
+ "lsl.l #1,%[byte] \n" /* if ((byte <<= 1) carry) */
+ "bcc.s 1f \n"
+
+ "not.l %[sdab] \n" /* SDA_HI_IN */
+ "and.l %[sdab],(8,%[sdard]) \n"
+ "not.l %[sdab] \n"
+ ".word 0x51fb \n" /* trapf.l; else */
+ "1: \n"
+ "or.l %[sdab],(8,%[sdard]) \n" /* SDA_LO_OUT */
+
+ "move.l %[dly],%%d0 \n" /* DELAY */
+ "1: \n"
+ "subq.l #1,%%d0 \n"
+ "bhi.s 1b \n"
+
+ "not.l %[sclb] \n" /* SCL_HI_IN */
+ "and.l %[sclb],(8,%[sclrd]) \n"
+ "not.l %[sclb] \n"
+ "1: \n"
+ "move.l (%[sclrd]),%%d0 \n"
+ "btst.l %[sclbnum],%%d0 \n"
+ "beq.s 1b \n"
+
+ "move.l %[dly],%%d0 \n" /* DELAY */
+ "1: \n"
+ "subq.l #1,%%d0 \n"
+ "bhi.s 1b \n"
+
+ "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
+
+ "subq.l #1,%%d1 \n" /* i-- */
+ "bne.s 2b \n" /* while (i != 0) */
+ : /* outputs */
+ [byte] "+d"(byte)
+ : /* inputs */
+ [sclrd] "a"(&SCL_GPIO_READ),
+ [sclb] "d"(SCL_BIT),
+ [sclbnum] "i"(SCL_BITNUM),
+ [sdard] "a"(&SDA_GPIO_READ),
+ [sdab] "d"(SDA_BIT),
+ [dly] "d"(i2c_delay)
+ : /* clobbers */
+ "d0", "d1"
+ );
+#else
+ int i;
+
+ /* clock out each bit, MSB first */
+ for ( i=0x80; i; i>>=1 )
+ {
+ if ( i & byte )
+ SDA_HI_IN;
+ else
+ SDA_LO_OUT;
+ DELAY;
+ SCL_HI_IN;
+ DELAY;
+ SCL_LO_OUT;
+ }
+#endif
+}
+
+unsigned char pcf50606_i2c_inb(bool ack)
+{
+ unsigned char byte = 0;
+
+#ifdef USE_ASM
+ asm (
+ "not.l %[sdab] \n" /* SDA_HI_IN */
+ "and.l %[sdab],(8,%[sdard]) \n"
+ "not.l %[sdab] \n"
+
+ "moveq.l #8,%%d1 \n" /* i = 8 */
+ "clr.l %[byte] \n" /* byte = 0 */
+
+ "2: \n" /* do */
+ "not.l %[sclb] \n" /* SCL_HI_IN */
+ "and.l %[sclb],(8,%[sclrd]) \n"
+ "not.l %[sclb] \n"
+ "1: \n"
+ "move.l (%[sclrd]),%%d0 \n"
+ "btst.l %[sclbnum],%%d0 \n"
+ "beq.s 1b \n"
+
+ "move.l %[dly],%%d0 \n" /* DELAY */
+ "1: \n"
+ "subq.l #1,%%d0 \n"
+ "bhi.s 1b \n"
+
+ "lsl.l #1,%[byte] \n" /* byte <<= 1 */
+ "move.l (%[sdard]),%%d0 \n" /* if (SDA) */
+ "btst.l %[sdabnum],%%d0 \n"
+ "beq.s 1f \n"
+ "addq.l #1,%[byte] \n" /* byte++ */
+ "1: \n"
+
+ "or.l %[sclb],(8,%[sclrd]) \n" /* SCL_LO_OUT */
+
+ "move.l %[dly],%%d0 \n" /* DELAY */
+ "1: \n"
+ "subq.l #1,%%d0 \n"
+ "bhi.s 1b \n"
+
+ "subq.l #1,%%d1 \n" /* i-- */
+ "bne.s 2b \n" /* while (i != 0) */
+ : /* outputs */
+ [byte] "=&d"(byte)
+ : /* inputs */
+ [sclrd] "a"(&SCL_GPIO_READ),
+ [sclb] "d"(SCL_BIT),
+ [sclbnum] "i"(SCL_BITNUM),
+ [sdard] "a"(&SDA_GPIO_READ),
+ [sdab] "d"(SDA_BIT),
+ [sdabnum] "i"(SDA_BITNUM),
+ [dly] "d"(i2c_delay)
+ : /* clobbers */
+ "d0", "d1"
+ );
+#else
+ int i;
+
+ /* clock in each bit, MSB first */
+ SDA_HI_IN;
+ for ( i=0x80; i; i>>=1 )
+ {
+ SCL_HI_IN;
+ DELAY;
+ if ( SDA )
+ byte |= i;
+ SCL_LO_OUT;
+ DELAY;
+ }
+#endif
+
+ pcf50606_i2c_ack(ack);
+
+ return byte;
+}
+
+int pcf50606_i2c_write(int address, const unsigned char* buf, int count)
+{
+ int i,x=0;
+
+ pcf50606_i2c_start();
+ pcf50606_i2c_outb(address & 0xfe);
+ if (pcf50606_i2c_getack())
+ {
+ for (i=0; i<count; i++)
+ {
+ pcf50606_i2c_outb(buf[i]);
+ if (!pcf50606_i2c_getack())
+ {
+ x=-2;
+ break;
+ }
+ }
+ }
+ else
+ {
+ logf("pcf50606_i2c_write() - no ack\n");
+ x=-1;
+ }
+ return x;
+}
+
+int pcf50606_read_multiple(int address, unsigned char* buf, int count)
+{
+ int i=0;
+ int ret = 0;
+ unsigned char obuf[1];
+
+ obuf[0] = address;
+
+ /* send read command */
+ if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
+ {
+ pcf50606_i2c_start();
+ pcf50606_i2c_outb(0x11);
+ if (pcf50606_i2c_getack())
+ {
+ for(i = 0;i < count-1;i++)
+ buf[i] = pcf50606_i2c_inb(true);
+
+ buf[i] = pcf50606_i2c_inb(false);
+ }
+ else
+ {
+ ret = -1;
+ }
+ }
+
+ pcf50606_i2c_stop();
+
+ return ret;
+}
+
+int pcf50606_read(int address)
+{
+ int ret;
+ unsigned char c;
+
+ ret = pcf50606_read_multiple(address, &c, 1);
+ if(ret >= 0)
+ return c;
+ else
+ return ret;
+}
+
+int pcf50606_write_multiple(int address, const unsigned char* buf, int count)
+{
+ unsigned char obuf[1];
+ int i;
+ int ret = 0;
+
+ obuf[0] = address;
+
+ /* send write command */
+ if (pcf50606_i2c_write(PCF50606_ADDR, obuf, 1) >= 0)
+ {
+ for (i=0; i<count; i++)
+ {
+ pcf50606_i2c_outb(buf[i]);
+ if (!pcf50606_i2c_getack())
+ {
+ ret = -2;
+ break;
+ }
+ }
+ }
+ else
+ {
+ ret = -1;
+ }
+
+ pcf50606_i2c_stop();
+ return ret;
+}
+
+int pcf50606_write(int address, unsigned char val)
+{
+ return pcf50606_write_multiple(address, &val, 1);
+}