summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2005-12-11 10:52:17 +0000
committerDave Chapman <dave@dchapman.com>2005-12-11 10:52:17 +0000
commite066a20b6722fc7a2948e92751a6709706f43525 (patch)
tree036e35bb632ac5608be7791c6702d2fa1a07715a
parent060320b95c99d91fd2e72cc1c3aabbad8d99127d (diff)
iPod: Cleanup of i2c code and addition of RTC driver
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8219 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/SOURCES3
-rw-r--r--firmware/drivers/i2c-pp5020.c170
-rw-r--r--firmware/drivers/pcf50605.c111
-rw-r--r--firmware/export/config-ipodcolor.h3
-rw-r--r--firmware/export/config-ipodnano.h3
-rw-r--r--firmware/export/config.h5
-rw-r--r--firmware/export/i2c-pp5020.h43
-rw-r--r--firmware/export/pcf50605.h31
8 files changed, 231 insertions, 138 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 144b1c1032..87316cba1e 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -99,6 +99,9 @@ drivers/mas.c
#ifdef IRIVER_H300_SERIES
drivers/pcf50606.c
#endif
+#if defined(APPLE_IPODCOLOR) || defined(APPLE_IPODNANO)
+drivers/pcf50605.c
+#endif
#if CONFIG_RTC == RTC_M41ST84W
drivers/rtc.c
#endif
diff --git a/firmware/drivers/i2c-pp5020.c b/firmware/drivers/i2c-pp5020.c
index 6f8d9a91d5..ec6bcef0cd 100644
--- a/firmware/drivers/i2c-pp5020.c
+++ b/firmware/drivers/i2c-pp5020.c
@@ -23,18 +23,8 @@
#include "system.h"
#include "i2c-pp5020.h"
-#define I2C_DEVICE_1 ((volatile unsigned char *)0)
-#define I2C_DEVICE_2 ((volatile unsigned char *)0)
-
/* Local functions definitions */
-#if 0
-static int i2c_write_byte(int device, unsigned char data);
-static int i2c_gen_start(int device);
-static void i2c_gen_stop(int device);
-static volatile unsigned char *i2c_get_addr(int device);
-#endif
-
#define IPOD_I2C_BASE 0x7000c000
#define IPOD_I2C_CTRL (IPOD_I2C_BASE+0x00)
#define IPOD_I2C_ADDR (IPOD_I2C_BASE+0x04)
@@ -52,142 +42,124 @@ static volatile unsigned char *i2c_get_addr(int device);
#define POLL_TIMEOUT (HZ)
-static int
-ipod_i2c_wait_not_busy(void)
+static int ipod_i2c_wait_not_busy(void)
{
-#if 0
unsigned long timeout;
- timeout = jiffies + POLL_TIMEOUT;
- while (time_before(jiffies, timeout)) {
+ timeout = current_tick + POLL_TIMEOUT;
+ while (TIME_BEFORE(current_tick, timeout)) {
if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) {
return 0;
}
yield();
}
- return -ETIMEDOUT;
-#endif
- return 0;
+ return -1;
}
/* Public functions */
-void i2c_init(void)
+int ipod_i2c_read_byte(unsigned int addr, unsigned int *data)
{
- /* From ipodlinux */
+ if (ipod_i2c_wait_not_busy() < 0)
+ {
+ return -1;
+ }
- outl(inl(0x6000600c) | 0x1000, 0x6000600c); /* enable 12 */
- outl(inl(0x60006004) | 0x1000, 0x60006004); /* start reset 12 */
- outl(inl(0x60006004) & ~0x1000, 0x60006004); /* end reset 12 */
+ /* clear top 15 bits, left shift 1, or in 0x1 for a read */
+ outb(((addr << 17) >> 16) | 0x1, IPOD_I2C_ADDR);
- outl(0x0, 0x600060a4);
- outl(0x80 | (0 << 8), 0x600060a4);
+ outb(inb(IPOD_I2C_CTRL) | 0x20, IPOD_I2C_CTRL);
- //i2c_readbyte(0x8, 0);
-}
+ outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL);
-void i2c_close(void)
-{
+ if (ipod_i2c_wait_not_busy() < 0)
+ {
+ return -1;
+ }
+ if (data)
+ {
+ *data = inb(IPOD_I2C_DATA0);
+ }
+
+ return 0;
}
-/**
- * Writes bytes to the selected device.
- *
- * Returns number of bytes successfully send or -1 if START failed
- */
-int i2c_write(int device, unsigned char *buf, int count)
+int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data)
{
- /* From ipodlinux */
- int data_addr;
- int i;
-
- if (count < 1 || count > 4) {
- return -2;
- }
+ int data_addr;
+ unsigned int i;
- if (ipod_i2c_wait_not_busy() < 0) {
- return -1;
- }
-
- // clear top 15 bits, left shift 1
- outb((device << 17) >> 16, IPOD_I2C_ADDR);
+ if (len < 1 || len > 4)
+ {
+ return -1;
+ }
- outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL);
+ if (ipod_i2c_wait_not_busy() < 0)
+ {
+ return -2;
+ }
- data_addr = IPOD_I2C_DATA0;
- for ( i = 0; i < count; i++ ) {
- outb(*buf++, data_addr);
+ /* clear top 15 bits, left shift 1 */
+ outb((addr << 17) >> 16, IPOD_I2C_ADDR);
- data_addr += 4;
- }
+ outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL);
- outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((count-1) << 1), IPOD_I2C_CTRL);
+ data_addr = IPOD_I2C_DATA0;
+ for ( i = 0; i < len; i++ )
+ {
+ outb(*data++, data_addr);
+ data_addr += 4;
+ }
- outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL);
+ outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((len-1) << 1), IPOD_I2C_CTRL);
- return 0x0;
+ outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL);
- return count;
+ return 0x0;
}
-#if 0
-/* Write a byte to the interface, returns 0 on success, -1 otherwise. */
-static int i2c_write_byte(int device, unsigned char data)
+int ipod_i2c_send_byte(unsigned int addr, int data0)
{
- if (ipod_i2c_wait_not_busy() < 0) {
- return -2;
- }
+ unsigned char data[1];
- // clear top 15 bits, left shift 1
- outb((device << 17) >> 16, IPOD_I2C_ADDR);
+ data[0] = data0;
- outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL);
+ return ipod_i2c_send_bytes(addr, 1, data);
+}
- outb(data, IPOD_I2C_DATA0);
- outb((inb(IPOD_I2C_CTRL) & ~0x26), IPOD_I2C_CTRL);
+int i2c_readbyte(unsigned int dev_addr, int addr)
+{
+ int data;
- outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL);
+ ipod_i2c_send_byte(dev_addr, addr);
+ ipod_i2c_read_byte(dev_addr, &data);
- return 0;
+ return data;
}
-
-/* Returns 0 on success, -1 on failure */
-int i2c_gen_start(int device)
+int ipod_i2c_send(unsigned int addr, int data0, int data1)
{
- volatile unsigned char *regs = i2c_get_addr(device);
- long count = 0;
+ unsigned char data[2];
- /* Wait for bus to become free */
- while ((regs[O_MBSR] & IBB) && (count < MAX_LOOP))
- {
- yield();
- count++;
- }
-
- if (count >= MAX_LOOP)
- return -1;
-
- regs[O_MBCR] |= MSTA | MTX; /* Generate START */
+ data[0] = data0;
+ data[1] = data1;
- return 0;
-}
+ return ipod_i2c_send_bytes(addr, 2, data);
+}
-void i2c_gen_stop(int device)
+void i2c_init(void)
{
- volatile unsigned char *regs = i2c_get_addr(device);
- regs[O_MBCR] &= ~MSTA; /* Clear MSTA to generate STOP */
-}
+ /* From ipodlinux */
-#endif
+ outl(inl(0x6000600c) | 0x1000, 0x6000600c); /* enable 12 */
+ outl(inl(0x60006004) | 0x1000, 0x60006004); /* start reset 12 */
+ outl(inl(0x60006004) & ~0x1000, 0x60006004); /* end reset 12 */
-volatile unsigned char *i2c_get_addr(int device)
-{
- if (device == 1)
- return I2C_DEVICE_1;
+ outl(0x0, 0x600060a4);
+ outl(0x80 | (0 << 8), 0x600060a4);
- return I2C_DEVICE_2;
+ i2c_readbyte(0x8, 0);
}
diff --git a/firmware/drivers/pcf50605.c b/firmware/drivers/pcf50605.c
new file mode 100644
index 0000000000..87ef9576b6
--- /dev/null
+++ b/firmware/drivers/pcf50605.c
@@ -0,0 +1,111 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Dave Chapman
+ *
+ * Based on code from the iPodLinux project (C) 2004-2005 Bernard Leach
+ *
+ * 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 "i2c-pp5020.h"
+#include "rtc.h"
+
+int pcf50605_read(int address)
+{
+ return i2c_readbyte(0x8,address);
+}
+
+int pcf50605_read_multiple(int address, unsigned char* buf, int count)
+{
+ int i;
+
+ for (i=0;i<count;i++)
+ {
+ buf[i]=pcf50605_read(address);
+ address++;
+ }
+
+ return 0;
+}
+
+int pcf50605_write(int address, unsigned char val)
+{
+ /* TODO */
+ (void)address;
+ (void)val;
+ return 0;
+}
+
+int pcf50605_write_multiple(int address, const unsigned char* buf, int count)
+{
+ /* TODO */
+ (void)address;
+ (void)buf;
+ (void)count;
+ return 0;
+}
+
+static int pcf50605_a2d_read(int adc_input)
+{
+ int hi, lo;
+
+ /* Enable ACD module */
+ ipod_i2c_send(0x8, 0x33, 0x80); /* ACDC1, ACDAPE = 1 */
+
+ /* select ADCIN1 - subtractor, and start sampling process */
+ ipod_i2c_send(0x8, 0x2f, (adc_input<<1) | 0x1); /* ADCC2, ADCMUX = adc_input, ADCSTART = 1 */
+
+ /* ADCC2, wait for ADCSTART = 0 (wait for sampling to start) */
+ while ((i2c_readbyte(0x8, 0x2f) & 1)) /* do nothing */;
+
+ /* ADCS2, wait ADCRDY = 0 (wait for sampling to end) */
+ while (!(i2c_readbyte(0x8, 0x31) & 0x80)) /* do nothing */;
+
+ hi = i2c_readbyte(0x8, 0x30); /* ADCS1 */
+ lo = (i2c_readbyte(0x8, 0x31) & 0x3); /* ADCS2 */
+
+ return (hi << 2) | lo;
+}
+
+int pcf50605_battery_read(void)
+{
+ return pcf50605_a2d_read(0x3); /* ADCIN1, subtractor */
+}
+
+void rtc_init(void)
+{
+ /* Nothing to do. */
+}
+
+int rtc_read_datetime(unsigned char* buf)
+{
+ int rc;
+
+ rc = pcf50605_read_multiple(0x0a, buf, 7);
+
+ return rc;
+}
+
+
+int rtc_write_datetime(unsigned char* buf)
+{
+ int i;
+
+ for (i=0;i<7;i++) {
+ ipod_i2c_send(0x8, 0x0a+i, buf[i]);
+ }
+
+ return 1;
+}
diff --git a/firmware/export/config-ipodcolor.h b/firmware/export/config-ipodcolor.h
index c1068b06eb..9f71ba895f 100644
--- a/firmware/export/config-ipodcolor.h
+++ b/firmware/export/config-ipodcolor.h
@@ -26,6 +26,9 @@
/* Define this if you do software codec */
#define CONFIG_CODEC SWCODEC
+/* define this if you have a real-time clock */
+#define CONFIG_RTC RTC_PCF50605
+
/* Define this if you have a software controlled poweroff */
//#define HAVE_SW_POWEROFF
diff --git a/firmware/export/config-ipodnano.h b/firmware/export/config-ipodnano.h
index 99eb67b5bf..6657ba8aaa 100644
--- a/firmware/export/config-ipodnano.h
+++ b/firmware/export/config-ipodnano.h
@@ -26,6 +26,9 @@
/* Define this if you do software codec */
#define CONFIG_CODEC SWCODEC
+/* define this if you have a real-time clock */
+#define CONFIG_RTC RTC_PCF50605
+
/* Define this if you have a software controlled poweroff */
//#define HAVE_SW_POWEROFF
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 555e062eb4..d34c5682c7 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -102,8 +102,9 @@
#define LED_VIRTUAL 2 /* Virtual LED (icon) (Archos Ondio) */
/* CONFIG_RTC */
-#define RTC_M41ST84W 1
-#define RTC_PCF50606 2
+#define RTC_M41ST84W 1 /* Archos Recorder */
+#define RTC_PCF50605 2 /* iPod 4G */
+#define RTC_PCF50606 3 /* iriver H300 */
/* else HW controlled LED (iRiver H1x0) */
diff --git a/firmware/export/i2c-pp5020.h b/firmware/export/i2c-pp5020.h
index 8487c678cf..c0dc969e8b 100644
--- a/firmware/export/i2c-pp5020.h
+++ b/firmware/export/i2c-pp5020.h
@@ -18,48 +18,17 @@
****************************************************************************/
/*
- * Driver for ARM i2c driver
- *
+ * PP5020 i2c driver
*
*/
-#ifndef _I2C_ARM_H
-#define _I2C_ARM_H
+#ifndef _I2C_PP5020_H
+#define _I2C_PP5020_H
-/* TODO: Implement: i2c-pp5020.h */
+/* TODO: Fully implement i2c driver */
void i2c_init(void);
-int i2c_write(int device, unsigned char *buf, int count);
-void i2c_close(void);
-
-#define MAX_LOOP 0x100 /* TODO: select a better value */
-
-/* PLLCR control */
-#define QSPISEL (1 << 11) /* Selects QSPI or I2C interface */
-
-/* Offsets to I2C registers from base address */
-#define O_MADR 0x00 /* Slave Address */
-#define O_MFDR 0x04 /* Frequency divider */
-#define O_MBCR 0x08 /* Control register */
-#define O_MBSR 0x0c /* Status register */
-#define O_MBDR 0x10 /* Data register */
-
-/* MBSR - Status register */
-#define ICF (1 << 7) /* Transfer Complete */
-#define IAAS (1 << 6) /* Addressed As Alave */
-#define IBB (1 << 5) /* Bus Busy */
-#define IAL (1 << 4) /* Arbitration Lost */
-#define SRW (1 << 2) /* Slave R/W */
-#define IFF (1 << 1) /* I2C Interrupt */
-#define RXAK (1 << 0) /* No Ack bit */
-
-/* MBCR - Control register */
-#define IEN (1 << 7) /* I2C Enable */
-#define IIEN (1 << 6) /* Interrupt Enable */
-#define MSTA (1 << 5) /* Master/Slave select */
-#define MTX (1 << 4) /* Transmit/Receive */
-#define TXAK (1 << 3) /* Transfer ACK */
-#define RSTA (1 << 2) /* Restart.. */
-
+int i2c_readbyte(unsigned int dev_addr, int addr);
+int ipod_i2c_send(unsigned int addr, int data0, int data1);
#endif
diff --git a/firmware/export/pcf50605.h b/firmware/export/pcf50605.h
new file mode 100644
index 0000000000..fc52b98e99
--- /dev/null
+++ b/firmware/export/pcf50605.h
@@ -0,0 +1,31 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Dave Chapman
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef PCF50605_H
+#define PCF50605_H
+
+#if defined(APPLE_IPODCOLOR) || defined(APPLE_IPODNANO)
+int pcf50605_read(int address);
+void pcf50605_read_multiple(int address, unsigned char* buf, int count);
+int pcf50605_write(int address, unsigned char val);
+int pcf50605_write_multiple(int address, const unsigned char* buf, int count);
+int pcf50605_battery_read(void);
+#endif
+
+#endif