summaryrefslogtreecommitdiff
path: root/firmware/drivers
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 /firmware/drivers
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
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/i2c-pp5020.c170
-rw-r--r--firmware/drivers/pcf50605.c111
2 files changed, 182 insertions, 99 deletions
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;
+}