/**
 * 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;
}
/*
 * *********************************************************
 * IicReadData with address added as an input parameter - Repeated Start
 * *********************************************************
 */
int IicReadData(u8 IicAddr, u8 addr, u8 *BufferPtr, u16 ByteCount)
{
	int Status;
	u8 IicOptions;
	u32 IicTimeoutCounter = 0;
	/*
	 * Set Receive Flag
	 */
	ReceiveComplete = 1;

	IicOptions = XIic_GetOptions(&IicInstance);
	XIic_SetOptions(&IicInstance, IicOptions | XII_REPEATED_START_OPTION);

	/*
	 * Start Iic Device
	 */
	Status = XIic_Start(&IicInstance);
	if (Status != XST_SUCCESS) {
#ifdef IIC_DEBUG
		xil_printf("IicReadData: 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("IicReadData: 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
	 */
	Status = XIic_MasterSend(&IicInstance, &addr, 1);
	if (Status != XST_SUCCESS) {
#ifdef IIC_DEBUG
		xil_printf("IicReadData: IIC Master Send failed with status %x\r\n", Status);
#endif
		return XST_FAILURE;
	}

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

	/*
	 * Clear Repeated Start option
	 */
	XIic_SetOptions(&IicInstance, IicOptions);

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

	return XST_SUCCESS;
}
Beispiel #4
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;
}
void TaskRun_Batt_LTC2943(void)
{
	int16_t status;
	u32 iic_option;

	/*Wait for IIC data transfer*/
	if(s_iic_status == LTC2943_TRANSFERRING)
		return;

	else if(s_iic_status == LTC2943_TRANSFERRED_DONE)
	{

		switch(s_ltc2943_state)
		{

			/*Done data write operation*/
			case LTC2943_WriteWait:
				 /*Release IIC Resource*/
				 status = EndoIicClose(BATT_LTC2943);
				 /*Set the status to transferring*/
				 s_iic_status = LTC2943_IDLE ;
				 /*Finish a write operation, and wait for next command*/
				 s_ltc2943_state = LTC2943_WaitForCommand;

				break;

			case LTC2943_WriteRepeatedStartWait:
				iic_option = XIic_GetOptions(iic_ptr);
				XIic_SetOptions(iic_ptr, iic_option &= XII_REPEATED_START_OPTION);
				/*Set the status to transferring*/
				s_iic_status = LTC2943_TRANSFERRING;
				/*Read 14 bytes of data from LTC2943_VOLTAGE_MSB_REG
				 * to LTC2943_TEMPERATURE_LSB_REG*/
				//memset(rx_buffer,0, 16);
				(void)XIic_MasterRecv(iic_ptr, rx_buffer, 24);

				/*Update the LTC2943 state*/
				s_ltc2943_state = LTC2943_ReadAdcValueWait;
				break;


			case LTC2943_ReadAdcValueWait:
				/*Finish a repeated START read*/
				status = EndoIicClose(BATT_LTC2943);
				if(status == ENDO_SUCCESS)
				{
					/*Convert raw data to voltage, current, temperature*/
					LTC2943_ConvertData(rx_buffer+8, 14);
				}
				/*Set the status to transferring*/
				s_iic_status = LTC2943_IDLE ;
				/*Finish the write-read operation, and wait for next command*/
				s_ltc2943_state = LTC2943_WaitForCommand;
				break;


			default:
				/*Error happen here*/
				s_iic_status = LTC2943_IDLE ;

				s_ltc2943_state = LTC2943_Error;
					break;
		}



	}
	else /*s_iic_status == LTC2943_IDLE*/
	{
		switch(s_ltc2943_state)
				{
					case LTC2943_Init:
						 status = EndoIicSensorInit(BATT_LTC2943, iic_ptr,
								 	 	 	 	 	 LTC2943_SendHandler,
								 	 	 	 	 	 LTC2943_RecvHandler,
								 	 	 	 	 	 LTC2943_StatusHandler);

						 if(status == ENDO_SUCCESS)
							 s_ltc2943_state = LTC2943_WaitForCommand;

						break;


					case LTC2943_WaitForCommand:
						break;

					case LTC2943_Error:
						s_ltc2943_state = LTC2943_WaitForCommand;
						break;

					default:
						break;
				}
	}


}