/*
 * Basic I2C functions
 *
 * Copyright (c) 2004 Texas Instruments
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Author: Jian Zhang jzhang@ti.com, Texas Instruments
 *
 * Copyright (c) 2003 Wolfgang Denk, wd@denx.de
 * Rewritten to fit into the current U-Boot framework
 *
 * Adapted for OMAP2420 I2C, r-woodruff2@ti.com
 *
 */

#include <common.h>

#ifdef CONFIG_DRIVER_OMAP24XX_I2C

#include <asm/arch/i2c.h>
#include <asm/io.h>

#define inw(a) __raw_readw(a)
#define outw(a,v) __raw_writew(a,v)

static void wait_for_bb (void);
static u16 wait_for_pin (void);
void flush_fifo(void);

void i2c_init (int speed, int slaveadd)
{
	u16 scl;

	if (inw (I2C_CON) & I2C_CON_EN) {
		outw (0, I2C_CON);
		udelay (50000);
	}

	/* 12Mhz I2C module clock */
	outw (0, I2C_PSC);
	speed = speed/1000;		    /* 100 or 400 */
	scl = ((12000/(speed*2)) - 7);	/* use 7 when PSC = 0 */
	outw (scl, I2C_SCLL);
	outw (scl, I2C_SCLH);
	/* own address */
	outw (slaveadd, I2C_OA);
	outw (I2C_CON_EN, I2C_CON);
	outw (0, I2C_CNT);
	/* have to enable intrrupts or OMAP i2c module doesn't work */
	outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
	      I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
	udelay (1000);
}

static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
{
	int i2c_error = 0;
	u16 status;

	/* wait until bus not busy */
	wait_for_bb ();

	/* one byte only */
	outw (1, I2C_CNT);
	/* set slave address */
	outw (devaddr, I2C_SA);
	/* no stop bit needed here */
	outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON);

	status = wait_for_pin ();

	if (status & I2C_STAT_XRDY) {
		/* Important: have to use byte access */
		*(volatile u8 *) (I2C_DATA) = regoffset;
		udelay (20000);
		if (inw (I2C_STAT) & I2C_STAT_NACK) {
			i2c_error = 1;
		}
	} else {
		i2c_error = 1;
	}

	if (!i2c_error) {
		/* free bus, otherwise we can't use a combined transction */
		outw (0, I2C_CON);
		while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) {
			udelay (10000);
			/* Have to clear pending interrupt to clear I2C_STAT */
			outw (0xFFFF, I2C_STAT);
		}

		wait_for_bb ();
		/* set slave address */
		outw (devaddr, I2C_SA);
		/* read one byte from slave */
		outw (1, I2C_CNT);
		/* need stop bit here */
		outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
		      I2C_CON);

		status = wait_for_pin ();
		if (status & I2C_STAT_RRDY) {
			*value = inw (I2C_DATA);
			udelay (20000);
		} else {
			i2c_error = 1;
		}

		if (!i2c_error) {
			outw (I2C_CON_EN, I2C_CON);
			while (inw (I2C_STAT)
			       || (inw (I2C_CON) & I2C_CON_MST)) {
				udelay (10000);
				outw (0xFFFF, I2C_STAT);
			}
		}
	}
	flush_fifo();
	outw (0xFFFF, I2C_STAT);
	outw (0, I2C_CNT);
	return i2c_error;
}

