/**
 * Write Data to LTC2943 Sensor
 *
 * @param: buffer: pointer to the data buffer
 * 		   len: length of data byte
 *
 * @return: ENDO_SUCCESS if the data is successfully copy to IIC TX FIFO
 * 			ENDO_FAILURE: fails when IIC device is not properly initialized
 * 								or LTC2943 state is not WaitForCommand
 * Author: Phuong Pham
 * Created: 1/12/2016
******************************************************************************/
int16_t LTC2943_WriteData(u8 *buffer, u16 len)
{
	/*Check if the IIC device is properly initialized*/
	if(iic_ptr == NULL)
		return ENDO_FAILURE;

	/*Check if the state of LTC2943 is LTC2943_WaitForCommand
	 * If not return right away*/
	if(s_ltc2943_state != LTC2943_WaitForCommand)
		return ENDO_FAILURE;


	int16_t status = EndoIicOpen(BATT_LTC2943);

	if((status != ENDO_SUCCESS) && (status !=(int16_t)IIC_ALREADY_USING))
		return status;

	/*Set the status to transferring*/
	s_iic_status = LTC2943_TRANSFERRING;
	/*Update the state to WriteWait*/
	s_ltc2943_state = LTC2943_WriteWait;

	(void)XIic_MasterSend(iic_ptr, buffer, len);



	return ENDO_SUCCESS;
}
int16_t LTC2943_InitDriver(LTC2943_DataReadyHandler Callback)
{
	if(Callback != NULL)
		DataReady = Callback;

	u32 iic_instance_addr;
	u16 status = EndoIicSensorInit(BATT_LTC2943, &iic_instance_addr, LTC2943_SendHandler,
			 	 	 	 	 	 LTC2943_RecvHandler, LTC2943_StatusHandler);


	 if(status == ENDO_SUCCESS)
	 {

		 iic_ptr = (XIic *)iic_instance_addr;
		/*Write Control Register with the value FC
		* FC = LTC2943_AUTOMATIC_MODE|
		* 		LTC2943_PRESCALAR_M_4096|
		* 		LTC2943_DISABLE_ALCC_PIN*/
		u8 buffer[2] ={0x01, 0xFE};
		buffer[0] = 0x01;
		buffer[1] = 0xFE;

		/*Set the status to transferring*/
		s_iic_status = LTC2943_TRANSFERRING;


		(void)XIic_MasterSend(iic_ptr, buffer, 2);

		while(s_iic_status == LTC2943_TRANSFERRING)
			s_iic_status = LTC2943_IDLE;

		 s_ltc2943_state = LTC2943_WaitForCommand;
	 }



	return ENDO_SUCCESS;
}
/**
 * Write Data in REPEATED START mode to LTC2943 Sensor
 *
 * @param: command to write,

 *
 * @return: ENDO_SUCCESS if the data is successfully copy to IIC TX FIFO
 * 			ENDO_FAILURE: fails when IIC device is not properly initialized
 * 								or LTC2943 state is not WaitForCommand
 * Author: Phuong Pham
 * Created: 1/12/2016
******************************************************************************/
int16_t LTC2943_RepeatedStartWrite(u8 command)
{
	/*Check if the IIC device is properly initialized*/
	if(iic_ptr == NULL)
		return ENDO_FAILURE;

	/*Check for valid data length,
	 * LTC2943 has only 23 register*/
	//if((len == 0) && (len > 23))
	//	return ENDO_FAILURE;

	/*Check if the state of LTC2943 is LTC2943_WaitForCommand
	 * If not return right away*/
	if(s_ltc2943_state != LTC2943_WaitForCommand)
		return ENDO_FAILURE;

	int16_t status = EndoIicOpen(BATT_LTC2943);

	if((status != ENDO_SUCCESS) && (status !=(int16_t)IIC_ALREADY_USING))
		return status;

	/*Set the status to transferring*/
	s_iic_status = LTC2943_TRANSFERRING;
	/*Update the state to WriteWait*/
	s_ltc2943_state = LTC2943_WriteRepeatedStartWait;

	/*Read Status Register*/
	u32 option = XIic_GetOptions(iic_ptr);
	XIic_SetOptions(iic_ptr, option | XII_REPEATED_START_OPTION);
	/*Send data by copying data to IIC device*/
	(void)XIic_MasterSend(iic_ptr, command, 1);




	return ENDO_SUCCESS;
}
static int
xiic_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
{
    struct xiic_data *dev = (struct xiic_data *) i2c_adap;
    struct i2c_msg *pmsg;
    u32 options;
    int i, retries;
    u32 Status;
    u32 writeop;
	
    for (i = 0; i < num; i++)
    {
        pmsg = &msgs[i];

        if (!pmsg->len) /* If length is zero */
             continue;  /* on to the next request. */

        /*
         * This code checks up to 16 times for the
         * bus busy condition.
         */
        retries = 4;
        while((XIic_IsIicBusy(&dev->Iic) == TRUE) &&
              (retries-- != 0))
        {
            set_current_state(TASK_INTERRUPTIBLE);
            schedule_timeout(HZ/250);
        }


        /* If bus is still busy, bail */
        if (XIic_IsIicBusy(&dev->Iic) == TRUE)
        {
            printk(KERN_WARNING
                   "%s #%d: Could not talk to device 0x%2x (%d), bus always busy, trying to reset\n",
                   dev->adap.name, dev->index, pmsg->addr,
                   dev->status_intr_flag);

			/* Try stopping, reseting and starting device to clear condition
			*/
			if (XIic_Stop(&dev->Iic) != XST_SUCCESS)
			{
				/* The bus was in use.. */
				printk(KERN_WARNING
					   "%s #%d: Could not stop device. Restart from higher layer.\n",
					   dev->adap.name, dev->index);
				return -ENXIO;
			}
			else
			{
				XIic_Reset(&dev->Iic);
				if (XIic_Start(&dev->Iic) != XST_SUCCESS)
				{
					printk(KERN_ERR "%s #%d: Could not start device.\n",
						   dev->adap.name, dev->index);
					return -ENODEV;
				}

				return -ENXIO;
			}
        }

        options = 0;
        if (pmsg->flags & I2C_M_TEN)
            options |= XII_SEND_10_BIT_OPTION;
        XIic_SetOptions(&dev->Iic, options);

        if (XIic_SetAddress(&dev->Iic, XII_ADDR_TO_SEND_TYPE,
                    pmsg->addr) != XST_SUCCESS)
        {
            printk(KERN_WARNING
                   "%s #%d: Could not set address to 0x%2x.\n",
                   dev->adap.name, dev->index, pmsg->addr);
            return -EIO;
        }


        dev->transmit_intr_flag = 0xFFFFFFFF;
        dev->receive_intr_flag = 0xFFFFFFFF;
        dev->status_intr_flag = 0xFFFFFFFF;

        /* set the writeop flag to 0 so the adapter does not wait
         * at bottom of loop
         */
        writeop = 0;

		dev->Iic.Stats.TxErrors = 0;

        if (pmsg->flags & I2C_M_RD)
        {
            Status = XIic_MasterRecv(&dev->Iic, pmsg->buf, pmsg->len);
        }
        else
        {
            Status = XIic_MasterSend(&dev->Iic, pmsg->buf, pmsg->len);
        }

        if (Status != XST_SUCCESS)
        {
            printk(KERN_WARNING
                   "%s #%d: Unexpected error %d.\n",
                   dev->adap.name, dev->index, (int)Status);
            return -EIO;
        }

        /*
	 * Wait till the data is transmitted or received. If there is an error
	 * retry for 10 times.
	 */
	retries = 10;

	if(pmsg->flags & I2C_M_RD)
	{
		while((((volatile int)(dev->receive_intr_flag)) != 0) && (retries != 0))
		{
			if ( dev->Iic.Stats.TxErrors != 0)
			{
				udelay(25);
				Status = XIic_MasterRecv(&dev->Iic, pmsg->buf, pmsg->len);
				dev->Iic.Stats.TxErrors = 0;
				retries--;
			}

			/* the udelay was not working for Microblaze and this seems
			   like a better solution */	
			schedule_timeout_interruptible(1);
                }
	}
	else
	{
		while((((volatile int)(dev->transmit_intr_flag)) != 0) && (retries != 0))
		{
			if ( dev->Iic.Stats.TxErrors != 0)
			{
				udelay(25);
				Status = XIic_MasterSend(&dev->Iic, pmsg->buf, pmsg->len);
				dev->Iic.Stats.TxErrors = 0;
				retries--;
			}

			/* the udelay was not working for Microblaze and this seems
			   like a better solution */	
			schedule_timeout_interruptible(1);
		}
	}

	if(retries == 0)
	{
		printk("Unable to talk to Device\n");
		printk("Wrong Slave address or Slave device Busy\n");
	}
    }
    return num;
}
/*
 * *********************************************************
 * IicWriteData with address added as an input parameter
 * *********************************************************
 */
