/*
 * Copyright (c) 2016, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

/**
 * \file:    DM8127_i2c.c
 *
 * \brief:   I2C routines for DM8127 EVM
 * \n        This file contains the routines for configuring and
 * \n        accessing the I2C controller and slave devices.
 *
 */

/*
 *====================
 * Includes
 *====================
 */
#include "dm8127_platform.h"
#include "dm8127_types.h"
#include "dm8127_i2c.h"
#include "dm8127_evm.h"
#include "aic3104.h"
#include "stdio.h"

/*
 *====================
 * Defines
 *====================
*/
#define I2C_FUNC_CLOCK		(48000000)
#define I2C_BUS_CLOCK		(10000u)
#define DM8127_I2C_TIMEOUT	(100000u)


/*
 *=========================
 * Function implementations
 *========================
 */

/***
 * \brief: Routine to initialize the I2C - 0
 *
 * \b \Descr: This routine initializes the I2C instance 0. We are not configuring the
 * \n         interrupts here as the code is intended to carry out all I/O operations
 * \n         in polled mode.
 *
 * \param: u8BusNum		[IN]	Bus Instance number
 *
 * \return: SUCCESS for success  - Description
 * \n       FAILED for error   - Description
 *
 */
STATUS DM8127I2cInit
(
	UINT8	u8BusNum
)
{
	STATUS	u32RetVal = SUCCESS;
	UINT16	u16SlaveAddr;
	DM8127_I2C_REGS	stI2cRegs ;
	UINT16	u16delayCnt;
	UINT16  u16SCLValues = 0;
	
	stI2cRegs = INIT_VAL;
	u16delayCnt = 1000;
	u16SlaveAddr = 0x18; /* I2c Slave address 0xcc */
	switch (u8BusNum)
	{
		/* This is based on the devices */
		case aic3104_I2C_BUS_NUM_0:
			stI2cRegs = (DM8127_I2C_REGS) I2C0_BASE;
#ifdef DEBUG
			printf("\r\n Initializing Bus number 0\r\n");
#else
		//	Uart_stringSend("\r\nI2c Bus number 0 initialized\r\n");
#endif
			break;

		case aic3104_I2C_BUS_NUM_1:
			stI2cRegs = (DM8127_I2C_REGS) I2C1_BASE;
#ifdef DEBUG
			printf("\r\n Initializing Bus number 1\r\n");
#else
		//	Uart_stringSend("\r\nI2c Bus number 1 initialized\r\n");
#endif
			break;

		case aic3104_I2C_BUS_NUM_2:
			stI2cRegs = (DM8127_I2C_REGS) I2C2_BASE;
#ifdef DEBUG
			printf("\r\n Initializing Bus number 2\r\n");
#else
		//	Uart_stringSend("\r\nI2c Bus number 2 initialized\r\n");
#endif
			break;

		case aic3104_I2C_BUS_NUM_3:
			stI2cRegs = (DM8127_I2C_REGS) I2C3_BASE;
#ifdef DEBUG
			printf("\r\n Initializing Bus number 3\r\n");
#else
		//	Uart_stringSend("\r\nI2c Bus number 3 initialized\r\n");
#endif
			break;

		default:
			stI2cRegs = (DM8127_I2C_REGS) INIT_VAL;
			printf ("Invalid I2C bus number \r\n");
			return FAILED;
	}
	
	/* Ensure the module is enabled and the clock to it is also enabled */
	/* This register handled the clock for the I2C_0 and for the I2c_2*/
	*(UINT32*) CM_ALWON_I2C_0_CLKCTRL = 0x02;
	
	delay(1000);
	
	/* Check the state is changed */
	while ((*(UINT32*) CM_ALWON_I2C_0_CLKCTRL) & 0x00030000);

	/* Ensure the module is enabled and the clock to it is also enabled */
	*(UINT32*) CM_ALWON_I2C_1_CLKCTRL = 0x02;
	
	delay(1000);
	
	/* Check the state is changed 0x30000 is the reset value of the
	 * CM_ALWON_I2C_1_CLKCTRL */
	while ((*(UINT32*) CM_ALWON_I2C_1_CLKCTRL) & 0x00030000);


	/* Reset all the registers */
	stI2cRegs->I2C_CON = 0;
	stI2cRegs->I2C_PSC = 0;
	stI2cRegs->I2C_SCLL = 0;
	stI2cRegs->I2C_SCLH = 0;
	stI2cRegs->I2C_BUF = 0;
	stI2cRegs->I2C_SYSC = 0;
	stI2cRegs->I2C_WE = 0;
	stI2cRegs->I2C_STAT = 0xFFFF;
		
	/* DM8127 */
	delay (500);

	/* soft-reset the I2c Controller */
	stI2cRegs->I2C_SYSC = SYSC_SOFTRESET_MASK; 
	
	/* For some reasons, the I2C requires to be enabled for reset to complete */
	stI2cRegs->I2C_CON = I2C_CON_EN;
	
	/* wait till reset is done */
	while (SYSS_RESETDONE_MASK != (stI2cRegs->I2C_SYSC & SYSS_RESETDONE_MASK))
	{
		u16delayCnt--;
		delay(1);
		
		if (u16delayCnt <= 0)
			break;
	}
	
	if (u16delayCnt == 0)
	{
		u32RetVal = FAILED;
		return (u32RetVal);
	}
	
	/* SYSC register is cleared by the reset, rewrite it */
	stI2cRegs->I2C_SYSC = SYSC_AUTOIDLE_MASK
            			| SYSC_ENAWAKEUP_MASK
            			| (SYSC_IDLEMODE_SMART << SYSC_IDLEMODE_SHIFT)
            			| (SYSC_CLOCKACTIVITY_FCLK << SYSC_CLOCKACTIVITY_SHIFT);
	
	/* Disable the controller */
	stI2cRegs->I2C_CON = 0;
	
	/* compute the PSC value */
	if (I2C_BUS_CLOCK > 100000)
	{
		/* I2C_FUNC_CLOCL = 48 Mhz
		 * I2C Internal Clock = 12 Mhz
		 * SCL values = (Internal Clock)/(2*(BUS Speed)) */
		stI2cRegs->I2C_PSC = 3;
		u16SCLValues = 12000000/I2C_BUS_CLOCK;
	}	
	else
	{
		/* I2C Functional clock = 48 Mhz
		 * I2C Internal clock = 4 Mhz
		 * SCL Values = (Internal Clock)/(2*(BUS Speed)) */
		stI2cRegs->I2C_PSC = 11;
		u16SCLValues = 4000000/I2C_BUS_CLOCK;
	}
	
	/* Disable  & clear all the Interrupts */
	stI2cRegs->I2C_IRQENABLE_CLR = 0x6FF;
	

	/* set the SCL Low and High time */
	stI2cRegs->I2C_SCLL = u16SCLValues - 7;
	stI2cRegs->I2C_SCLH = u16SCLValues - 5;
	
	/* Set the self address */
	stI2cRegs->I2C_OA = u16SlaveAddr & I2C_OA_MASK;
	
	/* Enable the I2C controller */
	stI2cRegs->I2C_CON = I2C_CON_EN;
	
	/* We don't operate in interrupt mode. So disable the interrupts */
	stI2cRegs->I2C_IE = 0;
	
	/* set the slave address */
	stI2cRegs->I2C_SA = 0x0;
	
	/* Set data count */
	stI2cRegs->I2C_CNT = 0x0;
	
	return (u32RetVal);

}

