/**
*
* Runs a limited self-test on the driver/device. This test does a read/write
* test of the Interrupt Registers There is no loopback capabilities for the
* device such that this test does not send or receive data.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return
*		- XST_SUCCESS if no errors are found
*		- XST_FAILURE if errors are found
*
* @note		None.
*
****************************************************************************/
int XIic_SelfTest(XIic *InstancePtr)
{
	int Status = XST_SUCCESS;
	int GlobalIntrStatus;
	u32 IntrEnableStatus;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/*
	 * Store the Global Interrupt Register and the Interrupt Enable Register
	 * contents.
	 */
	GlobalIntrStatus = XIic_IsIntrGlobalEnabled(InstancePtr->BaseAddress);
	IntrEnableStatus = XIic_ReadIier(InstancePtr->BaseAddress);

	/*
	 * Reset the device so it's in a known state and the default state of
	 * the interrupt registers can be tested.
	 */
	XIic_Reset(InstancePtr);

	if (XIic_IsIntrGlobalEnabled(InstancePtr->BaseAddress)!= 0) {
		Status = XST_FAILURE;
	}

	if (XIic_ReadIier(InstancePtr->BaseAddress)!= 0) {
		Status = XST_FAILURE;
	}

	/*
	 * Test Read/Write to the Interrupt Enable register.
	 */
	XIic_WriteIier(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
	if (XIic_ReadIier(InstancePtr->BaseAddress)!= XIIC_TX_RX_INTERRUPTS) {
		Status = XST_FAILURE;
	}

	/*
	 * Reset device to remove the affects of the previous test.
	 */
	XIic_Reset(InstancePtr);

	/*
	 * Restore the Global Interrupt Register and the Interrupt Enable
	 * Register contents.
	 */
	if (GlobalIntrStatus == TRUE) {
		XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
	}
	XIic_WriteIier(InstancePtr->BaseAddress, IntrEnableStatus);

	return Status;
}
Example #2
0
/**
*
* Initializes a specific XIic instance.  The initialization entails:
*
* - Initialize the driver to allow access to the device registers and
*   initialize other subcomponents necessary for the operation of the device.
* - Default options to:
*	 - 7-bit slave addressing
*	 - Send messages as a slave device
*	 - Repeated start off
*	 - General call recognition disabled
* - Clear messageing and error statistics
*
* The XIic_Start() function must be called after this function before the device
* is ready to send and receive data on the IIC bus.
*
* Before XIic_Start() is called, the interrupt control must connect the ISR
* routine to the interrupt handler. This is done by the user, and not
* XIic_Start() to allow the user to use an interrupt controller of their choice.
*
* @param	InstancePtr is a pointer to the XIic instance to be worked on.
* @param	Config is a reference to a structure containing information
*		about a specific IIC device. This function can initialize
*		multiple instance objects with the use of multiple calls giving
*		different Config information on each call.
* @param	EffectiveAddr is the device base address in the virtual memory
*		address space. The caller is responsible for keeping the
*		address mapping from EffectiveAddr to the device physical base
*		address unchanged once this function is invoked. Unexpected
*		errors may occur if the address mapping changes after this
*		function is called. If address translation is not used, use
*		Config->BaseAddress for this parameters, passing the physical
*		address instead.
*
* @return
*		- XST_SUCCESS when successful
*		- XST_DEVICE_IS_STARTED indicates the device is started
*		(i.e. interrupts enabled and messaging is possible). Must stop
*		before re-initialization is allowed.
*
* @note		None.
*
****************************************************************************/
int XIic_CfgInitialize(XIic *InstancePtr, XIic_Config * Config,
			   u32 EffectiveAddr)
{
	/*
	 * Asserts test the validity of selected input arguments.
	 */
	Xil_AssertNonvoid(InstancePtr != NULL);

	InstancePtr->IsReady = 0;

	/*
	 * If the device is started, disallow the initialize and return a Status
	 * indicating it is started.  This allows the user to stop the device
	 * and reinitialize, but prevents a user from inadvertently
	 * initializing.
	 */
	if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
		return XST_DEVICE_IS_STARTED;
	}

	/*
	 * Set default values and configuration data, including setting the
	 * callback handlers to stubs  so the system will not crash should the
	 * application not assign its own callbacks.
	 */
	InstancePtr->IsStarted = 0;
	InstancePtr->BaseAddress = EffectiveAddr;
	InstancePtr->RecvHandler = XIic_StubHandler;
	InstancePtr->RecvBufferPtr = NULL;
	InstancePtr->SendHandler = XIic_StubHandler;
	InstancePtr->SendBufferPtr = NULL;
	InstancePtr->StatusHandler = XIic_StubStatusHandler;
	InstancePtr->Has10BitAddr = Config->Has10BitAddr;
	InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
	InstancePtr->Options = 0;
	InstancePtr->BNBOnly = FALSE;
	InstancePtr->GpOutWidth = Config->GpOutWidth;
	InstancePtr->IsDynamic = FALSE;
	InstancePtr->IsSlaveSetAckOff = FALSE;

	/*
	 * Reset the device.
	 */
	XIic_Reset(InstancePtr);

	XIic_ClearStats(InstancePtr);

	return XST_SUCCESS;
}
Example #3
0
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;
}
Example #4
0
/*
 * *********************************************************
 * 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;
}
Example #5
0
/*
 * *********************************************************
 * 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;
}
/**
*
* Runs a limited self-test on the driver/device. The self-test is destructive
* in that a reset of the device is performed in order to check the reset
* values of the registers and to get the device into a known state. There is no
* loopback capabilities for the device such that this test does not send or
* receive data.
*
* @param    InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return
*
* <pre>
*   XST_SUCCESS                         No errors found
*   XST_IIC_STAND_REG_ERROR             One or more IIC regular registers did
*                                       not zero on reset or read back
*                                       correctly based on what was written
*                                       to it
*   XST_IIC_TX_FIFO_REG_ERROR           One or more IIC parametrizable TX
*                                       FIFO registers did not zero on reset
*                                       or read back correctly based on what
*                                       was written to it
*   XST_IIC_RX_FIFO_REG_ERROR           One or more IIC parametrizable RX
*                                       FIFO registers did not zero on reset
*                                       or read back correctly based on what
*                                       was written to it
*   XST_IIC_STAND_REG_RESET_ERROR       A non parameterizable reg  value after
*                                       reset not valid
*   XST_IIC_TX_FIFO_REG_RESET_ERROR     Tx fifo, included in design, value
*                                       after reset not valid
*   XST_IIC_RX_FIFO_REG_RESET_ERROR     Rx fifo, included in design, value
*                                       after reset not valid
*   XST_IIC_TBA_REG_RESET_ERROR         10 bit addr, incl in design, value
*                                       after reset not valid
*   XST_IIC_CR_READBACK_ERROR           Read of the control register didn't
*                                       return value written
*   XST_IIC_DTR_READBACK_ERROR          Read of the data Tx reg didn't return
*                                       value written
*   XST_IIC_DRR_READBACK_ERROR          Read of the data Receive reg didn't
*                                       return value written
*   XST_IIC_ADR_READBACK_ERROR          Read of the data Tx reg didn't return
*                                       value written
*   XST_IIC_TBA_READBACK_ERROR          Read of the 10 bit addr reg didn't
*                                       return written value
* </pre>
*
* @note
*
* Only the registers that have be included into the hardware design are
* tested, such as, 10-bit vs 7-bit addressing.
*
****************************************************************************/
int XIic_SelfTest(XIic * InstancePtr)
{
	int Status = XST_SUCCESS;

	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/*
	 * Reset the device so it's in a known state and the default state of
	 * the registers can be tested
	 */
	XIic_Reset(InstancePtr);

	/*
	 * Test the standard - non parameterizable registers to ensure they are
	 * in the default state
	 */
	if ((XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET) &
	     XIo_In8(InstancePtr->BaseAddress + XIIC_SR_REG_OFFSET) &
	     XIo_In8(InstancePtr->BaseAddress + XIIC_DTR_REG_OFFSET) &
	     XIo_In8(InstancePtr->BaseAddress + XIIC_DRR_REG_OFFSET) &
	     XIo_In8(InstancePtr->BaseAddress + XIIC_ADR_REG_OFFSET)) != 0) {
		Status = XST_IIC_STAND_REG_RESET_ERROR;
	}

	if (XIo_In8(InstancePtr->BaseAddress + XIIC_TFO_REG_OFFSET) != 0) {
		Status = XST_IIC_TX_FIFO_REG_RESET_ERROR;
	}

	if ((XIo_In8(InstancePtr->BaseAddress + XIIC_RFO_REG_OFFSET) &
	     XIo_In8(InstancePtr->BaseAddress + XIIC_RFD_REG_OFFSET)) != 0) {
		Status = XST_IIC_RX_FIFO_REG_RESET_ERROR;
	}

	/*
	 * Test the 10-bit address parameterizable register only if it's supposed
	 * to be in the hardware
	 */
	if (InstancePtr->Has10BitAddr == TRUE) {
		if (XIo_In8(InstancePtr->BaseAddress + XIIC_TBA_REG_OFFSET) !=
		    0) {
			Status = XST_IIC_TBA_REG_RESET_ERROR;
		}
	}

	/*
	 * Perform register write/readback tests to verify the registers are
	 * working, test the control register by writing all 1's except the
	 * MSMS bit.
	 */
	XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET, 0x7B);
	if (XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET) != 0x7B) {
		Status = XST_IIC_CR_READBACK_ERROR;
	}

	/* Reset device to remove the affects of the previous test */

	XIic_Reset(InstancePtr);

	/* Test the data transmit register */

	XIo_Out8(InstancePtr->BaseAddress + XIIC_DTR_REG_OFFSET, 0xFF);
	if (XIo_In8(InstancePtr->BaseAddress + XIIC_DTR_REG_OFFSET) != 0xFF) {
		Status = XST_IIC_DTR_READBACK_ERROR;
	}

	/* Test the address register */

	XIo_Out8(InstancePtr->BaseAddress + XIIC_ADR_REG_OFFSET, 0xFE);
	if (XIo_In8(InstancePtr->BaseAddress + XIIC_ADR_REG_OFFSET) != 0xFE) {
		Status = XST_IIC_ADR_READBACK_ERROR;
	}

	/* Test 10-bit address register only if it's in the hardware */

	if (InstancePtr->Has10BitAddr == TRUE) {
		XIo_Out8(InstancePtr->BaseAddress + XIIC_TBA_REG_OFFSET, 0x07);
		if (XIo_In8(InstancePtr->BaseAddress + XIIC_TBA_REG_OFFSET) !=
		    0x07) {
			Status = XST_IIC_TBA_READBACK_ERROR;
		}
	}


	/* Reset the device so that it's in a known state before returning */

	XIic_Reset(InstancePtr);
	return Status;
}