diff options
Diffstat (limited to 'firmware/drivers/i2c-pp5002.c')
-rw-r--r-- | firmware/drivers/i2c-pp5002.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/firmware/drivers/i2c-pp5002.c b/firmware/drivers/i2c-pp5002.c new file mode 100644 index 0000000000..dc26d8a5d9 --- /dev/null +++ b/firmware/drivers/i2c-pp5002.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * PP5002 I2C driver | ||
11 | * | ||
12 | * Based on code from the ipodlinux project - http://ipodlinux.org/ | ||
13 | * Adapted for Rockbox in January 2006 | ||
14 | * | ||
15 | * Original file: linux/arch/armnommu/mach-ipod/hardware.c | ||
16 | * | ||
17 | * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) | ||
18 | * | ||
19 | * All files in this archive are subject to the GNU General Public License. | ||
20 | * See the file COPYING in the source tree root for full license agreement. | ||
21 | * | ||
22 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
23 | * KIND, either express or implied. | ||
24 | * | ||
25 | ****************************************************************************/ | ||
26 | |||
27 | #include "cpu.h" | ||
28 | #include "kernel.h" | ||
29 | #include "logf.h" | ||
30 | #include "system.h" | ||
31 | #include "i2c-pp5002.h" | ||
32 | |||
33 | /* Local functions definitions */ | ||
34 | |||
35 | #define IPOD_I2C_BASE 0xc0008000 | ||
36 | #define IPOD_I2C_CTRL (IPOD_I2C_BASE+0x00) | ||
37 | #define IPOD_I2C_ADDR (IPOD_I2C_BASE+0x04) | ||
38 | #define IPOD_I2C_DATA0 (IPOD_I2C_BASE+0x0c) | ||
39 | #define IPOD_I2C_DATA1 (IPOD_I2C_BASE+0x10) | ||
40 | #define IPOD_I2C_DATA2 (IPOD_I2C_BASE+0x14) | ||
41 | #define IPOD_I2C_DATA3 (IPOD_I2C_BASE+0x18) | ||
42 | #define IPOD_I2C_STATUS (IPOD_I2C_BASE+0x1c) | ||
43 | |||
44 | /* IPOD_I2C_CTRL bit definitions */ | ||
45 | #define IPOD_I2C_SEND 0x80 | ||
46 | |||
47 | /* IPOD_I2C_STATUS bit definitions */ | ||
48 | #define IPOD_I2C_BUSY (1<<6) | ||
49 | |||
50 | #define POLL_TIMEOUT (HZ) | ||
51 | |||
52 | static int ipod_i2c_wait_not_busy(void) | ||
53 | { | ||
54 | unsigned long timeout; | ||
55 | timeout = current_tick + POLL_TIMEOUT; | ||
56 | while (TIME_BEFORE(current_tick, timeout)) { | ||
57 | if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) { | ||
58 | return 0; | ||
59 | } | ||
60 | yield(); | ||
61 | } | ||
62 | |||
63 | return -1; | ||
64 | } | ||
65 | |||
66 | |||
67 | /* Public functions */ | ||
68 | |||
69 | int ipod_i2c_read_byte(unsigned int addr, unsigned int *data) | ||
70 | { | ||
71 | if (ipod_i2c_wait_not_busy() < 0) | ||
72 | { | ||
73 | return -1; | ||
74 | } | ||
75 | |||
76 | /* clear top 15 bits, left shift 1, or in 0x1 for a read */ | ||
77 | outb(((addr << 17) >> 16) | 0x1, IPOD_I2C_ADDR); | ||
78 | |||
79 | outb(inb(IPOD_I2C_CTRL) | 0x20, IPOD_I2C_CTRL); | ||
80 | |||
81 | outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); | ||
82 | |||
83 | if (ipod_i2c_wait_not_busy() < 0) | ||
84 | { | ||
85 | return -1; | ||
86 | } | ||
87 | |||
88 | if (data) | ||
89 | { | ||
90 | *data = inb(IPOD_I2C_DATA0); | ||
91 | } | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data) | ||
97 | { | ||
98 | int data_addr; | ||
99 | unsigned int i; | ||
100 | |||
101 | if (len < 1 || len > 4) | ||
102 | { | ||
103 | return -1; | ||
104 | } | ||
105 | |||
106 | if (ipod_i2c_wait_not_busy() < 0) | ||
107 | { | ||
108 | return -2; | ||
109 | } | ||
110 | |||
111 | /* clear top 15 bits, left shift 1 */ | ||
112 | outb((addr << 17) >> 16, IPOD_I2C_ADDR); | ||
113 | |||
114 | outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL); | ||
115 | |||
116 | data_addr = IPOD_I2C_DATA0; | ||
117 | for ( i = 0; i < len; i++ ) | ||
118 | { | ||
119 | outb(*data++, data_addr); | ||
120 | data_addr += 4; | ||
121 | } | ||
122 | |||
123 | outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((len-1) << 1), IPOD_I2C_CTRL); | ||
124 | |||
125 | outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); | ||
126 | |||
127 | return 0x0; | ||
128 | } | ||
129 | |||
130 | int ipod_i2c_send_byte(unsigned int addr, int data0) | ||
131 | { | ||
132 | unsigned char data[1]; | ||
133 | |||
134 | data[0] = data0; | ||
135 | |||
136 | return ipod_i2c_send_bytes(addr, 1, data); | ||
137 | } | ||
138 | |||
139 | |||
140 | int i2c_readbyte(unsigned int dev_addr, int addr) | ||
141 | { | ||
142 | int data; | ||
143 | |||
144 | ipod_i2c_send_byte(dev_addr, addr); | ||
145 | ipod_i2c_read_byte(dev_addr, &data); | ||
146 | |||
147 | return data; | ||
148 | } | ||
149 | |||
150 | int ipod_i2c_send(unsigned int addr, int data0, int data1) | ||
151 | { | ||
152 | unsigned char data[2]; | ||
153 | |||
154 | data[0] = data0; | ||
155 | data[1] = data1; | ||
156 | |||
157 | return ipod_i2c_send_bytes(addr, 2, data); | ||
158 | } | ||
159 | |||
160 | void i2c_init(void) | ||
161 | { | ||
162 | /* From ipodlinux */ | ||
163 | |||
164 | outl(inl(0xcf005000) | 0x2, 0xcf005000); | ||
165 | |||
166 | outl(inl(0xcf005030) | (1<<8), 0xcf005030); | ||
167 | outl(inl(0xcf005030) & ~(1<<8), 0xcf005030); | ||
168 | } | ||