/***
 * \brief: Routine to write data from slave deice the I2C - 2
 *
 * \b \Descr: This routine initializes the I2C controller for writing to the slave
 *            peripheral connected to the bus. This function takes the slave address
 *            as a parameter along with the write buffer pointer and the length of buffer.
 *            This function returns the number of bytes writen into the output len pointer.
 *
 * \param  u8BusNum 		 [IN]		I2C Bus number
 * \n      u16SlaveAddr 	 [IN]		I2C Slave address to read from
 * \n      *u8Buffer		 [OUT]		Buffer pointer to copy data into
 * \n      u8BufLen 		 [IN]		Length of the input buffer pointer
 * \n      *u8DataWritten    [OUT]		Place holder to return read number of bytes
 *
 * \return  SUCCESS for success  - Description
 * \n   	FAILED for error   - Description
 */
SINT32 DM8127I2cWitecamera
(
	UINT8 	u8BusNum,
	UINT16 	u16SlaveAddr,
	UINT8	*u8Buffer,
	UINT8	u8BufLen,
	UINT8   *u8DataWritten
)
{
	SINT32 u32RetVal = SUCCESS;
	DM8127_I2C_REGS	stI2cRegs = NULL;
	UINT16  u16Status = 0;
	UINT8	u8BytesWritten = 0;
	UINT8*  pu8DataPtr = u8Buffer;
	UINT32	u32TimeOut = DM8127_I2C_TIMEOUT;
	UINT8 count=1;

	if ((NULL == pu8DataPtr) ||
		(0 == u8BufLen))
		{
		u32RetVal = 0;
		return (u32RetVal);
		}

	/* Assign the I2C register base */
	switch (u8BusNum)
	{
		case 0:
			stI2cRegs = (DM8127_I2C_REGS) I2C0_BASE;
			break;
		case 1:
			stI2cRegs = (DM8127_I2C_REGS) I2C1_BASE;
			break;
		case 2:
			stI2cRegs = (DM8127_I2C_REGS) I2C2_BASE;
			break;
		case 3:
			stI2cRegs = (DM8127_I2C_REGS) I2C3_BASE;
			break;
		default:
			stI2cRegs = (DM8127_I2C_REGS) NULL;
			platform_write ("Invalid I2C bus number \r\n");
			return FAILED;
	}

	/* just to ensure the previous transactions flags are cleared */
	stI2cRegs->I2C_STAT = 0xFFFF;

	pu8DataPtr = u8Buffer;
	//platform_write("buffer data=%x %x\n",pu8DataPtr[0],pu8DataPtr[1]);
	//platform_write("u8Buffer address 0x%x \n",u8Buffer);


	/*  set the slave address */
	stI2cRegs->I2C_SA = u16SlaveAddr & I2C_SA_MASK;

	/* set the count */
	stI2cRegs->I2C_CNT = u8BufLen;

	/* Poll for the bus to become free/idle */
	for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
	{
		if ((stI2cRegs->I2C_STAT & I2C_STAT_BB) == 0)
			break;
	}
#if 0
	if (u32TimeOut == DM8127_I2C_TIMEOUT)
	{
		u32RetVal = FAILED;
	}
#endif
	if (SUCCESS == u32RetVal)
	{
		/* configure the I2C bus as master for receiving mode */
		stI2cRegs->I2C_CON = 0	\
							| I2C_CON_EN    // I2C Enable
							| I2C_CON_MST       // Master Mode
							| I2C_CON_TX        // TRansmit Mode
							| I2C_CON_STP       // Stop
							| I2C_CON_STT       // Start
							;
	}

	/* Loop till we have written all the data or we have timed-out */
	for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
	{
		u16Status = stI2cRegs->I2C_STAT;

		/* Check for NACK*/
		if ((u16Status & I2C_STAT_NACK) == 0)
		{
			/*  ack received. Now check for data ready */
			if ((u16Status & I2C_STAT_ARDY) == 0)
			{
				/* check for XRDY for data availability */
				if ((u16Status & I2C_STAT_XRDY) == I2C_STAT_XRDY)
				{
					/* clear the RRDY bits */
					stI2cRegs->I2C_STAT = I2C_STAT_XRDY;

					/* check if we have buffer space avaliable */

					if (u8BytesWritten < u8BufLen)
					{
						/* Write the data and ack */
						//platform_write("pu8DataPtr address- 0x%x and pu8DataPtr data=0x%x\n",pu8DataPtr,*pu8DataPtr);
						stI2cRegs->I2C_DATA = (*pu8DataPtr++ & 0xFF);
						count++;
						u8BytesWritten++;

					}
				}
				else
				{
					/* loop through to make another attempt */
				}
			}

			if (u8BytesWritten == u8BufLen)
			{
				//delay( 10 );
				break;
			}

				/* if we have lost the arbitration */
			if ((stI2cRegs->I2C_STAT & I2C_STAT_AL) == I2C_STAT_AL)
				{
					platform_write ("DM8127I2cWite:- AL... \r\n");
					u32RetVal = FAILED;
					/* clear the AL bits */
					stI2cRegs->I2C_STAT = I2C_STAT_AL;
					break;
				}
			#if 1
			if ( (stI2cRegs->I2C_STAT & I2C_STAT_ARDY) == I2C_STAT_ARDY)
				{
				/* all the reads are completed */
				stI2cRegs->I2C_STAT = I2C_STAT_ARDY;
				break;
				}
			#endif
			if ( (stI2cRegs->I2C_STAT & I2C_STAT_NACK) == I2C_STAT_NACK)
				{
				platform_write ("DM8127I2cWite:- NACK... \r\n");
				/* all the reads are completed */
				stI2cRegs->I2C_STAT = I2C_STAT_NACK;
				break;
				}

			 delay( 10 );

		}

		else
		{
		platform_write ("DM8127I2cWite:- NACK..... \r\n");
		u32RetVal = FAILED;
		/* clear the NACK bits */
		stI2cRegs->I2C_STAT = I2C_STAT_NACK;
		break;
		}
	}

	/* before returning, update the return counts too */
	if (NULL != u8DataWritten)
		*u8DataWritten = u8BytesWritten;

	return (u32RetVal);
}

