| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | 
| Robert P. J. Day | d08df60 | 2007-02-17 19:07:33 +0100 | [diff] [blame] | 17 | the Phillips docs the following algorithms appear to be correct.  I am | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 82 | void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs)  | 
 | 83 | { | 
| Nishanth Aravamudan | 074c527 | 2005-09-12 14:16:17 -0700 | [diff] [blame] | 84 | 	schedule_timeout_uninterruptible(usecs_to_jiffies(usecs)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | 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 | 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 | int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, char mode)  | 
 | 148 | {  | 
 | 149 | 	int ret, raddr; | 
 | 150 | #if 1 | 
 | 151 | 	WRITE_S1(SEND_I2C_STOP | ACK); | 
 | 152 | 	WRITE_S1(SELECT(S0) | ENABLE_SERIAL); | 
 | 153 | 	vfc_i2c_delay(dev); | 
 | 154 | #endif | 
 | 155 |  | 
 | 156 | 	switch(mode) { | 
 | 157 | 	case VFC_I2C_READ: | 
 | 158 | 		raddr = SHIFT(((unsigned int)addr | 0x1)); | 
 | 159 | 		WRITE_REG(raddr); | 
 | 160 | 		VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n", | 
 | 161 | 				      dev->instance, addr | 0x1)); | 
 | 162 | 		break; | 
 | 163 | 	case VFC_I2C_WRITE: | 
 | 164 | 		raddr = SHIFT((unsigned int)addr & ~0x1); | 
 | 165 | 		WRITE_REG(raddr); | 
 | 166 | 		VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", | 
 | 167 | 				      dev->instance, addr & ~0x1)); | 
 | 168 | 		break; | 
 | 169 | 	default: | 
 | 170 | 		return -EINVAL; | 
 | 171 | 	}; | 
 | 172 |  | 
 | 173 | 	WRITE_S1(SEND_I2C_START); | 
 | 174 | 	vfc_i2c_delay(dev); | 
 | 175 | 	ret = vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait | 
 | 176 | 							      for the | 
 | 177 | 							      i2c send | 
 | 178 | 							      to finish | 
 | 179 | 							      here but | 
 | 180 | 							      Sun | 
 | 181 | 							      doesn't, | 
 | 182 | 							      hmm */ | 
 | 183 | 	if (ret) { | 
 | 184 | 		printk(KERN_ERR "vfc%d: VFC xmit addr timed out or no ack\n", | 
 | 185 | 		       dev->instance); | 
 | 186 | 		return ret; | 
 | 187 | 	} else if (mode == VFC_I2C_READ) { | 
 | 188 | 		if ((ret = sbus_readl(&dev->regs->i2c_reg) & 0xff000000) != raddr) { | 
 | 189 | 			printk(KERN_WARNING  | 
 | 190 | 			       "vfc%d: returned slave address " | 
 | 191 | 			       "mismatch(%x,%x)\n", | 
 | 192 | 			       dev->instance, raddr, ret); | 
 | 193 | 		} | 
 | 194 | 	}	 | 
 | 195 | 	return 0; | 
 | 196 | } | 
 | 197 |  | 
 | 198 | int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte)  | 
 | 199 | { | 
 | 200 | 	int ret; | 
 | 201 | 	u32 val = SHIFT((unsigned int)*byte); | 
 | 202 |  | 
 | 203 | 	WRITE_REG(val); | 
 | 204 |  | 
 | 205 | 	ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_ACK_CHECK);  | 
 | 206 | 	switch(ret) { | 
 | 207 | 	case -ETIMEDOUT:  | 
 | 208 | 		printk(KERN_ERR "vfc%d: VFC xmit byte timed out or no ack\n", | 
 | 209 | 		       dev->instance); | 
 | 210 | 		break; | 
 | 211 | 	case -EIO: | 
 | 212 | 		ret = XMIT_LAST_BYTE; | 
 | 213 | 		break; | 
 | 214 | 	default: | 
 | 215 | 		break; | 
 | 216 | 	}; | 
 | 217 |  | 
 | 218 | 	return ret; | 
 | 219 | } | 
 | 220 |  | 
 | 221 | int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, int last)  | 
 | 222 | { | 
 | 223 | 	int ret; | 
 | 224 |  | 
 | 225 | 	if (last) { | 
 | 226 | 		WRITE_REG(NEGATIVE_ACK); | 
 | 227 | 		VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n", | 
 | 228 | 				      dev->instance)); | 
 | 229 | 	} else { | 
 | 230 | 		WRITE_S1(ACK); | 
 | 231 | 	} | 
 | 232 |  | 
 | 233 | 	ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_NO_ACK_CHECK); | 
 | 234 | 	if(ret) { | 
 | 235 | 		printk(KERN_ERR "vfc%d: " | 
 | 236 | 		       "VFC recv byte timed out\n", | 
 | 237 | 		       dev->instance); | 
 | 238 | 	} | 
 | 239 | 	*byte = (sbus_readl(&dev->regs->i2c_reg)) >> 24; | 
 | 240 | 	return ret; | 
 | 241 | } | 
 | 242 |  | 
 | 243 | int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr, | 
 | 244 | 		    char *buf, int count) | 
 | 245 | { | 
 | 246 | 	int ret, last; | 
 | 247 |  | 
 | 248 | 	if(!(count && buf && dev && dev->regs) ) | 
 | 249 | 		return -EINVAL; | 
 | 250 |  | 
 | 251 | 	if ((ret = vfc_i2c_wait_for_bus(dev))) { | 
 | 252 | 		printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); | 
 | 253 | 		return ret; | 
 | 254 | 	} | 
 | 255 |  | 
 | 256 | 	if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_READ))) { | 
 | 257 | 		WRITE_S1(SEND_I2C_STOP); | 
 | 258 | 		vfc_i2c_delay(dev); | 
 | 259 | 		return ret; | 
 | 260 | 	} | 
 | 261 | 	 | 
 | 262 | 	last = 0; | 
 | 263 | 	while (count--) { | 
 | 264 | 		if (!count) | 
 | 265 | 			last = 1; | 
 | 266 | 		if ((ret = vfc_i2c_recv_byte(dev, buf, last))) { | 
 | 267 | 			printk(KERN_ERR "vfc%d: " | 
 | 268 | 			       "VFC error while receiving byte\n", | 
 | 269 | 			       dev->instance); | 
 | 270 | 			WRITE_S1(SEND_I2C_STOP); | 
 | 271 | 			ret = -EINVAL; | 
 | 272 | 		} | 
 | 273 | 		buf++; | 
 | 274 | 	} | 
 | 275 | 	WRITE_S1(SEND_I2C_STOP | ACK); | 
 | 276 | 	vfc_i2c_delay(dev); | 
 | 277 | 	return ret; | 
 | 278 | } | 
 | 279 |  | 
 | 280 | int vfc_i2c_sendbuf(struct vfc_dev *dev, unsigned char addr,  | 
 | 281 | 		    char *buf, int count)  | 
 | 282 | { | 
 | 283 | 	int ret; | 
 | 284 | 	 | 
 | 285 | 	if (!(buf && dev && dev->regs)) | 
 | 286 | 		return -EINVAL; | 
 | 287 | 	 | 
 | 288 | 	if ((ret = vfc_i2c_wait_for_bus(dev))) { | 
 | 289 | 		printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); | 
 | 290 | 		return ret; | 
 | 291 | 	} | 
 | 292 | 	 | 
 | 293 | 	if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_WRITE))) { | 
 | 294 | 		WRITE_S1(SEND_I2C_STOP); | 
 | 295 | 		vfc_i2c_delay(dev); | 
 | 296 | 		return ret; | 
 | 297 | 	} | 
 | 298 | 	 | 
 | 299 | 	while(count--) { | 
 | 300 | 		ret = vfc_i2c_xmit_byte(dev, buf); | 
 | 301 | 		switch(ret) { | 
 | 302 | 		case XMIT_LAST_BYTE: | 
 | 303 | 			VFC_I2C_DEBUG_PRINTK(("vfc%d: " | 
 | 304 | 					      "Receiver ended transmission with " | 
 | 305 | 					      " %d bytes remaining\n", | 
 | 306 | 					      dev->instance, count)); | 
 | 307 | 			ret = 0; | 
 | 308 | 			goto done; | 
 | 309 | 			break; | 
 | 310 | 		case 0: | 
 | 311 | 			break; | 
 | 312 | 		default: | 
 | 313 | 			printk(KERN_ERR "vfc%d: " | 
 | 314 | 			       "VFC error while sending byte\n", dev->instance); | 
 | 315 | 			break; | 
 | 316 | 		}; | 
 | 317 |  | 
 | 318 | 		buf++; | 
 | 319 | 	} | 
 | 320 | done: | 
 | 321 | 	WRITE_S1(SEND_I2C_STOP | ACK); | 
 | 322 | 	vfc_i2c_delay(dev); | 
 | 323 | 	return ret; | 
 | 324 | } | 
 | 325 |  | 
 | 326 |  | 
 | 327 |  | 
 | 328 |  | 
 | 329 |  | 
 | 330 |  | 
 | 331 |  | 
 | 332 |  | 
 | 333 |  |