/**
 * \file   plat_i2c.c
 *
 * \brief  
 *
 * 
*/

/*
 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
 */

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */
//#include "plat_i2c.h"
#include "plat_i2c.h"
#include "hsi2c.h"
#include "hw/hw_types.h"
#include "hw/soc_AM335x.h"
#include "armv7a/am335x/interrupt.h"
#include "armv7a/am335x/evmAM335x.h"
#include "hw/hw_control_AM335x.h"
#include "hw_cm_per.h"
#include "hw_cm_wkup.h"


/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */
#define I2C_INSTANCE_COUNT	2
/* ========================================================================== */
/*                         Structures and Enums                               */
/* ========================================================================== */

/* ========================================================================== */
/*                 Internal Function Declarations                             */
/* ========================================================================== */ 

/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */
volatile static unsigned int i2cInitCount[I2C_INSTANCE_COUNT] = {0};
extern unsigned char am335x_board_type;
volatile static unsigned short i2cDelayVal = I2C_DELAY_CYCLES;
volatile I2CDELAY_FN i2cDelayFn  = NULL;
/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */


void I2CSetDelayFn(I2CDELAY_FN fn)
{
    i2cDelayFn = fn;
	if(fn)
		i2cDelayVal = I2C_DELAY_MILLI_SEC;
	else
		i2cDelayVal = I2C_DELAY_CYCLES;
}

void I2CPowerup(unsigned char i2c_instance)
{
	if(I2_INSTANCE_1 == i2c_instance )
	{
		HWREG( SOC_PRCM_REGS + CM_PER_I2C1_CLKCTRL)      |= 0x2; 		// I2C1
	}
	else if(I2_INSTANCE_0 == i2c_instance )
	{
		HWREG( SOC_PRCM_REGS + CM_PER_SPI0_CLKCTRL)      |= 0x2; 		// I2C0
	}
}

void SetupI2CTransmitMan(unsigned char i2c_instance,unsigned char data,unsigned char output)
{
    unsigned long i2c_base_addr = 0;
    /* Enable the clock for I2C1 */
	if(I2_INSTANCE_1 == i2c_instance )
	{
        i2c_base_addr = SOC_I2C_1_REGS;       
	}
	else if(I2_INSTANCE_0 == i2c_instance )
	{
        i2c_base_addr = SOC_I2C_0_REGS;   		
	}
    else
        return;
    /* Set i2c data count register to number of data to be transmit */
    I2CSetDataCount(i2c_base_addr, 2);

    /* Clear status of all interrupts */
    CleanUpInterrupts(i2c_instance);

    /* Configure I2C controller in Master Transmitter mode */
    I2CMasterControl(i2c_base_addr, I2C_CFG_MST_TX);

    /* Transmit interrupt is enabled */
    I2CMasterIntEnableEx(i2c_base_addr, I2C_INT_TRANSMIT_READY);

    /* Generate Start Condition over I2C bus */
    I2CMasterDataPut(i2c_base_addr, data);
    I2CMasterDataPut(i2c_base_addr, output);
    I2CMasterStart(i2c_base_addr);
}

/* Clear status of all interrupts */
void CleanUpInterrupts(unsigned char i2c_instance)
{
    unsigned long i2c_base_addr = 0;
    /* Enable the clock for I2C1 */
	if(I2_INSTANCE_1 == i2c_instance )
	{
        i2c_base_addr = SOC_I2C_1_REGS;       
	}
	else if(I2_INSTANCE_0 == i2c_instance )
	{
        i2c_base_addr = SOC_I2C_0_REGS;   		
	}
    else
        return;
    I2CMasterIntEnableEx(i2c_base_addr, 0x7FF);
    I2CMasterIntClearEx(i2c_base_addr,  0x7FF);
    I2CMasterIntDisableEx(i2c_base_addr, 0x7FF);
}


#if 0
/*
**  Obsolate function 
 */