/***
 * \brief: Routine to read data from slave deice the I2C - 0
 *
 * \b \Descr: This routine initializes the I2C controller for reading from the slave
 * \n         peripheral connected to the bus. This function takes the slave address
 * \n         as a parameter along with the read buffer pointer and the length of
 * \n         buffer. This function returns the number of bytes read into the output
 * \n         len pointer.
 *
 * \param:  u8BusNum 		[IN]		I2C Bus number
 * \n       u16SlaveAddr 	[IN]		I2C Slave address to read from
 * \n       *u8Buffer		[OUT]		Buffer pointer to copy data into
 * \n       u8BufLen 		[IN]		Length of the input buffer pointer
 * \n       *u8DataRead	    [OUT]		Place holder to return read number of bytes
 *
 * \return  SUCCESS for success  - Description
 * \n       FAILED for error   - Description
 */

 STATUS	DM8127I2cRead
 (
	UINT8	u8BusNum,
	UINT16	u16SlaveAddr,
	UINT8	*u8Buffer,
	UINT8	u8BufLen,
	UINT8	*u8DataRead
 )
 {
	STATUS u32RetVal = SUCCESS;
	DM8127_I2C_REGS	stI2cRegs = INIT_VAL;
	UINT16  u16Status = 0;
	UINT8	u8BytesRead = 0;
	UINT8*  pu8DataPtr = INIT_VAL;
	UINT32	u32TimeOut = DM8127_I2C_TIMEOUT;
	
	/* input param validation */
	if ((INIT_VAL != u8Buffer) &&
		(0 != u8BufLen))
	{
		pu8DataPtr = u8Buffer;
	}
	else
	{
		u32RetVal = FAILED;
		return(u32RetVal);
	}

	switch (u8BusNum)
	{
		case aic3104_I2C_BUS_NUM_0:
			stI2cRegs = (DM8127_I2C_REGS) I2C0_BASE;
			break;
		case aic3104_I2C_BUS_NUM_1:
			stI2cRegs = (DM8127_I2C_REGS) I2C1_BASE;
			break;
		case aic3104_I2C_BUS_NUM_2:
			stI2cRegs = (DM8127_I2C_REGS) I2C2_BASE;
			break;
		case aic3104_I2C_BUS_NUM_3:
			stI2cRegs = (DM8127_I2C_REGS) I2C3_BASE;
			break;
		default:
			stI2cRegs = (DM8127_I2C_REGS) INIT_VAL;
			printf ("DM8127I2cRead: -Invalid I2C bus number \r\n");
			return FAILED;
	}
	
	/*  set the slave address */
	stI2cRegs->I2C_SA = u16SlaveAddr & I2C_SA_MASK;
	
	/* set the count */
	stI2cRegs->I2C_CNT = u8BufLen;
	
	/* Poll for the bus to become free/idle */
	for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
	{
		if ((stI2cRegs->I2C_STAT & I2C_STAT_BB) == 0)
			break;
	}
	
	if (u32TimeOut == DM8127_I2C_TIMEOUT)
		u32RetVal = FAILED;	
	
	if (SUCCESS == u32RetVal)
	{
		/* configure the I2C bus as master for receiving mode */
		stI2cRegs->I2C_CON = 0	\
							| I2C_CON_EN    // I2C Enable
							| I2C_CON_MST       // Master Mode
							| I2C_CON_RX        // Receive Mode
							| I2C_CON_STP       // Stop
							| I2C_CON_STT       // Start
							;							
	}
	
	/* in a loop till we have read all the data or we have timed-out,
     * read the data from I2C data registetr and return
	 */
	for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
	{
		u16Status = stI2cRegs->I2C_STAT;
		
		/* Check for NACK*/
		if ((u16Status & I2C_STAT_NACK) == 0)
		{
			/*  ack received. Now check for data ready */
			if ((u16Status & I2C_STAT_ARDY) == 0)
			{
				/* check for RRDY for data availability */
				if ((u16Status & I2C_STAT_RRDY) == I2C_STAT_RRDY)
				{
					/* check if we have buffer space avaliable */
					if (u8BytesRead < u8BufLen)
					{
						/* data is available. Read it now and ack */
						*pu8DataPtr++ = stI2cRegs->I2C_DATA & 0xFF;
						u8BytesRead++;
					}
					/* clear the RRDY bits */
					stI2cRegs->I2C_STAT = I2C_STAT_RRDY;
				}
				else
				{
					/* loop through to make another attempt */
				}
			}
				
				/* if we have lost the arbitration */
			if ((stI2cRegs->I2C_STAT & I2C_STAT_AL) == I2C_STAT_AL)
				{
					printf ("DM8127I2cRead: -AL... \r\n");
					u32RetVal = FAILED;
					/* clear the AL bits */
					stI2cRegs->I2C_STAT = I2C_STAT_AL;					
					break;
				}
			
			if ((stI2cRegs->I2C_STAT & I2C_STAT_ARDY) == I2C_STAT_ARDY)
				{
				/* all the reads are completed */
				stI2cRegs->I2C_STAT = I2C_STAT_ARDY;					
				break;
				}

			if ((stI2cRegs->I2C_STAT & I2C_STAT_NACK) == I2C_STAT_NACK)
				{
				printf ("DM8127I2cRead: -NACK... \r\n");
				u32RetVal = FAILED;
				/* all the reads are completed */
				stI2cRegs->I2C_STAT = I2C_STAT_NACK;					
				break;
				}
				delay( 1 );
				
		}
		else
		{
		printf ("DM8127I2cRead: -NACK... \r\n");
		u32RetVal = FAILED;
		/* clear the NACK bits */
		stI2cRegs->I2C_STAT = I2C_STAT_NACK;					
		break;
		}
	}
	
	/* before returning, update the return counts too */
	if (INIT_VAL != u8DataRead)
		*u8DataRead = u8BytesRead;
		
	return (u32RetVal);
 }
 /***
  * \brief: Routine to write data from slave deice the I2C - 0
  *
  * \b \Desc: This routine initializes the I2C controller for writing to the slave
  * \n        peripheral connected to the bus. This function takes the slave address
  * \n        as a parameter along with the write buffer pointer and the length of buffer.
  * \n        This function returns the number of bytes writen into the output len pointer.
  *
  * \param:   u8BusNum 		 [IN]		I2C Bus number
  * \n        u16SlaveAddr 	 [IN]		I2C Slave address to read from
  * \n        *u8Buffer		 [OUT]		Buffer pointer to copy data into
  * \n        u8BufLen 		 [IN]		Length of the input buffer pointer
  * \n        *u8DataWritten [OUT]		Place holder to return read number of bytes
  *
  * \return  SUCCESS for success  - Description
  *	\n		 FAILED for error   - Description
  */