static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
{
	int i2c_error = 0;
	u16 status, stat;

	/* wait until bus not busy */
	wait_for_bb ();

	/* two bytes */
	outw (2, I2C_CNT);
	/* set slave address */
	outw (devaddr, I2C_SA);
	/* stop bit needed here */
	outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
	      I2C_CON_STP, I2C_CON);

	/* wait until state change */
	status = wait_for_pin ();

	if (status & I2C_STAT_XRDY) {
		/* send out two bytes */
		outw ((value << 8) + regoffset, I2C_DATA);
		/* must have enough delay to allow BB bit to go low */
		udelay (50000);
		if (inw (I2C_STAT) & I2C_STAT_NACK) {
			i2c_error = 1;
		}
	} else {
		i2c_error = 1;
	}

	if (!i2c_error) {
		outw (I2C_CON_EN, I2C_CON);
		while ((stat = inw (I2C_STAT)) || (inw (I2C_CON) & I2C_CON_MST)) {
			udelay (1000);
			/* have to read to clear intrrupt */
			outw (0xFFFF, I2C_STAT);
		}
	}
	flush_fifo();
	outw (0xFFFF, I2C_STAT);
	outw (0, I2C_CNT);
	return i2c_error;
}

void flush_fifo(void)
{	u16 stat;

	/* note: if you try and read data when its not there or ready
	 * you get a bus error
	 */
	while(1){
		stat = inw(I2C_STAT);
		if(stat == I2C_STAT_RRDY){
			inw(I2C_DATA);
			outw(I2C_STAT_RRDY,I2C_STAT);
			udelay(1000);
		}else
			break;
	}
}

int i2c_probe (uchar chip)
{
	int res = 1; /* default = fail */

	if (chip == inw (I2C_OA)) {
		return res;
	}

	/* wait until bus not busy */
	wait_for_bb ();

	/* try to read one byte */
	outw (1, I2C_CNT);
	/* set slave address */
	outw (chip, I2C_SA);
	/* stop bit needed here */
	outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON);
	/* enough delay for the NACK bit set */
	udelay (50000);

	if (!(inw (I2C_STAT) & I2C_STAT_NACK)) {
		res = 0;      /* success case */
		flush_fifo();
		outw(0xFFFF, I2C_STAT);
	} else {
		outw(0xFFFF, I2C_STAT);	 /* failue, clear sources*/
		outw (inw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */
		udelay(20000);
		wait_for_bb ();
	}
	flush_fifo();
	outw (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/
	outw(0xFFFF, I2C_STAT);
	return res;
}

int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
{
	int i;

	if (alen > 1) {
		printf ("I2C read: addr len %d not supported\n", alen);
		return 1;
	}

	if (addr + len > 256) {
		printf ("I2C read: address out of range\n");
		return 1;
	}

	for (i = 0; i < len; i++) {
		if (i2c_read_byte (chip, addr + i, &buffer[i])) {
			printf ("I2C read: I/O error\n");
			i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
			return 1;
		}
	}

	return 0;
}

int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
{
	int i;

	if (alen > 1) {
		printf ("I2C read: addr len %d not supported\n", alen);
		return 1;
	}

	if (addr + len > 256) {
		printf ("I2C read: address out of range\n");
		return 1;
	}

	for (i = 0; i < len; i++) {
		if (i2c_write_byte (chip, addr + i, buffer[i])) {
			printf ("I2C read: I/O error\n");
			i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
			return 1;
		}
	}

	return 0;
}

static void wait_for_bb (void)
{
	int timeout = 10;
	u16 stat;

	outw(0xFFFF, I2C_STAT);	 /* clear current interruts...*/
	while ((stat = inw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
		outw (stat, I2C_STAT);
		udelay (50000);
	}

	if (timeout <= 0) {
		printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
			inw (I2C_STAT));
	}
	outw(0xFFFF, I2C_STAT);	 /* clear delayed stuff*/
}

static u16 wait_for_pin (void)
{
	u16 status;
	int timeout = 10;

	do {
		udelay (1000);
		status = inw (I2C_STAT);
	} while (  !(status &
		   (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
		    I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
		    I2C_STAT_AL)) && timeout--);

	if (timeout <= 0) {
		printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
			inw (I2C_STAT));
			outw(0xFFFF, I2C_STAT);
}
	return status;
}

#endif /* CONFIG_DRIVER_OMAP24XX_I2C */