void SetupI2C(unsigned char i2c_instance,unsigned int slaveAdd)
{
    unsigned long i2c_base_addr = 0;
    /* Enable the clock for I2C1 */
	if(I2_INSTANCE_1 == i2c_instance )
	{
	    I2C1ModuleClkConfig();		
        i2c_base_addr = SOC_I2C_1_REGS;       
	}
	else if(I2_INSTANCE_0 == i2c_instance )
	{
		I2C0ModuleClkConfig();	
        i2c_base_addr = SOC_I2C_0_REGS;   		
	}
    else
        return;    
	I2CPinMuxSetup(i2c_instance);

    /* Put i2c in reset/disabled state */
    I2CMasterDisable(i2c_base_addr);

    /* Disable auto Idle functionality */
    I2CAutoIdleDisable(i2c_base_addr);

    /* Configure i2c bus speed to 100khz */
    I2CMasterInitExpClk(i2c_base_addr, 48000000, 12000000, 100000);

    /* Set i2c slave address */
    I2CMasterSlaveAddrSet(i2c_base_addr, slaveAdd);

    /* Bring I2C out of reset */
    I2CMasterEnable(i2c_base_addr);
}


int SetupI2CReception(unsigned char i2c_instance,unsigned char* buff,unsigned int dcount)
{
	unsigned int status = 0;
	unsigned int rCount = 0;
	unsigned int numOfBytes = 0;
    unsigned long i2c_base_addr = 0;
    
	if(I2_INSTANCE_1 == i2c_instance )
	{
        i2c_base_addr = SOC_I2C_1_REGS;       
	}
	else if(I2_INSTANCE_0 == i2c_instance )
	{
        i2c_base_addr = SOC_I2C_0_REGS;   		
	}
    else
        return -1;
        
    /* Wait untill I2C registers are ready to access */
    while(!(I2CMasterIntRawStatus(i2c_base_addr) & (I2C_INT_ADRR_READY_ACESS)));

    /* Data Count specifies the number of bytes to be received */
    I2CSetDataCount(i2c_base_addr, dcount);
	
	numOfBytes = I2CDataCountGet(i2c_base_addr);
	
	CleanUpInterrupts(i2c_instance);
	
	/* Configure I2C controller in Master Receiver mode */
    I2CMasterControl(i2c_base_addr, I2C_CFG_MST_RX);
	
    /* Receive and Stop Condition Interrupts are enabled */
    I2CMasterIntEnableEx(i2c_base_addr,  I2C_INT_RECV_READY |
                                          I2C_INT_STOP_CONDITION);	
										  
	I2CMasterStart(i2c_base_addr);									  
	while(1)
	{
		status = I2CMasterIntStatus(i2c_base_addr);
		if(status & I2C_INT_RECV_READY)
		{
			 /* Receive data from data receive register */
			buff[rCount++] = I2CMasterDataGet(i2c_base_addr);

			/* Clear receive ready interrupt status */	
			I2CMasterIntClearEx(i2c_base_addr,  I2C_INT_RECV_READY);
			
			 if(rCount == numOfBytes)
			 {
				  /* Disable the receive ready interrupt */
				  I2CMasterIntDisableEx(i2c_base_addr, I2C_INT_RECV_READY);
				  /* Generate a STOP */
				  I2CMasterStop(i2c_base_addr);
				  return 0;
				  
			 }
		}
		
		if (status & I2C_INT_STOP_CONDITION)
		{
			 /* Disable transmit data ready and receive data read interupt */
			 I2CMasterIntDisableEx(i2c_base_addr, I2C_INT_TRANSMIT_READY |
												   I2C_INT_RECV_READY     |
							   I2C_INT_STOP_CONDITION);
			 return -1;
		}		
	
	}

}



#endif

