2 * drivers/sbus/char/vfc_i2c.c
4 * Driver for the Videopix Frame Grabber.
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
10 * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu)
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 algorithims apper to be correct. I am
18 fairly certain that the flowcharts in the phillips docs are wrong. */
21 #include <linux/kernel.h>
22 #include <linux/string.h>
23 #include <linux/malloc.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>
31 #include <asm/system.h>
41 #define VFC_I2C_READ (0x1)
42 #define VFC_I2C_WRITE (0x0)
45 The i2c bus controller chip on the VFC is a pcd8584t, but
46 phillips claims it doesn't exist. As far as I can tell it is
47 identical to the PCF8584 so I treat it like it is the pcf8584.
49 NOTE: The pcf8584 only cares
50 about the msb of the word you feed it
53 int vfc_pcf8584_init(struct vfc_dev
*dev
)
55 dev
->regs
->i2c_s1
=RESET
; /* This will also choose
56 register S0_OWN so we can set it*/
58 dev
->regs
->i2c_reg
=0x55000000; /* the pcf8584 shifts this
59 value left one bit and uses
60 it as its i2c bus address */
61 dev
->regs
->i2c_s1
=SELECT(S2
);
62 dev
->regs
->i2c_reg
=0x14000000; /* this will set the i2c bus at
63 the same speed sun uses,
64 and set another magic bit */
66 dev
->regs
->i2c_s1
=CLEAR_I2C_BUS
; /* enable the serial port,
67 idle the i2c bus and set
73 void vfc_i2c_delay_wakeup(struct vfc_dev
*dev
)
75 /* Used to profile code and eliminate too many delays */
76 VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n",dev
->instance
));
77 wake_up(&dev
->poll_wait
);
80 void vfc_i2c_delay_no_busy(struct vfc_dev
*dev
,unsigned long usecs
)
82 dev
->poll_timer
.next
= NULL
;
83 dev
->poll_timer
.prev
= NULL
;
84 dev
->poll_timer
.expires
= jiffies
+
85 ((unsigned long)usecs
*(HZ
))/1000000;
86 dev
->poll_timer
.data
=(unsigned long)dev
;
87 dev
->poll_timer
.function
=(void *)(unsigned long)vfc_i2c_delay_wakeup
;
88 add_timer(&dev
->poll_timer
);
89 sleep_on(&dev
->poll_wait
);
90 del_timer(&dev
->poll_timer
);
93 void inline vfc_i2c_delay(struct vfc_dev
*dev
)
95 vfc_i2c_delay_no_busy(dev
,100);
98 int vfc_init_i2c_bus(struct vfc_dev
*dev
)
100 dev
->regs
->i2c_s1
= ENABLE_SERIAL
| SELECT(S0
) | ACK
;
101 vfc_i2c_reset_bus(dev
);
105 int vfc_i2c_reset_bus(struct vfc_dev
*dev
)
107 VFC_I2C_DEBUG_PRINTK((KERN_DEBUG
"vfc%d: Resetting the i2c bus\n",
109 if(!dev
) return -EINVAL
;
110 if(!dev
->regs
) return -EINVAL
;
111 dev
->regs
->i2c_s1
=SEND_I2C_STOP
;
112 dev
->regs
->i2c_s1
=SEND_I2C_STOP
| ACK
;
114 dev
->regs
->i2c_s1
=CLEAR_I2C_BUS
;
115 VFC_I2C_DEBUG_PRINTK((KERN_DEBUG
"vfc%d: I2C status %x\n",
116 dev
->instance
, dev
->regs
->i2c_s1
));
120 int vfc_i2c_wait_for_bus(struct vfc_dev
*dev
)
124 while(!(dev
->regs
->i2c_s1
& BB
)) {
125 if(!(timeout
--)) return -ETIMEDOUT
;
131 int vfc_i2c_wait_for_pin(struct vfc_dev
*dev
, int ack
)
136 while((s1
=dev
->regs
->i2c_s1
) & PIN
) {
137 if(!(timeout
--)) return -ETIMEDOUT
;
140 if(ack
==VFC_I2C_ACK_CHECK
) {
141 if(s1
& LRB
) return -EIO
;
146 #define SHIFT(a) ((a) << 24)
147 int vfc_i2c_xmit_addr(struct vfc_dev
*dev
, unsigned char addr
, char mode
)
151 dev
->regs
->i2c_s1
=SEND_I2C_STOP
| ACK
;
152 dev
->regs
->i2c_s1
=SELECT(S0
) | ENABLE_SERIAL
;
158 dev
->regs
->i2c_reg
=raddr
=SHIFT((unsigned int)addr
| 0x1);
159 VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n",
160 dev
->instance
,addr
| 0x1));
163 dev
->regs
->i2c_reg
=raddr
=SHIFT((unsigned int)addr
& ~0x1);
164 VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n",
165 dev
->instance
,addr
& ~0x1));
170 dev
->regs
->i2c_s1
= SEND_I2C_START
;
172 ret
=vfc_i2c_wait_for_pin(dev
,VFC_I2C_ACK_CHECK
); /* We wait
181 printk(KERN_ERR
"vfc%d: VFC xmit addr timed out or no ack\n",
184 } else if(mode
== VFC_I2C_READ
) {
185 if((ret
=dev
->regs
->i2c_reg
& 0xff000000) != raddr
) {
187 "vfc%d: returned slave address "
189 dev
->instance
,raddr
,ret
);
195 int vfc_i2c_xmit_byte(struct vfc_dev
*dev
,unsigned char *byte
)
198 dev
->regs
->i2c_reg
=SHIFT((unsigned int)*byte
);
200 ret
=vfc_i2c_wait_for_pin(dev
,VFC_I2C_ACK_CHECK
);
203 printk(KERN_ERR
"vfc%d: VFC xmit byte timed out or no ack\n",
215 int vfc_i2c_recv_byte(struct vfc_dev
*dev
, unsigned char *byte
, int last
)
219 dev
->regs
->i2c_reg
=NEGATIVE_ACK
;
220 VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n",
223 dev
->regs
->i2c_s1
=ACK
;
226 ret
=vfc_i2c_wait_for_pin(dev
,VFC_I2C_NO_ACK_CHECK
);
228 printk(KERN_ERR
"vfc%d: "
229 "VFC recv byte timed out\n",dev
->instance
);
231 *byte
=(dev
->regs
->i2c_reg
) >> 24;
235 int vfc_i2c_recvbuf(struct vfc_dev
*dev
, unsigned char addr
,
236 char *buf
, int count
)
240 if(!(count
&& buf
&& dev
&& dev
->regs
) ) return -EINVAL
;
242 if((ret
=vfc_i2c_wait_for_bus(dev
))) {
243 printk(KERN_ERR
"vfc%d: VFC I2C bus busy\n",dev
->instance
);
247 if((ret
=vfc_i2c_xmit_addr(dev
,addr
,VFC_I2C_READ
))) {
248 dev
->regs
->i2c_s1
=SEND_I2C_STOP
;
256 if((ret
=vfc_i2c_recv_byte(dev
,buf
,last
))) {
257 printk(KERN_ERR
"vfc%d: "
258 "VFC error while receiving byte\n",
260 dev
->regs
->i2c_s1
=SEND_I2C_STOP
;
266 dev
->regs
->i2c_s1
=SEND_I2C_STOP
| ACK
;
271 int vfc_i2c_sendbuf(struct vfc_dev
*dev
, unsigned char addr
,
272 char *buf
, int count
)
276 if(!(buf
&& dev
&& dev
->regs
) ) return -EINVAL
;
278 if((ret
=vfc_i2c_wait_for_bus(dev
))) {
279 printk(KERN_ERR
"vfc%d: VFC I2C bus busy\n",dev
->instance
);
283 if((ret
=vfc_i2c_xmit_addr(dev
,addr
,VFC_I2C_WRITE
))) {
284 dev
->regs
->i2c_s1
=SEND_I2C_STOP
;
290 ret
=vfc_i2c_xmit_byte(dev
,buf
);
293 VFC_I2C_DEBUG_PRINTK(("vfc%d: "
294 "Reciever ended transmission with "
295 " %d bytes remaining\n",
296 dev
->instance
,count
));
303 printk(KERN_ERR
"vfc%d: "
304 "VFC error while sending byte\n",dev
->instance
);
310 dev
->regs
->i2c_s1
=SEND_I2C_STOP
| ACK
;