STATUS DM8127I2cWite
(
	UINT8 	u8BusNum,
	UINT16 	u16SlaveAddr,
	UINT8	*u8Buffer,
	UINT8	u8BufLen,
	UINT8   *u8DataWritten
)
{
	STATUS u32RetVal ;
	DM8127_I2C_REGS	stI2cRegs = INIT_VAL;
	UINT16  u16Status = 0;
	UINT8	u8BytesWritten = 0;
	UINT8*  pu8DataPtr = u8Buffer;
	UINT32	u32TimeOut = DM8127_I2C_TIMEOUT;
	
	u32RetVal = FAILED;

	if ((INIT_VAL == pu8DataPtr) ||(0 == u8BufLen))
	{
		u32RetVal = 0;
		return (u32RetVal);
	}
		
	/* Assign the I2C register based on the BUS number */
	switch (u8BusNum)
	{
		case aic3104_I2C_BUS_NUM_0:
			stI2cRegs = (DM8127_I2C_REGS) I2C0_BASE;
			break;
		case aic3104_I2C_BUS_NUM_1:
			stI2cRegs = (DM8127_I2C_REGS) I2C1_BASE;
			break;
		case aic3104_I2C_BUS_NUM_2:
			stI2cRegs = (DM8127_I2C_REGS) I2C2_BASE;
			break;
		case aic3104_I2C_BUS_NUM_3:
			stI2cRegs = (DM8127_I2C_REGS) I2C3_BASE;
			break;
		default:
			stI2cRegs = (DM8127_I2C_REGS) INIT_VAL;
			printf ("Invalid I2C bus number \r\n");
			return FAILED;
	}
	
	/* just to ensure the previous transactions flags are cleared */
	stI2cRegs->I2C_STAT = 0xFFFF;

	pu8DataPtr = u8Buffer;
	
	/*  set the slave address */
	stI2cRegs->I2C_SA = u16SlaveAddr & I2C_SA_MASK;
	
	/* set the count */
	stI2cRegs->I2C_CNT = u8BufLen;

#if 0
	/* Poll for the bus to become free/idle */
	for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
	{
		if ((stI2cRegs->I2C_STAT & I2C_STAT_BB) == 0)
			break;
	}
#endif

	u32TimeOut = 0;
	/* Poll for the bus to become free/idle */
	do
	{
		u32TimeOut ++;

	}while(((stI2cRegs->I2C_STAT & I2C_STAT_BB) != 0) && (u32TimeOut++ != DM8127_I2C_TIMEOUT));

	if (u32TimeOut != DM8127_I2C_TIMEOUT)
		u32RetVal = SUCCESS;
		
	if (SUCCESS == u32RetVal)
	{
		/* configure the I2C bus as master for receiving mode */
		stI2cRegs->I2C_CON = 0	\
							| I2C_CON_EN        // I2C Enable
							| I2C_CON_MST       // Master Mode
							| I2C_CON_TX        // TRansmit Mode
							| I2C_CON_STP       // Stop
							| I2C_CON_STT       // Start
							;							
	}
	
	/* Loop till we have written all the data or we have timed-out */
	for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
	{
		u16Status = stI2cRegs->I2C_STAT;
		
		/* Check for NACK*/
		if ((u16Status & I2C_STAT_NACK) == 0)
		{
			/*  ack received. Now check for data ready */
			if ((u16Status & I2C_STAT_ARDY) == 0)
			{
				/* check for XRDY for data availability */
				if ((u16Status & I2C_STAT_XRDY) == I2C_STAT_XRDY)
				{
					/* clear the RRDY bits */
					stI2cRegs->I2C_STAT = I2C_STAT_XRDY;
					
					/* check if we have buffer space avaliable */
					if (u8BytesWritten < u8BufLen)
					{
						/* Write the data and ack */
						stI2cRegs->I2C_DATA = (*pu8DataPtr++ & 0xFF);
						u8BytesWritten++;
					}
				}
				else
				{
					/* loop through to make another attempt */
				}
			}
			
			if (u8BytesWritten == u8BufLen)
				delay( 10 );
				
				
				/* if we have lost the arbitration */
			if ((stI2cRegs->I2C_STAT & I2C_STAT_AL) == I2C_STAT_AL)
				{
					printf ("DM8127I2cWite:- AL... \r\n");
					u32RetVal = FAILED;
					/* clear the AL bits */
					stI2cRegs->I2C_STAT = I2C_STAT_AL;					
					break;
				}
			
			if ( (stI2cRegs->I2C_STAT & I2C_STAT_ARDY) == I2C_STAT_ARDY)
				{
				/* all the reads are completed */
				stI2cRegs->I2C_STAT = I2C_STAT_ARDY;					
				break;
				}

			if ( (stI2cRegs->I2C_STAT & I2C_STAT_NACK) == I2C_STAT_NACK)
				{
				printf ("DM8127I2cWite:- NACK... \r\n");
				/* all the reads are completed */
				stI2cRegs->I2C_STAT = I2C_STAT_NACK;					
				break;
				}
				
			delay( 10 );

		}
		else
		{
		printf ("DM8127I2cWite:- NACK..... \r\n");
		u32RetVal = FAILED;
		/* clear the NACK bits */
		stI2cRegs->I2C_STAT = I2C_STAT_NACK;					
		break;
		}
	}
	
	/* before returning, update the return counts too */
	if (INIT_VAL != u8DataWritten)
		*u8DataWritten = u8BytesWritten;

	return (u32RetVal);
}