int IicWriteData(u8 IicAddr, u8 *BufferPtr, u16 ByteCount)
{
	int Status;
	u32 IicTimeoutCounter = 0;

	// Mark the Transmit Flag
	TransmitComplete = 1;
	IicInstance.Stats.TxErrors = 0;

	/*
	 * Start Iic Device
	 */
	Status = XIic_Start(&IicInstance);
	if (Status != XST_SUCCESS) {
#ifdef IIC_DEBUG
		xil_printf("IicWriteData: IIC Start Device Failed with status %x\r\n", Status);
#endif
		return XST_FAILURE;
	}

	/*
	 * Set Iic Address
	 */
	Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE, IicAddr);
	if (Status != XST_SUCCESS) {
#ifdef IIC_DEBUG
		xil_printf("IicWriteData: IIC Set Address Failed with status %x\r\n", Status);
#endif
		return XST_FAILURE;
	}

	/*
	 * Send the Data
	 */
	Status = XIic_MasterSend(&IicInstance, BufferPtr, ByteCount);
	if (Status != XST_SUCCESS) {
#ifdef IIC_DEBUG
		xil_printf("IicWriteData: IIC Master Send failed with status %x\r\n", Status);
#endif
		return XST_FAILURE;
	}

	/*
	 * Wait till the transmission is completed
	 */
	while(((TransmitComplete) || (XIic_IsIicBusy(&IicInstance)==TRUE)) && IicTimeoutCounter <= IIC_TIMEOUT) {
		IicTimeoutCounter++;
	}

	if (IicTimeoutCounter > IIC_TIMEOUT) {
		TransmitComplete = 0;
		XIic_Reset(&IicInstance);
		Status = XIic_Stop(&IicInstance);
#ifdef IIC_DEBUG
		xil_printf("IicWriteData: IIC Write Timeout!\r\n");
		if (Status != XST_SUCCESS) {
			xil_printf("IicWriteData: IIC stop failed with status %x\r\n", Status);
		}
#endif
		return XST_FAILURE;
	}

	/*
	 * Stop Iic Device
	 */
	Status = XIic_Stop(&IicInstance);
	if (Status != XST_SUCCESS) {
#ifdef IIC_DEBUG
		xil_printf("IicWriteData: IIC Stop failed with status %x\r\n", Status);
#endif
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}
/*
 * *********************************************************
 * IicReadData3 with address added as an input parameter - two bytes address
 * *********************************************************
 */