short I2CWrite(unsigned char   instance,
               unsigned short  slaveAdd,
               unsigned char   *buffer,
               unsigned char   bufLen,
               unsigned char   *dataWritten )
{
    short retVal = SUCCESS;
    unsigned short  status = 0;
    unsigned char	bytesWritten = 0;
    unsigned int	timeOut = I2C_TIMEOUT;
    unsigned int  i2c_base_addr = 0;


    if ((NULL == buffer) ||  (0 == bufLen) || (NULL == dataWritten ))
    {
       retVal = 0;
       return (retVal);
    }

    /* Assign the I2C register base */
	switch (instance)
	{
        case 0:
        	i2c_base_addr = SOC_I2C_0_REGS;
            break;
        case 1:
            i2c_base_addr = SOC_I2C_1_REGS;
            break;
        default:
            return FAIL;
    }


    /*  set the slave address */
    I2CMasterSlaveAddrSet(i2c_base_addr, slaveAdd);

    /* Configure I2C controller in Master Transmitter mode */
    I2CMasterControl(i2c_base_addr, I2C_CFG_MST_TX | I2C_CON_STP | I2C_CON_STT);

    I2CSetDataCount(i2c_base_addr, bufLen);
    
    
  	I2CDelay(i2cDelayVal);
    
    /* Loop till we have written all the data or we have timed-out */
    for (timeOut = 0; timeOut < I2C_TIMEOUT; timeOut++)
    {

        status = HWREG(i2c_base_addr + I2C_IRQSTATUS_RAW);

        /* Check for NACK*/
        if (0 == (status & I2C_IRQSTATUS_RAW_NACK))
        {
            /*  ACK received. Now check for data ready */
        	if (I2C_IRQSTATUS_RAW_AL_LOST !=
        	                (status & I2C_IRQSTATUS_RAW_AL))
        	{
        	    /* check for XRDY for data availability */
        	    if (I2C_IRQSTATUS_RAW_XRDY ==(status & I2C_IRQSTATUS_RAW_XRDY))
        	    {

        			/* Write the data and ACK */
        			HWREG(i2c_base_addr + I2C_DATA) =
        					(*buffer++ & I2C_DATA_DATA);
        			bytesWritten++;

        			/* clear the XRDY bits */
		            HWREG(i2c_base_addr + I2C_IRQSTATUS_RAW) |= (I2C_IRQSTATUS_RAW_XRDY_CLEAR
 					                << I2C_IRQSTATUS_RAW_XRDY_SHIFT);
                    if (bytesWritten >= bufLen)
        			{
        				break;
        			}

        	    }
               	I2CDelay(i2cDelayVal);
            }
        	else
        	{
        	    retVal = FAIL;
                
        	    /* clear the AL bits */
        	    HWREG(i2c_base_addr + I2C_IRQSTATUS_RAW) |=
        	                 I2C_IRQSTATUS_RAW_AL_CLEAR;
        	    break;
        	}


        	status =  HWREG(i2c_base_addr + I2C_IRQSTATUS_RAW);

            /* if we have lost the arbitration */
            if (I2C_IRQSTATUS_RAW_AL_LOST ==
                (HWREG(i2c_base_addr + I2C_IRQSTATUS_RAW) & I2C_IRQSTATUS_RAW_AL))
            {
                retVal = FAIL;

                /* clear the AL bits */
                HWREG(i2c_base_addr + I2C_IRQSTATUS_RAW) |=
                    I2C_IRQSTATUS_RAW_AL_CLEAR;
                break;
            }

            if (I2C_IRQSTATUS_RAW_NACK == (HWREG(i2c_base_addr + I2C_IRQSTATUS_RAW)
            		& I2C_IRQSTATUS_RAW_NACK))
            {
                retVal = FAIL;
                
                /* Clear that Bit */
                HWREG(i2c_base_addr + I2C_IRQSTATUS_RAW) |=(I2C_IRQSTATUS_RAW_NACK_CLEAR
                    << I2C_IRQSTATUS_RAW_NACK_SHIFT);
                break;
            }
        }
        else
        {
            retVal = FAIL;

            /* clear the NACK bits */
            HWREG(i2c_base_addr + I2C_IRQSTATUS_RAW) = (I2C_IRQSTATUS_RAW_NACK_CLEAR
                << I2C_IRQSTATUS_RAW_NACK_SHIFT);
            break;
        }
    }
    if(timeOut >= I2C_TIMEOUT)
    {
        return FAIL;
    }

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

    return (retVal);
}

short I2CReInit( unsigned char instance)
{
    unsigned int tempVal = 0;
    short ret = 0;
    if(instance >= I2C_INSTANCE_COUNT)
        return FAIL;
        
    tempVal = i2cInitCount[instance];  
    i2cInitCount[instance] = 0;      
    ret = I2CInit(instance);
    
    if(ret != FAIL)
        i2cInitCount[instance] = tempVal+1;
    return ret;   
}

