summaryrefslogtreecommitdiff
path: root/firmware/drivers/i2c-pp5020.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/i2c-pp5020.c')
-rw-r--r--firmware/drivers/i2c-pp5020.c170
1 files changed, 71 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 @@
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}