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)
downloadrockbox-e066a20b6722fc7a2948e92751a6709706f43525.tar.gz
rockbox-e066a20b6722fc7a2948e92751a6709706f43525.zip
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
99#ifdef IRIVER_H300_SERIES 99#ifdef IRIVER_H300_SERIES
100drivers/pcf50606.c 100drivers/pcf50606.c
101#endif 101#endif
102#if defined(APPLE_IPODCOLOR) || defined(APPLE_IPODNANO)
103drivers/pcf50605.c
104#endif
102#if CONFIG_RTC == RTC_M41ST84W 105#if CONFIG_RTC == RTC_M41ST84W
103drivers/rtc.c 106drivers/rtc.c
104#endif 107#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 @@
23#include "system.h" 23#include "system.h"
24#include "i2c-pp5020.h" 24#include "i2c-pp5020.h"
25 25
26#define I2C_DEVICE_1 ((volatile unsigned char *)0)
27#define I2C_DEVICE_2 ((volatile unsigned char *)0)
28
29/* Local functions definitions */ 26/* Local functions definitions */
30 27
31#if 0
32static int i2c_write_byte(int device, unsigned char data);
33static int i2c_gen_start(int device);
34static void i2c_gen_stop(int device);
35static volatile unsigned char *i2c_get_addr(int device);
36#endif
37
38#define IPOD_I2C_BASE 0x7000c000 28#define IPOD_I2C_BASE 0x7000c000
39#define IPOD_I2C_CTRL (IPOD_I2C_BASE+0x00) 29#define IPOD_I2C_CTRL (IPOD_I2C_BASE+0x00)
40#define IPOD_I2C_ADDR (IPOD_I2C_BASE+0x04) 30#define IPOD_I2C_ADDR (IPOD_I2C_BASE+0x04)
@@ -52,142 +42,124 @@ static volatile unsigned char *i2c_get_addr(int device);
52 42
53#define POLL_TIMEOUT (HZ) 43#define POLL_TIMEOUT (HZ)
54 44
55static int 45static int ipod_i2c_wait_not_busy(void)
56ipod_i2c_wait_not_busy(void)
57{ 46{
58#if 0
59 unsigned long timeout; 47 unsigned long timeout;
60 timeout = jiffies + POLL_TIMEOUT; 48 timeout = current_tick + POLL_TIMEOUT;
61 while (time_before(jiffies, timeout)) { 49 while (TIME_BEFORE(current_tick, timeout)) {
62 if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) { 50 if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) {
63 return 0; 51 return 0;
64 } 52 }
65 yield(); 53 yield();
66 } 54 }
67 55
68 return -ETIMEDOUT; 56 return -1;
69#endif
70 return 0;
71} 57}
72 58
73 59
74/* Public functions */ 60/* Public functions */
75 61
76void i2c_init(void) 62int ipod_i2c_read_byte(unsigned int addr, unsigned int *data)
77{ 63{
78 /* From ipodlinux */ 64 if (ipod_i2c_wait_not_busy() < 0)
65 {
66 return -1;
67 }
79 68
80 outl(inl(0x6000600c) | 0x1000, 0x6000600c); /* enable 12 */ 69 /* clear top 15 bits, left shift 1, or in 0x1 for a read */
81 outl(inl(0x60006004) | 0x1000, 0x60006004); /* start reset 12 */ 70 outb(((addr << 17) >> 16) | 0x1, IPOD_I2C_ADDR);
82 outl(inl(0x60006004) & ~0x1000, 0x60006004); /* end reset 12 */
83 71
84 outl(0x0, 0x600060a4); 72 outb(inb(IPOD_I2C_CTRL) | 0x20, IPOD_I2C_CTRL);
85 outl(0x80 | (0 << 8), 0x600060a4);
86 73
87 //i2c_readbyte(0x8, 0); 74 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL);
88}
89 75
90void i2c_close(void) 76 if (ipod_i2c_wait_not_busy() < 0)
91{ 77 {
78 return -1;
79 }
92 80
81 if (data)
82 {
83 *data = inb(IPOD_I2C_DATA0);
84 }
85
86 return 0;
93} 87}
94 88
95/** 89int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data)
96 * Writes bytes to the selected device.
97 *
98 * Returns number of bytes successfully send or -1 if START failed
99 */
100int i2c_write(int device, unsigned char *buf, int count)
101{ 90{
102 /* From ipodlinux */ 91 int data_addr;
103 int data_addr; 92 unsigned int i;
104 int i;
105
106 if (count < 1 || count > 4) {
107 return -2;
108 }
109 93
110 if (ipod_i2c_wait_not_busy() < 0) { 94 if (len < 1 || len > 4)
111 return -1; 95 {
112 } 96 return -1;
113 97 }
114 // clear top 15 bits, left shift 1
115 outb((device << 17) >> 16, IPOD_I2C_ADDR);
116 98
117 outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL); 99 if (ipod_i2c_wait_not_busy() < 0)
100 {
101 return -2;
102 }
118 103
119 data_addr = IPOD_I2C_DATA0; 104 /* clear top 15 bits, left shift 1 */
120 for ( i = 0; i < count; i++ ) { 105 outb((addr << 17) >> 16, IPOD_I2C_ADDR);
121 outb(*buf++, data_addr);
122 106
123 data_addr += 4; 107 outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL);
124 }
125 108
126 outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((count-1) << 1), IPOD_I2C_CTRL); 109 data_addr = IPOD_I2C_DATA0;
110 for ( i = 0; i < len; i++ )
111 {
112 outb(*data++, data_addr);
113 data_addr += 4;
114 }
127 115
128 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); 116 outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((len-1) << 1), IPOD_I2C_CTRL);
129 117
130 return 0x0; 118 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL);
131 119
132 return count; 120 return 0x0;
133} 121}
134 122
135#if 0 123int ipod_i2c_send_byte(unsigned int addr, int data0)
136/* Write a byte to the interface, returns 0 on success, -1 otherwise. */
137static int i2c_write_byte(int device, unsigned char data)
138{ 124{
139 if (ipod_i2c_wait_not_busy() < 0) { 125 unsigned char data[1];
140 return -2;
141 }
142 126
143 // clear top 15 bits, left shift 1 127 data[0] = data0;
144 outb((device << 17) >> 16, IPOD_I2C_ADDR);
145 128
146 outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL); 129 return ipod_i2c_send_bytes(addr, 1, data);
130}
147 131
148 outb(data, IPOD_I2C_DATA0);
149 132
150 outb((inb(IPOD_I2C_CTRL) & ~0x26), IPOD_I2C_CTRL); 133int i2c_readbyte(unsigned int dev_addr, int addr)
134{
135 int data;
151 136
152 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); 137 ipod_i2c_send_byte(dev_addr, addr);
138 ipod_i2c_read_byte(dev_addr, &data);
153 139
154 return 0; 140 return data;
155} 141}
156 142
157 143int ipod_i2c_send(unsigned int addr, int data0, int data1)
158/* Returns 0 on success, -1 on failure */
159int i2c_gen_start(int device)
160{ 144{
161 volatile unsigned char *regs = i2c_get_addr(device); 145 unsigned char data[2];
162 long count = 0;
163 146
164 /* Wait for bus to become free */ 147 data[0] = data0;
165 while ((regs[O_MBSR] & IBB) && (count < MAX_LOOP)) 148 data[1] = data1;
166 {
167 yield();
168 count++;
169 }
170
171 if (count >= MAX_LOOP)
172 return -1;
173
174 regs[O_MBCR] |= MSTA | MTX; /* Generate START */
175 149
176 return 0; 150 return ipod_i2c_send_bytes(addr, 2, data);
177} 151}
178 152
179void i2c_gen_stop(int device) 153void i2c_init(void)
180{ 154{
181 volatile unsigned char *regs = i2c_get_addr(device); 155 /* From ipodlinux */
182 regs[O_MBCR] &= ~MSTA; /* Clear MSTA to generate STOP */
183}
184 156
185#endif 157 outl(inl(0x6000600c) | 0x1000, 0x6000600c); /* enable 12 */
158 outl(inl(0x60006004) | 0x1000, 0x60006004); /* start reset 12 */
159 outl(inl(0x60006004) & ~0x1000, 0x60006004); /* end reset 12 */
186 160
187volatile unsigned char *i2c_get_addr(int device) 161 outl(0x0, 0x600060a4);
188{ 162 outl(0x80 | (0 << 8), 0x600060a4);
189 if (device == 1)
190 return I2C_DEVICE_1;
191 163
192 return I2C_DEVICE_2; 164 i2c_readbyte(0x8, 0);
193} 165}
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Dave Chapman
11 *
12 * Based on code from the iPodLinux project (C) 2004-2005 Bernard Leach
13 *
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "i2c-pp5020.h"
23#include "rtc.h"
24
25int pcf50605_read(int address)
26{
27 return i2c_readbyte(0x8,address);
28}
29
30int pcf50605_read_multiple(int address, unsigned char* buf, int count)
31{
32 int i;
33
34 for (i=0;i<count;i++)
35 {
36 buf[i]=pcf50605_read(address);
37 address++;
38 }
39
40 return 0;
41}
42
43int pcf50605_write(int address, unsigned char val)
44{
45 /* TODO */
46 (void)address;
47 (void)val;
48 return 0;
49}
50
51int pcf50605_write_multiple(int address, const unsigned char* buf, int count)
52{
53 /* TODO */
54 (void)address;
55 (void)buf;
56 (void)count;
57 return 0;
58}
59
60static int pcf50605_a2d_read(int adc_input)
61{
62 int hi, lo;
63
64 /* Enable ACD module */
65 ipod_i2c_send(0x8, 0x33, 0x80); /* ACDC1, ACDAPE = 1 */
66
67 /* select ADCIN1 - subtractor, and start sampling process */
68 ipod_i2c_send(0x8, 0x2f, (adc_input<<1) | 0x1); /* ADCC2, ADCMUX = adc_input, ADCSTART = 1 */
69
70 /* ADCC2, wait for ADCSTART = 0 (wait for sampling to start) */
71 while ((i2c_readbyte(0x8, 0x2f) & 1)) /* do nothing */;
72
73 /* ADCS2, wait ADCRDY = 0 (wait for sampling to end) */
74 while (!(i2c_readbyte(0x8, 0x31) & 0x80)) /* do nothing */;
75
76 hi = i2c_readbyte(0x8, 0x30); /* ADCS1 */
77 lo = (i2c_readbyte(0x8, 0x31) & 0x3); /* ADCS2 */
78
79 return (hi << 2) | lo;
80}
81
82int pcf50605_battery_read(void)
83{
84 return pcf50605_a2d_read(0x3); /* ADCIN1, subtractor */
85}
86
87void rtc_init(void)
88{
89 /* Nothing to do. */
90}
91
92int rtc_read_datetime(unsigned char* buf)
93{
94 int rc;
95
96 rc = pcf50605_read_multiple(0x0a, buf, 7);
97
98 return rc;
99}
100
101
102int rtc_write_datetime(unsigned char* buf)
103{
104 int i;
105
106 for (i=0;i<7;i++) {
107 ipod_i2c_send(0x8, 0x0a+i, buf[i]);
108 }
109
110 return 1;
111}
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 @@
26/* Define this if you do software codec */ 26/* Define this if you do software codec */
27#define CONFIG_CODEC SWCODEC 27#define CONFIG_CODEC SWCODEC
28 28
29/* define this if you have a real-time clock */
30#define CONFIG_RTC RTC_PCF50605
31
29/* Define this if you have a software controlled poweroff */ 32/* Define this if you have a software controlled poweroff */
30//#define HAVE_SW_POWEROFF 33//#define HAVE_SW_POWEROFF
31 34
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 @@
26/* Define this if you do software codec */ 26/* Define this if you do software codec */
27#define CONFIG_CODEC SWCODEC 27#define CONFIG_CODEC SWCODEC
28 28
29/* define this if you have a real-time clock */
30#define CONFIG_RTC RTC_PCF50605
31
29/* Define this if you have a software controlled poweroff */ 32/* Define this if you have a software controlled poweroff */
30//#define HAVE_SW_POWEROFF 33//#define HAVE_SW_POWEROFF
31 34
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 @@
102#define LED_VIRTUAL 2 /* Virtual LED (icon) (Archos Ondio) */ 102#define LED_VIRTUAL 2 /* Virtual LED (icon) (Archos Ondio) */
103 103
104/* CONFIG_RTC */ 104/* CONFIG_RTC */
105#define RTC_M41ST84W 1 105#define RTC_M41ST84W 1 /* Archos Recorder */
106#define RTC_PCF50606 2 106#define RTC_PCF50605 2 /* iPod 4G */
107#define RTC_PCF50606 3 /* iriver H300 */
107 108
108/* else HW controlled LED (iRiver H1x0) */ 109/* else HW controlled LED (iRiver H1x0) */
109 110
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 @@
18 ****************************************************************************/ 18 ****************************************************************************/
19 19
20/* 20/*
21 * Driver for ARM i2c driver 21 * PP5020 i2c driver
22 *
23 * 22 *
24 */ 23 */
25 24
26#ifndef _I2C_ARM_H 25#ifndef _I2C_PP5020_H
27#define _I2C_ARM_H 26#define _I2C_PP5020_H
28 27
29/* TODO: Implement: i2c-pp5020.h */ 28/* TODO: Fully implement i2c driver */
30 29
31void i2c_init(void); 30void i2c_init(void);
32int i2c_write(int device, unsigned char *buf, int count); 31int i2c_readbyte(unsigned int dev_addr, int addr);
33void i2c_close(void); 32int ipod_i2c_send(unsigned int addr, int data0, int data1);
34
35#define MAX_LOOP 0x100 /* TODO: select a better value */
36
37/* PLLCR control */
38#define QSPISEL (1 << 11) /* Selects QSPI or I2C interface */
39
40/* Offsets to I2C registers from base address */
41#define O_MADR 0x00 /* Slave Address */
42#define O_MFDR 0x04 /* Frequency divider */
43#define O_MBCR 0x08 /* Control register */
44#define O_MBSR 0x0c /* Status register */
45#define O_MBDR 0x10 /* Data register */
46
47/* MBSR - Status register */
48#define ICF (1 << 7) /* Transfer Complete */
49#define IAAS (1 << 6) /* Addressed As Alave */
50#define IBB (1 << 5) /* Bus Busy */
51#define IAL (1 << 4) /* Arbitration Lost */
52#define SRW (1 << 2) /* Slave R/W */
53#define IFF (1 << 1) /* I2C Interrupt */
54#define RXAK (1 << 0) /* No Ack bit */
55
56/* MBCR - Control register */
57#define IEN (1 << 7) /* I2C Enable */
58#define IIEN (1 << 6) /* Interrupt Enable */
59#define MSTA (1 << 5) /* Master/Slave select */
60#define MTX (1 << 4) /* Transmit/Receive */
61#define TXAK (1 << 3) /* Transfer ACK */
62#define RSTA (1 << 2) /* Restart.. */
63
64 33
65#endif 34#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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Dave Chapman
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
20#ifndef PCF50605_H
21#define PCF50605_H
22
23#if defined(APPLE_IPODCOLOR) || defined(APPLE_IPODNANO)
24int pcf50605_read(int address);
25void pcf50605_read_multiple(int address, unsigned char* buf, int count);
26int pcf50605_write(int address, unsigned char val);
27int pcf50605_write_multiple(int address, const unsigned char* buf, int count);
28int pcf50605_battery_read(void);
29#endif
30
31#endif