short I2CInit( unsigned char instance)
{
    short   retVal = SUCCESS;
    unsigned int  i2c_base_addr = 0;
    
    if(instance >= I2C_INSTANCE_COUNT)
        return FAIL;
    
    /* Increment the init count by one */
    i2cInitCount[instance]++;
    
    if( i2cInitCount[instance] > 1)
    {
        /* This instance is already intitalized. */
        return SUCCESS;
    }
    
   	I2CPowerup(instance);
    
	/* Assign the I2C register base */
	switch (instance)
	{
        case 0:
            I2C0ModuleClkConfig();	
            
        	i2c_base_addr = SOC_I2C_0_REGS;
            break;
        case 1:
            I2C1ModuleClkConfig();
            i2c_base_addr = SOC_I2C_1_REGS;
            break;
        default:
            return FAIL;
    }

    I2CPinMuxSetup(instance);
    if (SUCCESS == retVal)
    {
        /*Setting Clock as Required for I2C to Work*/
        //clockInit(instance);
        /* Reset all the registers */
        HWREG(i2c_base_addr + I2C_CON) = 0;
        HWREG(i2c_base_addr + I2C_PSC) = 0;
        HWREG(i2c_base_addr + I2C_SCLL)= 0;
        HWREG(i2c_base_addr + I2C_SCLH)= 0;
        HWREG(i2c_base_addr + I2C_BUF) = 0;
        HWREG(i2c_base_addr + I2C_SYSC)= 0;
        HWREG(i2c_base_addr + I2C_WE)  = 0;
        HWREG(i2c_base_addr + I2C_IRQSTATUS_RAW)= 0;
        HWREG(i2c_base_addr + I2C_SYSTEST)= 0;

        /* soft-reset the I2c Controller */
       HWREG(i2c_base_addr + I2C_SYSC)|=
           (I2C_SYSC_SRST & (I2C_SYSC_SRST_RESET <<
                   I2C_SYSC_SRST_SHIFT));

       I2CDelay(i2cDelayVal);

       /* DISABLE THE I@C MODULE LIKE HOLD RESET*/
       HWREG(i2c_base_addr + I2C_CON)|=
           (I2C_CON_I2C_EN & (I2C_CON_I2C_EN_DISABLE <<
                I2C_CON_I2C_EN_SHIFT));

       /* IDLE DISABLING AND ON CLOCKS*/
       HWREG(i2c_base_addr + I2C_SYSC) |=

          /*NO IDLE MODE*/
          (I2C_SYSC_AUTOIDLE & (I2C_SYSC_AUTOIDLE_DISABLE
                    << I2C_SYSC_AUTOIDLE_SHIFT))

          |(I2C_SYSC_CLKACTIVITY  &
               (I2C_SYSC_CLKACTIVITY_BOTH<<
                   I2C_SYSC_CLKACTIVITY_SHIFT))

          |(I2C_SYSC_IDLEMODE  &
              (I2C_SYSC_IDLEMODE_NOIDLE<<
                  I2C_SYSC_IDLEMODE_SHIFT));


        /* I2C PRESCALE settings. */
        HWREG(i2c_base_addr + I2C_PSC) = 3;

        HWREG(i2c_base_addr + I2C_SCLL) |=
            (I2C_SCLL_SCLL &
                (33 <<
                    I2C_SCLL_SCLL_SHIFT));

        HWREG(i2c_base_addr + I2C_SCLH) |=
            (I2C_SCLH_SCLH &
                (23 <<
                    I2C_SCLH_SCLH_SHIFT));

        /* Disable  & clear all the Interrupts */
        HWREG(i2c_base_addr + I2C_IRQENABLE_CLR) |= 0x6FF;

        /* Set the self address */
        HWREG(i2c_base_addr + I2C_OA) |=
            (I2C_OA_OA & 0xCC);

        /* Enable the I2C controller */
        HWREG(i2c_base_addr + I2C_CON) |= I2C_CON_I2C_EN;

        /* set the slave address */
        HWREG(i2c_base_addr + I2C_SA) = 0;

        /* Set data count */
        HWREG(i2c_base_addr + I2C_CNT) = 0;
    }
    return (retVal);
}

short I2CDeInit( unsigned char instance)
{
    if(instance >= I2C_INSTANCE_COUNT)
        return FAIL;
    
    
    if( i2cInitCount[instance] == 0)
    {
        /* This instance is already intitalized. */
        return FAIL;
    }
    /* Decrement the init count by one */
    i2cInitCount[instance]--;
    return SUCCESS;
    
}