/***
 * \brief: Routine to Probe slave device on the I2C Bus
 *
 * \b \Desc: This routine tries to write a byte to the slave device and looks for
 * \n        NACk. If there is no NACK, it assumes the device is present.
 *
 * \param:   u8BusNum 		[IN]		I2C Bus number
 * \n        u16SlaveAddr 	[IN]		I2C Slave address to read from
 *
 * \return:  SUCCESS for success  - Description
 * \n        FAILED for error   - Description
 */
STATUS DM8127I2cProbe
(
	UINT8 	u8BusNum,
	UINT16 	u16SlaveAddr
)
{
	STATUS u32RetVal = SUCCESS;
	DM8127_I2C_REGS	stI2cRegs = INIT_VAL;
	UINT16  u16Status = 0;
	UINT8	u8BytesWritten = 0;
	UINT32	u32TimeOut = DM8127_I2C_TIMEOUT;

	switch (u8BusNum)
	{
		case aic3104_I2C_BUS_NUM_0:
			stI2cRegs = (DM8127_I2C_REGS) I2C0_BASE;
			break;
		case aic3104_I2C_BUS_NUM_1:
			stI2cRegs = (DM8127_I2C_REGS) I2C1_BASE;
			break;
		case aic3104_I2C_BUS_NUM_2:
			stI2cRegs = (DM8127_I2C_REGS) I2C2_BASE;
			break;
		case aic3104_I2C_BUS_NUM_3:
			stI2cRegs = (DM8127_I2C_REGS) I2C3_BASE;
			break;
		default:
			stI2cRegs = (DM8127_I2C_REGS) INIT_VAL;
			printf ("Invalid I2C bus number \r\n");
			return FAILED;
	}

	/* just to ensure the previous transactions flags are cleared */
	stI2cRegs->I2C_STAT = 0xFFFF;
	
	/* Disable the Interrupts */
	stI2cRegs->I2C_IE = 0x00;

	/* Poll for the bus to become free/idle */
	for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
	{
		if ((stI2cRegs->I2C_STAT & I2C_STAT_BB) == 0)
			break;
	}
	
	if (u32TimeOut == DM8127_I2C_TIMEOUT)
	{
		printf ("Bus is busy.\r\n");
		u32RetVal = FAILED;
		return (u32RetVal);
	}


	/* set the count */
	stI2cRegs->I2C_CNT = 1;

	/*  set the slave address */
	stI2cRegs->I2C_SA = u16SlaveAddr & I2C_SA_MASK;
		
	if (SUCCESS == u32RetVal)
	{
		/* configure the I2C bus as master for receiving mode */
		stI2cRegs->I2C_CON = 0	\
							| I2C_CON_EN    // I2C Enable
							| I2C_CON_MST       // Master Mode
							| I2C_CON_STP       // Stop
							| I2C_CON_STT       // Start
							| I2C_CON_RX        // Receive Mode							
							;							
	}
	
	u32RetVal = FAILED;

	/* have a large enough delay for client device to respond */
	delay (2 * DM8127_I2C_TIMEOUT);
	
	/* check the status to see if we succeeded */
	u16Status = stI2cRegs->I2C_STAT;
	
	if (I2C_STAT_NACK == (u16Status & I2C_STAT_NACK))
	{
		u32RetVal = FAILED;
		/* clear the status bits */
		stI2cRegs->I2C_STAT = 0xFFFF;
		/* configure the I2C bus as master for receiving mode */
		stI2cRegs->I2C_CON |= I2C_CON_STP;       // Stop		

		delay (1000);
		/* Poll for the bus to become free/idle */
		for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
		{
			if ((stI2cRegs->I2C_STAT & I2C_STAT_BB) == 0)
				break;
		}		
	}
	else
	{
		/* We got the ACK from the device. So clear the I2C status */
		for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
		{
			u16Status = stI2cRegs->I2C_STAT;
			
			if(I2C_STAT_RRDY == (u16Status & I2C_STAT_RRDY))
			{
				u32RetVal = SUCCESS;
				u8BytesWritten = stI2cRegs->I2C_DATA;
				stI2cRegs->I2C_STAT = I2C_STAT_RRDY;
				delay (1000);
				break;
			}
			else
				break;
		}
	}
	
	/* clear the status bits */
	stI2cRegs->I2C_STAT = 0xFFFF;
	/* configure the I2C bus as master for receiving mode */
	stI2cRegs->I2C_CON |= I2C_CON_STP;       // Stop
	
	delay (10);
	
	/* to avoide the compiler warning */
	u8BytesWritten = u8BytesWritten ;
	
	return (u32RetVal);
}


