/*
 * drivers/sbus/char/vfc_i2c.c
 *
 * Driver for the Videopix Frame Grabber.
 * 
 * Functions that support the Phillips i2c(I squared C) bus on the vfc
 *  Documentation for the Phillips I2C bus can be found on the 
 *  phillips home page
 *
 * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu)
 *
 */

/* NOTE: It seems to me that the documentation regarding the
pcd8584t/pcf8584 does not show the correct way to address the i2c bus.
Based on the information on the I2C bus itself and the remainder of
the Phillips docs the following algorithms appear to be correct.  I am
fairly certain that the flowcharts in the phillips docs are wrong. */


#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/sbus.h>

#if 0 
#define VFC_I2C_DEBUG
#endif

#include "vfc.h"
#include "vfc_i2c.h"

#define WRITE_S1(__val) \
	sbus_writel(__val, &dev->regs->i2c_s1)
#define WRITE_REG(__val) \
	sbus_writel(__val, &dev->regs->i2c_reg)

#define VFC_I2C_READ (0x1)
#define VFC_I2C_WRITE (0x0)
     
/****** 
  The i2c bus controller chip on the VFC is a pcd8584t, but
  phillips claims it doesn't exist.  As far as I can tell it is
  identical to the PCF8584 so I treat it like it is the pcf8584.
  
  NOTE: The pcf8584 only cares
  about the msb of the word you feed it 
*****/

int vfc_pcf8584_init(struct vfc_dev *dev) 
{
	/* This will also choose register S0_OWN so we can set it. */
	WRITE_S1(RESET);

	/* The pcf8584 shifts this value left one bit and uses
	 * it as its i2c bus address.
	 */
	WRITE_REG(0x55000000);

	/* This will set the i2c bus at the same speed sun uses,
	 * and set another magic bit.
	 */
	WRITE_S1(SELECT(S2));
	WRITE_REG(0x14000000);
	
	/* Enable the serial port, idle the i2c bus and set
	 * the data reg to s0.
	 */
	WRITE_S1(CLEAR_I2C_BUS);
	udelay(100);
	return 0;
}

void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) 
{
	schedule_timeout_uninterruptible(usecs_to_jiffies(usecs));
}

void inline vfc_i2c_delay(struct vfc_dev *dev) 
{ 
	vfc_i2c_delay_no_busy(dev, 100);
}

int vfc_init_i2c_bus(struct vfc_dev *dev)
{
	WRITE_S1(ENABLE_SERIAL | SELECT(S0) | ACK);
	vfc_i2c_reset_bus(dev);
	return 0;
}

int vfc_i2c_reset_bus(struct vfc_dev *dev) 
{
	VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n",
			      dev->instance));
	if(dev == NULL)
		return -EINVAL;
	if(dev->regs == NULL)
		return -EINVAL;
	WRITE_S1(SEND_I2C_STOP);
	WRITE_S1(SEND_I2C_STOP | ACK);
	vfc_i2c_delay(dev);
	WRITE_S1(CLEAR_I2C_BUS);
	VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n",
			      dev->instance,
			      sbus_readl(&dev->regs->i2c_s1)));
	return 0;
}

static int vfc_i2c_wait_for_bus(struct vfc_dev *dev)
{
	int timeout = 1000; 

	while(!(sbus_readl(&dev->regs->i2c_s1) & BB)) {
		if(!(timeout--))
			return -ETIMEDOUT;
		vfc_i2c_delay(dev);
	}
	return 0;
}

static int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack)
{
	int timeout = 1000; 
	int s1;

	while ((s1 = sbus_readl(&dev->regs->i2c_s1)) & PIN) {
		if (!(timeout--))
			return -ETIMEDOUT;
		vfc_i2c_delay(dev);
	}
	if (ack == VFC_I2C_ACK_CHECK) {
		if(s1 & LRB)
			return -EIO; 
	}
	return 0;
}

