diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-27 01:26:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-29 05:13:09 -0400 |
commit | 7f06a3b2c162573c924f425053227a52b4bd7cb1 (patch) | |
tree | 32ae30d8cc16ee6ea2320f927f354fa47339babd /drivers/sbus/char/vfc_i2c.c | |
parent | 902663f6ea4a2603bee0d88450aae2d653a46f5d (diff) |
sparc: Kill videopix SBUS driver.
This has been marked BROKEN for a long time and it's more likely
to get rewritten from scratch than to be fixed up and made usable.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/sbus/char/vfc_i2c.c')
-rw-r--r-- | drivers/sbus/char/vfc_i2c.c | 335 |
1 files changed, 0 insertions, 335 deletions
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c deleted file mode 100644 index 32b986e0ed78..000000000000 --- a/drivers/sbus/char/vfc_i2c.c +++ /dev/null | |||
@@ -1,335 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/sbus/char/vfc_i2c.c | ||
3 | * | ||
4 | * Driver for the Videopix Frame Grabber. | ||
5 | * | ||
6 | * Functions that support the Phillips i2c(I squared C) bus on the vfc | ||
7 | * Documentation for the Phillips I2C bus can be found on the | ||
8 | * phillips home page | ||
9 | * | ||
10 | * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu) | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | /* NOTE: It seems to me that the documentation regarding the | ||
15 | pcd8584t/pcf8584 does not show the correct way to address the i2c bus. | ||
16 | Based on the information on the I2C bus itself and the remainder of | ||
17 | the Phillips docs the following algorithms appear to be correct. I am | ||
18 | fairly certain that the flowcharts in the phillips docs are wrong. */ | ||
19 | |||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/wait.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <asm/openprom.h> | ||
29 | #include <asm/oplib.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/system.h> | ||
32 | #include <asm/sbus.h> | ||
33 | |||
34 | #if 0 | ||
35 | #define VFC_I2C_DEBUG | ||
36 | #endif | ||
37 | |||
38 | #include "vfc.h" | ||
39 | #include "vfc_i2c.h" | ||
40 | |||
41 | #define WRITE_S1(__val) \ | ||
42 | sbus_writel(__val, &dev->regs->i2c_s1) | ||
43 | #define WRITE_REG(__val) \ | ||
44 | sbus_writel(__val, &dev->regs->i2c_reg) | ||
45 | |||
46 | #define VFC_I2C_READ (0x1) | ||
47 | #define VFC_I2C_WRITE (0x0) | ||
48 | |||
49 | /****** | ||
50 | The i2c bus controller chip on the VFC is a pcd8584t, but | ||
51 | phillips claims it doesn't exist. As far as I can tell it is | ||
52 | identical to the PCF8584 so I treat it like it is the pcf8584. | ||
53 | |||
54 | NOTE: The pcf8584 only cares | ||
55 | about the msb of the word you feed it | ||
56 | *****/ | ||
57 | |||
58 | int vfc_pcf8584_init(struct vfc_dev *dev) | ||
59 | { | ||
60 | /* This will also choose register S0_OWN so we can set it. */ | ||
61 | WRITE_S1(RESET); | ||
62 | |||
63 | /* The pcf8584 shifts this value left one bit and uses | ||
64 | * it as its i2c bus address. | ||
65 | */ | ||
66 | WRITE_REG(0x55000000); | ||
67 | |||
68 | /* This will set the i2c bus at the same speed sun uses, | ||
69 | * and set another magic bit. | ||
70 | */ | ||
71 | WRITE_S1(SELECT(S2)); | ||
72 | WRITE_REG(0x14000000); | ||
73 | |||
74 | /* Enable the serial port, idle the i2c bus and set | ||
75 | * the data reg to s0. | ||
76 | */ | ||
77 | WRITE_S1(CLEAR_I2C_BUS); | ||
78 | udelay(100); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) | ||
83 | { | ||
84 | schedule_timeout_uninterruptible(usecs_to_jiffies(usecs)); | ||
85 | } | ||
86 | |||
87 | void inline vfc_i2c_delay(struct vfc_dev *dev) | ||
88 | { | ||
89 | vfc_i2c_delay_no_busy(dev, 100); | ||
90 | } | ||
91 | |||
92 | int vfc_init_i2c_bus(struct vfc_dev *dev) | ||
93 | { | ||
94 | WRITE_S1(ENABLE_SERIAL | SELECT(S0) | ACK); | ||
95 | vfc_i2c_reset_bus(dev); | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | int vfc_i2c_reset_bus(struct vfc_dev *dev) | ||
100 | { | ||
101 | VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n", | ||
102 | dev->instance)); | ||
103 | if(dev == NULL) | ||
104 | return -EINVAL; | ||
105 | if(dev->regs == NULL) | ||
106 | return -EINVAL; | ||
107 | WRITE_S1(SEND_I2C_STOP); | ||
108 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
109 | vfc_i2c_delay(dev); | ||
110 | WRITE_S1(CLEAR_I2C_BUS); | ||
111 | VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n", | ||
112 | dev->instance, | ||
113 | sbus_readl(&dev->regs->i2c_s1))); | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static int vfc_i2c_wait_for_bus(struct vfc_dev *dev) | ||
118 | { | ||
119 | int timeout = 1000; | ||
120 | |||
121 | while(!(sbus_readl(&dev->regs->i2c_s1) & BB)) { | ||
122 | if(!(timeout--)) | ||
123 | return -ETIMEDOUT; | ||
124 | vfc_i2c_delay(dev); | ||
125 | } | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack) | ||
130 | { | ||
131 | int timeout = 1000; | ||
132 | int s1; | ||
133 | |||
134 | while ((s1 = sbus_readl(&dev->regs->i2c_s1)) & PIN) { | ||
135 | if (!(timeout--)) | ||
136 | return -ETIMEDOUT; | ||
137 | vfc_i2c_delay(dev); | ||
138 | } | ||
139 | if (ack == VFC_I2C_ACK_CHECK) { | ||
140 | if(s1 & LRB) | ||
141 | return -EIO; | ||
142 | } | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | #define SHIFT(a) ((a) << 24) | ||
147 | static int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, | ||
148 | char mode) | ||
149 | { | ||
150 | int ret, raddr; | ||
151 | #if 1 | ||
152 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
153 | WRITE_S1(SELECT(S0) | ENABLE_SERIAL); | ||
154 | vfc_i2c_delay(dev); | ||
155 | #endif | ||
156 | |||
157 | switch(mode) { | ||
158 | case VFC_I2C_READ: | ||
159 | raddr = SHIFT(((unsigned int)addr | 0x1)); | ||
160 | WRITE_REG(raddr); | ||
161 | VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n", | ||
162 | dev->instance, addr | 0x1)); | ||
163 | break; | ||
164 | case VFC_I2C_WRITE: | ||
165 | raddr = SHIFT((unsigned int)addr & ~0x1); | ||
166 | WRITE_REG(raddr); | ||
167 | VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", | ||
168 | dev->instance, addr & ~0x1)); | ||
169 | break; | ||
170 | default: | ||
171 | return -EINVAL; | ||
172 | }; | ||
173 | |||
174 | WRITE_S1(SEND_I2C_START); | ||
175 | vfc_i2c_delay(dev); | ||
176 | ret = vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait | ||
177 | for the | ||
178 | i2c send | ||
179 | to finish | ||
180 | here but | ||
181 | Sun | ||
182 | doesn't, | ||
183 | hmm */ | ||
184 | if (ret) { | ||
185 | printk(KERN_ERR "vfc%d: VFC xmit addr timed out or no ack\n", | ||
186 | dev->instance); | ||
187 | return ret; | ||
188 | } else if (mode == VFC_I2C_READ) { | ||
189 | if ((ret = sbus_readl(&dev->regs->i2c_reg) & 0xff000000) != raddr) { | ||
190 | printk(KERN_WARNING | ||
191 | "vfc%d: returned slave address " | ||
192 | "mismatch(%x,%x)\n", | ||
193 | dev->instance, raddr, ret); | ||
194 | } | ||
195 | } | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte) | ||
200 | { | ||
201 | int ret; | ||
202 | u32 val = SHIFT((unsigned int)*byte); | ||
203 | |||
204 | WRITE_REG(val); | ||
205 | |||
206 | ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_ACK_CHECK); | ||
207 | switch(ret) { | ||
208 | case -ETIMEDOUT: | ||
209 | printk(KERN_ERR "vfc%d: VFC xmit byte timed out or no ack\n", | ||
210 | dev->instance); | ||
211 | break; | ||
212 | case -EIO: | ||
213 | ret = XMIT_LAST_BYTE; | ||
214 | break; | ||
215 | default: | ||
216 | break; | ||
217 | }; | ||
218 | |||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, | ||
223 | int last) | ||
224 | { | ||
225 | int ret; | ||
226 | |||
227 | if (last) { | ||
228 | WRITE_REG(NEGATIVE_ACK); | ||
229 | VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n", | ||
230 | dev->instance)); | ||
231 | } else { | ||
232 | WRITE_S1(ACK); | ||
233 | } | ||
234 | |||
235 | ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_NO_ACK_CHECK); | ||
236 | if(ret) { | ||
237 | printk(KERN_ERR "vfc%d: " | ||
238 | "VFC recv byte timed out\n", | ||
239 | dev->instance); | ||
240 | } | ||
241 | *byte = (sbus_readl(&dev->regs->i2c_reg)) >> 24; | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr, | ||
246 | char *buf, int count) | ||
247 | { | ||
248 | int ret, last; | ||
249 | |||
250 | if(!(count && buf && dev && dev->regs) ) | ||
251 | return -EINVAL; | ||
252 | |||
253 | if ((ret = vfc_i2c_wait_for_bus(dev))) { | ||
254 | printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_READ))) { | ||
259 | WRITE_S1(SEND_I2C_STOP); | ||
260 | vfc_i2c_delay(dev); | ||
261 | return ret; | ||
262 | } | ||
263 | |||
264 | last = 0; | ||
265 | while (count--) { | ||
266 | if (!count) | ||
267 | last = 1; | ||
268 | if ((ret = vfc_i2c_recv_byte(dev, buf, last))) { | ||
269 | printk(KERN_ERR "vfc%d: " | ||
270 | "VFC error while receiving byte\n", | ||
271 | dev->instance); | ||
272 | WRITE_S1(SEND_I2C_STOP); | ||
273 | ret = -EINVAL; | ||
274 | } | ||
275 | buf++; | ||
276 | } | ||
277 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
278 | vfc_i2c_delay(dev); | ||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | int vfc_i2c_sendbuf(struct vfc_dev *dev, unsigned char addr, | ||
283 | char *buf, int count) | ||
284 | { | ||
285 | int ret; | ||
286 | |||
287 | if (!(buf && dev && dev->regs)) | ||
288 | return -EINVAL; | ||
289 | |||
290 | if ((ret = vfc_i2c_wait_for_bus(dev))) { | ||
291 | printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); | ||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_WRITE))) { | ||
296 | WRITE_S1(SEND_I2C_STOP); | ||
297 | vfc_i2c_delay(dev); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | while(count--) { | ||
302 | ret = vfc_i2c_xmit_byte(dev, buf); | ||
303 | switch(ret) { | ||
304 | case XMIT_LAST_BYTE: | ||
305 | VFC_I2C_DEBUG_PRINTK(("vfc%d: " | ||
306 | "Receiver ended transmission with " | ||
307 | " %d bytes remaining\n", | ||
308 | dev->instance, count)); | ||
309 | ret = 0; | ||
310 | goto done; | ||
311 | break; | ||
312 | case 0: | ||
313 | break; | ||
314 | default: | ||
315 | printk(KERN_ERR "vfc%d: " | ||
316 | "VFC error while sending byte\n", dev->instance); | ||
317 | break; | ||
318 | }; | ||
319 | |||
320 | buf++; | ||
321 | } | ||
322 | done: | ||
323 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
324 | vfc_i2c_delay(dev); | ||
325 | return ret; | ||
326 | } | ||
327 | |||
328 | |||
329 | |||
330 | |||
331 | |||
332 | |||
333 | |||
334 | |||
335 | |||