short I2CRead
(
    unsigned char	busNum,
    unsigned short	slaveAddr,
    unsigned char	*buffer,
    unsigned char	bufLen,
    unsigned char	*pDataRead
)
{
    short retVal = SUCCESS;
    unsigned short status = 0;
    unsigned char bytesRead = 0;
    unsigned char* pDataPtr = NULL; /*Pointer to save received data*/
    unsigned int	timeOut = I2C_TIMEOUT;
    unsigned int  baseI2c = 0;
    unsigned char previousDatalength = 0;

    /* input parameter validation */
    if ((NULL != buffer) && (0 != bufLen) && (NULL != pDataRead))
    {
        pDataPtr = buffer;
    }
    else
    {
        return -1;
    }
    

    /* Assign the I2C register base */
	switch (busNum)
	{
        case 0:
        	baseI2c = SOC_I2C_0_REGS;
            break;
        case 1:
        	baseI2c = SOC_I2C_1_REGS;
            break;
        default:
            return FAIL;
    }


   // HWREG(baseI2c + I2C_CON) =(0);
    timeOut = I2C_TIMEOUT;
    while(1)
    {
        status = HWREG(baseI2c + I2C_IRQSTATUS_RAW);
        if((status & I2C_IRQSTATUS_RAW_BB) == I2C_IRQSTATUS_RAW_BB_FREE)
        {
            break;
        }
        timeOut--;
        if(timeOut == 0)
        {
            return FAIL;
        }
        I2CDelay(i2cDelayVal);
    }


    /* configure the I2C bus as master for receiving mode */
    HWREG(baseI2c + I2C_CON) =
        (I2C_CON_I2C_EN)     // I2C Enable
        | (I2C_CON_MST)        // Master Mode
        | (I2C_CON_TRX_RCV)        // Receive Mode
        | (I2C_CON_STP)        // Stop
        | (I2C_CON_STT);       // Start

    /*  set the slave address */
    HWREG(baseI2c + I2C_SA) = slaveAddr & I2C_SA_SA;

    /* set the count */
    HWREG(baseI2c + I2C_CNT) = bufLen;

    I2CDelay(i2cDelayVal);
    /* in THIS loop till we have TO read all the data or we have timed-out,
     * read the data from I2C data register and return
     */


    for (timeOut = 0; timeOut < I2C_TIMEOUT; timeOut++)
    {
        status = HWREG(baseI2c + I2C_IRQSTATUS_RAW);

        /* Check for NACK*/
        if (0 == (status & I2C_IRQSTATUS_RAW_NACK))
        {
             /* if we have lost the arbitration */
            if (I2C_IRQSTATUS_RAW_AL_LOST !=
                     (status & I2C_IRQSTATUS_RAW_AL))
            {
                /* if we have lost the arbitration */

                   /* check for RDR for Last data availability */
                    if (I2C_IRQSTATUS_RAW_RDR == (status & I2C_IRQSTATUS_RAW_RDR ))
                    {
                        previousDatalength =  (HWREG(baseI2c + I2C_BUFSTAT) &
                            I2C_BUFSTAT_RXSTAT) >> I2C_BUFSTAT_RXSTAT_SHIFT;
                        while(previousDatalength > 0)
                        {
                            /* Previous data is available. Read it now and ACK */
                            *pDataPtr = (unsigned char)(HWREG(baseI2c + I2C_DATA)) &
                                                        I2C_DATA_DATA;
                            pDataPtr++;
                            bytesRead++;
                            bufLen++;
                            previousDatalength = previousDatalength - 1;
                        }
                        /* CLEAR RDR FLAG*/
                        HWREG(baseI2c + I2C_IRQSTATUS_RAW) |= (I2C_IRQSTATUS_RAW_RDR_CLEAR
                                                   << I2C_IRQSTATUS_RAW_RDR_SHIFT);
                    }
                    /*CHECKING FOR NEW DATA */
                    else if(I2C_IRQSTATUS_RAW_RRDY == (status & I2C_IRQSTATUS_RAW_RRDY ))
                    {

                        /* check if we have buffer space available */
                        if (bytesRead < bufLen)
                        {
                            /* data is available. Read it now and ACK */
                            *pDataPtr = (unsigned char)(HWREG(baseI2c + I2C_DATA)) &
                                I2C_DATA_DATA;
                            pDataPtr++;
                            bytesRead++;
                            /* clear the RRDY bits */
                            HWREG(baseI2c + I2C_IRQSTATUS_RAW) |= (I2C_IRQSTATUS_RAW_RRDY_CLEAR
                               << I2C_IRQSTATUS_RAW_RRDY_SHIFT);
                        }
                        if(bytesRead >= bufLen)
                        {
                        	break;
                        }
                    I2CDelay(i2cDelayVal);
                    }


             }
            else
            {
                /* clear the AL bits */
                HWREG(baseI2c + I2C_IRQSTATUS_RAW) |=
                    I2C_IRQSTATUS_RAW_AL_CLEAR;
                /* configure the I2C bus as master for receiving mode */
                /* AFTER NACK STP AND STT ARE CLEARED BY HARDWARE*/

                HWREG(baseI2c + I2C_CON) =
                  (I2C_CON_I2C_EN)     // I2C Enable
                  | (I2C_CON_MST)        // Master Mode
                  | (I2C_CON_TRX_RCV << I2C_CON_TRX_SHIFT)        // Receive Mode
                  | (I2C_CON_STP)        // Stop
                  | (I2C_CON_STT);       // Start

                /*  set the slave address */
                HWREG(baseI2c + I2C_SA) = slaveAddr & I2C_SA_SA;

                /* set the count */
                HWREG(baseI2c + I2C_CNT) = bufLen;

                I2CDelay(i2cDelayVal);
                status = HWREG(baseI2c + I2C_CON);
                if((status & I2C_CON_STT) != I2C_CON_STT_STT )
                {
                    if(status & I2C_CON_STP)
                    {
                        break;
                    }
                    else
                    {
                       HWREG(baseI2c + I2C_CON) =
                             (I2C_CON_I2C_EN)     // I2C Enable
                             | (I2C_CON_MST)        // Master Mode
                             | (I2C_CON_TRX_RCV << I2C_CON_TRX_SHIFT)        // Receive Mode
                             | (I2C_CON_STP)        // Stop
                             | (I2C_CON_STT);       // Start
                    }
                }
            }
        }
        else
        {

            /* clear the NACK bits */
            HWREG(baseI2c + I2C_IRQSTATUS_RAW) |=
                (I2C_IRQSTATUS_RAW_NACK_CLEAR
                << I2C_IRQSTATUS_RAW_NACK_SHIFT);
            /* configure the I2C bus as master for receiving mode */
            /* AFTER NACK STP AND STT ARE CLEARED BY HARDWARE*/

            HWREG(baseI2c + I2C_CON) =
              (I2C_CON_I2C_EN)     // I2C Enable
              | (I2C_CON_MST)        // Master Mode
              | (I2C_CON_TRX_RCV << I2C_CON_TRX_SHIFT)        // Receive Mode
              | (I2C_CON_STP)        // Stop
              | (I2C_CON_STT);       // Start

            /*  set the slave address */
            HWREG(baseI2c + I2C_SA) = slaveAddr & I2C_SA_SA;

            /* set the count */
            HWREG(baseI2c + I2C_CNT) = bufLen;

            I2CDelay(i2cDelayVal);
            status = HWREG(baseI2c + I2C_CON);
            if((status & I2C_CON_STT) != I2C_CON_STT_STT )
            {
                if(status & I2C_CON_STP)
                {
                    break;
                }
                else
                {
                   HWREG(baseI2c + I2C_CON) =
                         (I2C_CON_I2C_EN)     // I2C Enable
                         | (I2C_CON_MST)        // Master Mode
                         | (I2C_CON_TRX_RCV << I2C_CON_TRX_SHIFT)        // Receive Mode
                         | (I2C_CON_STP)        // Stop
                         | (I2C_CON_STT);       // Start
                }
            }
        }
    }
    if(timeOut >= I2C_TIMEOUT)
    {
      return FAIL;
    }
    /* before returning, update the return counts too */
    if (NULL != pDataRead)
        *pDataRead = bytesRead;
    return (retVal);
}

void I2CDelay(unsigned int delay)
{
	volatile unsigned char delVar = 0;
        
    if(i2cDelayFn )
    {
        (*i2cDelayFn)(delay);
    }       
    else
    {
        while(delay > 0)
        {
            delVar = 0;
    	    while(delVar < 50)
    	    {
                delVar++;
    	    }
    	    delay--;
        }
    }        
}


/* -------------------------------------------------------------------------- */
/*                 Internal Function Definitions                              */
/* -------------------------------------------------------------------------- */