#define SHIFT(a) ((a) << 24)
static int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr,
			     char mode)
{ 
	int ret, raddr;
#if 1
	WRITE_S1(SEND_I2C_STOP | ACK);
	WRITE_S1(SELECT(S0) | ENABLE_SERIAL);
	vfc_i2c_delay(dev);
#endif

	switch(mode) {
	case VFC_I2C_READ:
		raddr = SHIFT(((unsigned int)addr | 0x1));
		WRITE_REG(raddr);
		VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n",
				      dev->instance, addr | 0x1));
		break;
	case VFC_I2C_WRITE:
		raddr = SHIFT((unsigned int)addr & ~0x1);
		WRITE_REG(raddr);
		VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n",
				      dev->instance, addr & ~0x1));
		break;
	default:
		return -EINVAL;
	};

	WRITE_S1(SEND_I2C_START);
	vfc_i2c_delay(dev);
	ret = vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait
							      for the
							      i2c send
							      to finish
							      here but
							      Sun
							      doesn't,
							      hmm */
	if (ret) {
		printk(KERN_ERR "vfc%d: VFC xmit addr timed out or no ack\n",
		       dev->instance);
		return ret;
	} else if (mode == VFC_I2C_READ) {
		if ((ret = sbus_readl(&dev->regs->i2c_reg) & 0xff000000) != raddr) {
			printk(KERN_WARNING 
			       "vfc%d: returned slave address "
			       "mismatch(%x,%x)\n",
			       dev->instance, raddr, ret);
		}
	}	
	return 0;
}

static int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte)
{
	int ret;
	u32 val = SHIFT((unsigned int)*byte);

	WRITE_REG(val);

	ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_ACK_CHECK); 
	switch(ret) {
	case -ETIMEDOUT: 
		printk(KERN_ERR "vfc%d: VFC xmit byte timed out or no ack\n",
		       dev->instance);
		break;
	case -EIO:
		ret = XMIT_LAST_BYTE;
		break;
	default:
		break;
	};

	return ret;
}

static int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte,
			     int last)
{
	int ret;

	if (last) {
		WRITE_REG(NEGATIVE_ACK);
		VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n",
				      dev->instance));
	} else {
		WRITE_S1(ACK);
	}

	ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_NO_ACK_CHECK);
	if(ret) {
		printk(KERN_ERR "vfc%d: "
		       "VFC recv byte timed out\n",
		       dev->instance);
	}
	*byte = (sbus_readl(&dev->regs->i2c_reg)) >> 24;
	return ret;
}

int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr,
		    char *buf, int count)
{
	int ret, last;

	if(!(count && buf && dev && dev->regs) )
		return -EINVAL;

	if ((ret = vfc_i2c_wait_for_bus(dev))) {
		printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance);
		return ret;
	}

	if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_READ))) {
		WRITE_S1(SEND_I2C_STOP);
		vfc_i2c_delay(dev);
		return ret;
	}
	
	last = 0;
	while (count--) {
		if (!count)
			last = 1;
		if ((ret = vfc_i2c_recv_byte(dev, buf, last))) {
			printk(KERN_ERR "vfc%d: "
			       "VFC error while receiving byte\n",
			       dev->instance);
			WRITE_S1(SEND_I2C_STOP);
			ret = -EINVAL;
		}
		buf++;
	}
	WRITE_S1(SEND_I2C_STOP | ACK);
	vfc_i2c_delay(dev);
	return ret;
}

int vfc_i2c_sendbuf(struct vfc_dev *dev, unsigned char addr, 
		    char *buf, int count) 
{
	int ret;
	
	if (!(buf && dev && dev->regs))
		return -EINVAL;
	
	if ((ret = vfc_i2c_wait_for_bus(dev))) {
		printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance);
		return ret;
	}
	
	if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_WRITE))) {
		WRITE_S1(SEND_I2C_STOP);
		vfc_i2c_delay(dev);
		return ret;
	}
	
	while(count--) {
		ret = vfc_i2c_xmit_byte(dev, buf);
		switch(ret) {
		case XMIT_LAST_BYTE:
			VFC_I2C_DEBUG_PRINTK(("vfc%d: "
					      "Receiver ended transmission with "
					      " %d bytes remaining\n",
					      dev->instance, count));
			ret = 0;
			goto done;
			break;
		case 0:
			break;
		default:
			printk(KERN_ERR "vfc%d: "
			       "VFC error while sending byte\n", dev->instance);
			break;
		};

		buf++;
	}
done:
	WRITE_S1(SEND_I2C_STOP | ACK);
	vfc_i2c_delay(dev);
	return ret;
}