/***
 * \brief: Routine to write data to slave deice siI9135 through I2C - 2
 *
 * \b \Descr: This routine initializes the I2C controller for writing to the slave
 * \n         peripheral connected to the bus. This function takes the slave address
 * \n         as a parameter along with the write buffer pointer and the length of
 * \n         buffer.This function returns the number of bytes writen into the output
 * \n         len pointer.
 *
 * \param:  u8BusNum 		 [IN]		I2C Bus number
 * \n       u16SlaveAddr 	 [IN]		I2C Slave address to read from
 * \n       *u8Buffer		 [OUT]		Buffer pointer to copy data into
 * \n       u8BufLen 		 [IN]		Length of the input buffer pointer
 * \n       *u8DataWritten [OUT]		Place holder to return read number of bytes
 *
 * \return:  SUCCESS for success
 * \n        FAILED for error
 */
STATUS siI9135I2cWite 
(
	UINT8 	u8BusNum,
	UINT16 	u16SlaveAddr,
	UINT8	*u8Buffer,
	UINT8	u8BufLen,
	UINT8   *u8DataWritten
)
{
	STATUS u32RetVal = SUCCESS;
	DM8127_I2C_REGS	stI2cRegs = INIT_VAL;
	UINT16  u16Status = 0;
	UINT8	u8BytesWritten = 0;
	UINT8*  pu8DataPtr = u8Buffer;
	UINT32	u32TimeOut = DM8127_I2C_TIMEOUT;
	
	if ((INIT_VAL == pu8DataPtr) ||
		(0 == u8BufLen))
		{
		u32RetVal = 0;
		return (u32RetVal);
		}
		
	/* Assign the I2C register base */
	switch (u8BusNum)
	{
		case aic3104_I2C_BUS_NUM_0:
			stI2cRegs = (DM8127_I2C_REGS) I2C0_BASE;
			break;
		case aic3104_I2C_BUS_NUM_1:
			stI2cRegs = (DM8127_I2C_REGS) I2C1_BASE;
			break;
		case aic3104_I2C_BUS_NUM_2:
			stI2cRegs = (DM8127_I2C_REGS) I2C2_BASE;
			break;
		case aic3104_I2C_BUS_NUM_3:
			stI2cRegs = (DM8127_I2C_REGS) I2C3_BASE;
			break;
		default:
			stI2cRegs = (DM8127_I2C_REGS) INIT_VAL;
			printf ("Invalid I2C bus number \r\n");
			return FAILED;
	}
	
	/* just to ensure the previous transactions flags are cleared */
	stI2cRegs->I2C_STAT = 0xFFFF;

	pu8DataPtr = u8Buffer;
	
	/*  set the slave address */
	stI2cRegs->I2C_SA = u16SlaveAddr & I2C_SA_MASK;
	
	/* set the count */
	stI2cRegs->I2C_CNT = u8BufLen;

	/* Poll for the bus to become free/idle */
	for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
	{
		if ((stI2cRegs->I2C_STAT & I2C_STAT_BB) == 0)
			break;
	}
	
	if (u32TimeOut == DM8127_I2C_TIMEOUT)
		u32RetVal = FAILED;
		
	if (SUCCESS == u32RetVal)
	{
		/* configure the I2C bus as master for receiving mode */
		stI2cRegs->I2C_CON = 0	\
							| I2C_CON_EN    // I2C Enable
							| I2C_CON_MST       // Master Mode
							| I2C_CON_TX        // TRansmit Mode
							| I2C_CON_STT       // Start
							;							
	}
	
	/* Loop till we have written all the data or we have timed-out */
	for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
	{
		u16Status = stI2cRegs->I2C_STAT;
		
		/* Check for NACK*/
		if ((u16Status & I2C_STAT_NACK) == 0)
		{
			/*  ack received. Now check for data ready */
			if ((u16Status & I2C_STAT_ARDY) == 0)
			{
				/* check for XRDY for data availability */
				if ((u16Status & I2C_STAT_XRDY) == I2C_STAT_XRDY)
				{
					/* clear the RRDY bits */
					stI2cRegs->I2C_STAT = I2C_STAT_XRDY;
					
					/* check if we have buffer space avaliable */
					if (u8BytesWritten < u8BufLen)
					{
						/* Write the data and ack */
						stI2cRegs->I2C_DATA = (*pu8DataPtr++ & 0xFF);
						u8BytesWritten++;
					}
				}
				else
				{
					/* loop through to make another attempt */
				}
			}
			
			if (u8BytesWritten == u8BufLen)
				delay( 10 );
				
				
				/* if we have lost the arbitration */
			if ((stI2cRegs->I2C_STAT & I2C_STAT_AL) == I2C_STAT_AL)
				{
					printf ("DM8127I2cWite:- AL... \r\n");
					u32RetVal = FAILED;
					/* clear the AL bits */
					stI2cRegs->I2C_STAT = I2C_STAT_AL;					
					break;
				}
			
			if ( (stI2cRegs->I2C_STAT & I2C_STAT_ARDY) == I2C_STAT_ARDY)
				{
				/* all the reads are completed */
				stI2cRegs->I2C_STAT = I2C_STAT_ARDY;					
				break;
				}

			if ( (stI2cRegs->I2C_STAT & I2C_STAT_NACK) == I2C_STAT_NACK)
				{
				printf ("DM8127I2cWite:- NACK... \r\n");
				/* all the reads are completed */
				stI2cRegs->I2C_STAT = I2C_STAT_NACK;					
				break;
				}
				
			delay( 10 );

		}
		else
		{
		printf ("DM8127I2cWite:- NACK..... \r\n");
		u32RetVal = FAILED;
		/* clear the NACK bits */
		stI2cRegs->I2C_STAT = I2C_STAT_NACK;					
		break;
		}
	}
	
	/* before returning, update the return counts too */
	if (INIT_VAL != u8DataWritten)
		*u8DataWritten = u8BytesWritten;

	return (u32RetVal);
}

