diff options
Diffstat (limited to 'firmware/drivers/i2c-pp5020.c')
-rw-r--r-- | firmware/drivers/i2c-pp5020.c | 170 |
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 | ||
32 | static int i2c_write_byte(int device, unsigned char data); | ||
33 | static int i2c_gen_start(int device); | ||
34 | static void i2c_gen_stop(int device); | ||
35 | static 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 | ||
55 | static int | 45 | static int ipod_i2c_wait_not_busy(void) |
56 | ipod_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 | ||
76 | void i2c_init(void) | 62 | int 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 | ||
90 | void 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 | /** | 89 | int 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 | */ | ||
100 | int 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 | 123 | int ipod_i2c_send_byte(unsigned int addr, int data0) |
136 | /* Write a byte to the interface, returns 0 on success, -1 otherwise. */ | ||
137 | static 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); | 133 | int 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 | 143 | int ipod_i2c_send(unsigned int addr, int data0, int data1) | |
158 | /* Returns 0 on success, -1 on failure */ | ||
159 | int 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 | ||
179 | void i2c_gen_stop(int device) | 153 | void 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 | ||
187 | volatile 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 | } |