int IicReadData3(u8 IicAddr, u16 addr, u8 *BufferPtr, u16 ByteCount)
{
	int Status;
	u8 IicOptions;
	u32 IicTimeoutCounter = 0;

	/*
	 * Set Receive Flag
	 */
	ReceiveComplete = 1;

	/*
	 * Start Iic Device
	 */
	Status = XIic_Start(&IicInstance);
	if (Status != XST_SUCCESS) {
#ifdef IIC_DEBUG
		xil_printf("IicReadData3: IIC Start failed with status %x\r\n", Status);
#endif
		return XST_FAILURE;
	}

	/*
	 * Set Iic Address
	 */
	Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE, IicAddr);
	if (Status != XST_SUCCESS) {
#ifdef IIC_DEBUG
		xil_printf("IicReadData3: IIC Set Address failed with status %x\r\n", Status);
#endif
		return XST_FAILURE;
	}

	/*
	 * Write addr to the device
	 */
	// Mark the Transmit Flag
	TransmitComplete = 1;
	IicInstance.Stats.TxErrors = 0;

	/*
	 * Send the Data
	 */
	u8 addrReorder[2];
	u8 *addrPtr;
	addrPtr = &addr;
	addrReorder[0] = addrPtr[1];
	addrReorder[1] = addrPtr[0];
	Status = XIic_MasterSend(&IicInstance, addrReorder, 2);
	if (Status != XST_SUCCESS) {
#ifdef IIC_DEBUG
		xil_printf("IicReadData3: IIC Master Send failed with status %x\r\n", Status);
#endif
		return XST_FAILURE;
	}

	/*
	 * Wait till the transmission is completed
	 */
	while(((TransmitComplete) || (XIic_IsIicBusy(&IicInstance)==TRUE)) && IicTimeoutCounter <= IIC_TIMEOUT) {
		IicTimeoutCounter ++;
	}

	/*
	 * Handle Tx Timeout
	 */
	if (IicTimeoutCounter > IIC_TIMEOUT) {
		XIic_Reset(&IicInstance);
		Status = XIic_Stop(&IicInstance);
#ifdef IIC_DEBUG
		xil_printf("IicReadData3: IIC Write Timeout!\r\n");
		if (Status != XST_SUCCESS) {
			xil_printf("IicReadData3: IIC Stop Failed with status %x\r\n", Status);
		}
#endif
		return XST_FAILURE;
	}

	/*
	 * Receive Data
	 */
	Status = XIic_MasterRecv(&IicInstance, BufferPtr, ByteCount);
	if(Status != XST_SUCCESS) {
		if (Status != XST_SUCCESS) {
#ifdef IIC_DEBUG
			xil_printf("IicReadData3: IIC Master Recv Failed with status %x\r\n", Status);
#endif
			return XST_FAILURE;
		}
	}

	/*
	 * Wait until all the data is received
	 */
	IicTimeoutCounter = 0;
	while(((ReceiveComplete) || (XIic_IsIicBusy(&IicInstance)==TRUE)) && IicTimeoutCounter <= IIC_TIMEOUT) {
		IicTimeoutCounter ++;
	}

	/*
	 * Handle Rx Timeout
	 */
	if (IicTimeoutCounter > IIC_TIMEOUT) {
		XIic_Reset(&IicInstance);
		Status = XIic_Stop(&IicInstance);
#ifdef IIC_DEBUG
		xil_printf("IicReadData3: IIC Recv Timeout!\r\n");
		if (Status != XST_SUCCESS) {
			xil_printf("IicReadData3: IIC Stop Failed with status %x\r\n", Status);
		}
#endif
		return XST_FAILURE;
	}

	/*
	 * Stop Iic
	 */
	Status = XIic_Stop(&IicInstance);
	if (Status != XST_SUCCESS) {
#ifdef IIC_DEBUG
		xil_printf("IicReadData3: IIC Stop Failed with status %x\r\n", Status);
#endif
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}
Exemple #7
0
static int xiic_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
		     int num)
{
	struct xiic_data *dev = container_of(i2c_adap, struct xiic_data, adap);
	struct i2c_msg *pmsg;
	u32 options;
	int i, retries;
	XStatus Status;

	for (i = 0; i < num; i++) {
		pmsg = &msgs[i];

		if (!pmsg->len)	/* If length is zero */
			continue;	/* on to the next request. */

		options = 0;
		if (pmsg->flags & I2C_M_TEN)
			options |= XII_SEND_10_BIT_OPTION;
		if (i != num - 1)
			options |= XII_REPEATED_START_OPTION;
		XIic_SetOptions(&dev->Iic, options);

		if (XIic_SetAddress(&dev->Iic, XII_ADDR_TO_SEND_TYPE,
				    pmsg->addr) != XST_SUCCESS) {
			printk(KERN_WARNING
			       "%s #%d: Could not set address to 0x%2x.\n",
			       dev->adap.name, dev->index, pmsg->addr);
			return -EIO;
		}
		dev->interrupt_status = ~(XStatus) 0;
		/*
		 * The Xilinx layer does not handle bus busy conditions yet
		 * so this code retries a request up to 16 times if it
		 * receives a bus busy condition.  If and when the underlying
		 * code is enhanced, the retry code can be removed.
		 */
		retries = 16;

		init_completion(&dev->complete);

		if (pmsg->flags & I2C_M_RD) {
			while ((Status = XIic_MasterRecv(&dev->Iic,
							 pmsg->buf, pmsg->len))
			       == XST_IIC_BUS_BUSY && retries--) {
				set_current_state(TASK_INTERRUPTIBLE);
				schedule_timeout(HZ / 10);
			}
		} else {
			while ((Status = XIic_MasterSend(&dev->Iic,
							 pmsg->buf, pmsg->len))
			       == XST_IIC_BUS_BUSY && retries--) {
				printk("retry %d\n", retries);
				set_current_state(TASK_INTERRUPTIBLE);
				schedule_timeout(HZ / 10);
			}
		}
		if (Status != XST_SUCCESS) {
			printk(KERN_WARNING
			       "%s #%d: Unexpected error %d.\n",
			       dev->adap.name, dev->index, Status);
			return -EIO;
		}

		wait_for_completion(&dev->complete);

		if (dev->interrupt_status != XST_SUCCESS) {
			printk(KERN_WARNING
			       "%s #%d: Could not talk to device 0x%2x (%d).\n",
			       dev->adap.name, dev->index, pmsg->addr,
			       dev->interrupt_status);
			return -EIO;
		}
	}
	return num;
}