/***
 * \brief:  Routine to read data from slave deice siI9135 using I2C - 2
 *
 * \b \Descr: This routine initializes the I2C controller for reading from
 * \n         the slave peripheral connected to the bus. This function takes
 * \n        the slave address as a parameter along with the read buffer
 * \n        pointer and the length of buffer. This function returns the
 * \n        number of bytes read into the output len pointer.
 *
 * \param   u8BusNum 		[IN]		I2C Bus number
 * \n       u16SlaveAddr 	[IN]		I2C Slave address to read from
 * \n       *u8Buffer		[OUT]		Buffer pointer to copy data into
 * \n       u8BufLen 		[IN]		Length of the input buffer pointer
 * \n       *u8DataRead	    [OUT]		Place holder to return read number of bytes
 *
 * \return: SUCCESS for success
 * \n       FAILED for error
 */

 STATUS	siI9135I2cRead 
 (
	UINT8	u8BusNum,
	UINT16	u16SlaveAddr,
	UINT8	*u8Buffer,
	UINT8	u8BufLen,
	UINT8	*u8DataRead
 )
 {
	STATUS u32RetVal = SUCCESS;
	DM8127_I2C_REGS	stI2cRegs = INIT_VAL;
	UINT16  u16Status = 0;
	UINT8	u8BytesRead = 0;
	UINT8*  pu8DataPtr = INIT_VAL;
	UINT32	u32TimeOut = DM8127_I2C_TIMEOUT;
	
	/* input param validation */
	if ((INIT_VAL != u8Buffer) &&
		(0 != u8BufLen))
	{
		pu8DataPtr = u8Buffer;
	}
	else
	{
		u32RetVal = FAILED;
		return(u32RetVal);
	}

	switch (u8BusNum)
	{
		case aic3104_I2C_BUS_NUM_0:
			stI2cRegs = (DM8127_I2C_REGS) I2C0_BASE;
			break;
		case aic3104_I2C_BUS_NUM_1:
			stI2cRegs = (DM8127_I2C_REGS) I2C1_BASE;
			break;
		case aic3104_I2C_BUS_NUM_2:
			stI2cRegs = (DM8127_I2C_REGS) I2C2_BASE;
			break;
		case aic3104_I2C_BUS_NUM_3:
			stI2cRegs = (DM8127_I2C_REGS) I2C3_BASE;
			break;
		default:
			stI2cRegs = (DM8127_I2C_REGS) INIT_VAL;
			printf ("DM8127I2cRead: -Invalid I2C bus number \r\n");
			return FAILED;
	}
	
	/*  set the slave address */
	stI2cRegs->I2C_SA = u16SlaveAddr & I2C_SA_MASK;
	
	/* set the count */
	stI2cRegs->I2C_CNT = u8BufLen;
	
	/* Poll for the bus to become free/idle */
	for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
	{
		if ((stI2cRegs->I2C_STAT & I2C_STAT_BB) == 0)
			break;
	}

	if (SUCCESS == u32RetVal)
	{
		/* configure the I2C bus as master for receiving mode */
		stI2cRegs->I2C_CON = 0	\
							| I2C_CON_EN    // I2C Enable
							| I2C_CON_MST       // Master Mode
							| I2C_CON_RX        // Receive Mode
							| I2C_CON_STP       // Stop
							| I2C_CON_STT       // Start
							;							
	}
	
	/* in a loop till we have read all the data or we have timed-out,
     * read the data from I2C data registetr and return
	 */
	for (u32TimeOut = 0; u32TimeOut < DM8127_I2C_TIMEOUT; u32TimeOut++)
	{
		u16Status = stI2cRegs->I2C_STAT;
		
		/* Check for NACK*/
		if ((u16Status & I2C_STAT_NACK) == 0)
		{
			/*  ack received. Now check for data ready */
			if ((u16Status & I2C_STAT_ARDY) == 0)
			{
				/* check for RRDY for data availability */
				if ((u16Status & I2C_STAT_RRDY) == I2C_STAT_RRDY)
				{
					/* check if we have buffer space avaliable */
					if (u8BytesRead < u8BufLen)
					{
						/* data is available. Read it now and ack */
						*pu8DataPtr++ = stI2cRegs->I2C_DATA & 0xFF;
						u8BytesRead++;
					}
					/* clear the RRDY bits */
					stI2cRegs->I2C_STAT = I2C_STAT_RRDY;
				}
				else
				{
					/* loop through to make another attempt */
				}
			}
				
				/* if we have lost the arbitration */
			if ((stI2cRegs->I2C_STAT & I2C_STAT_AL) == I2C_STAT_AL)
				{
					printf ("DM8127I2cRead: -AL... \r\n");
					u32RetVal = FAILED;
					/* clear the AL bits */
					stI2cRegs->I2C_STAT = I2C_STAT_AL;					
					break;
				}
			
			if ((stI2cRegs->I2C_STAT & I2C_STAT_ARDY) == I2C_STAT_ARDY)
				{
				/* all the reads are completed */
				stI2cRegs->I2C_STAT = I2C_STAT_ARDY;					
				break;
				}

			if ((stI2cRegs->I2C_STAT & I2C_STAT_NACK) == I2C_STAT_NACK)
				{
				printf ("DM8127I2cRead: -NACK... \r\n");
				u32RetVal = FAILED;
				/* all the reads are completed */
				stI2cRegs->I2C_STAT = I2C_STAT_NACK;					
				break;
				}
				delay( 1 );
				
		}
		else
		{
		printf ("DM8127I2cRead: -NACK... \r\n");
		u32RetVal = FAILED;
		/* clear the NACK bits */
		stI2cRegs->I2C_STAT = I2C_STAT_NACK;					
		break;
		}
	}
	
	/* before returning, update the return counts too */
	if (INIT_VAL != u8DataRead)
		*u8DataRead = u8BytesRead;
		
	return (u32RetVal);
 }
