Example #1
0
/**
* This function sets up the device to be a slave.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	SlaveAddr is the address of the slave we are receiving from.
*
* @return	None.
*
* @note
*	Interrupt is always enabled no matter the tranfer is interrupt-
*	driven or polled mode. Whether device will be interrupted or not
*	depends on whether the device is connected to an interrupt
*	controller and interrupt for the device is enabled.
*
****************************************************************************/
void XIicPs_SetupSlave(XIicPs *InstancePtr, u16 SlaveAddr)
{
	u32 ControlReg;
	u32 BaseAddr;

	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
	Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);

	BaseAddr = InstancePtr->Config.BaseAddress;

	ControlReg = XIicPs_In32(BaseAddr + XIICPS_CR_OFFSET);

	/*
	 * Set up master, AckEn, nea and also clear fifo.
	 */
	ControlReg |= (u32)XIICPS_CR_ACKEN_MASK | (u32)XIICPS_CR_CLR_FIFO_MASK;
	ControlReg |= (u32)XIICPS_CR_NEA_MASK;
	ControlReg &= (u32)(~XIICPS_CR_MS_MASK);

	XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
			  ControlReg);

	XIicPs_DisableAllInterrupts(BaseAddr);

	XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
			  XIICPS_ADDR_OFFSET, (u32)SlaveAddr);

	return;
}
Example #2
0
/**
* This function enables the slave monitor mode.
*
* It enables slave monitor in the control register and enables
* slave ready interrupt. It then does an address transfer to slave.
* Interrupt handler will signal the caller if slave responds to
* the address transfer.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	SlaveAddr is the address of the slave we want to contact.
*
* @return	None.
*
* @note		None.
*
****************************************************************************/
void XIicPs_EnableSlaveMonitor(XIicPs *InstancePtr, u16 SlaveAddr)
{
	u32 BaseAddr;

	Xil_AssertVoid(InstancePtr != NULL);

	BaseAddr = InstancePtr->Config.BaseAddress;

	/*
	 * Enable slave monitor mode in control register.
	 */
	XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
	XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
				XIICPS_CR_MS_MASK |
				XIICPS_CR_NEA_MASK |
				XIICPS_CR_SLVMON_MASK );

	/*
	 * Set up interrupt flag for slave monitor interrupt.
	 */
	XIicPs_EnableInterrupts(BaseAddr, XIICPS_IXR_NACK_MASK |
				XIICPS_IXR_SLV_RDY_MASK);

	/*
	 * Initialize the slave monitor register.
	 */
	XIicPs_WriteReg(BaseAddr, XIICPS_SLV_PAUSE_OFFSET, 0xF);

	/*
	 * Set the slave address to start the slave address transmission.
	 */
	XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);

	return;
}
Example #3
0
/**
* This function initiates an interrupt-driven receive in master mode.
*
* It sets the transfer size register so the slave can send data to us.
* The rest of the work is managed by interrupt handler.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	MsgPtr is the pointer to the receive buffer.
* @param	ByteCount is the number of bytes to be received.
* @param	SlaveAddr is the address of the slave we are receiving from.
*
* @return	None.
*
* @note		This receive routine is for interrupt-driven transfer only.
*
****************************************************************************/
void XIicPs_MasterRecv(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount,
		 u16 SlaveAddr)
{
	u32 BaseAddr;

	/*
	 * Assert validates the input arguments.
	 */
	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(MsgPtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
	Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);

	BaseAddr = InstancePtr->Config.BaseAddress;
	InstancePtr->RecvBufferPtr = MsgPtr;
	InstancePtr->RecvByteCount = ByteCount;
	InstancePtr->CurrByteCount = ByteCount;
	InstancePtr->SendBufferPtr = NULL;
	InstancePtr->IsSend = 0;
	InstancePtr->UpdateTxSize = 0;

	if ((ByteCount > XIICPS_DATA_INTR_DEPTH) ||
		(InstancePtr->IsRepeatedStart))
	{
		XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
				XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
						XIICPS_CR_HOLD_MASK);
	}

	/*
	 * Initialize for a master receiving role.
	 */
	XIicPs_SetupMaster(InstancePtr, RECVING_ROLE);

	/*
	 * Do the address transfer to signal the slave.
	 */
	XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);

	/*
	 * Setup the transfer size register so the slave knows how much
	 * to send to us.
	 */
	if (ByteCount > XIICPS_MAX_TRANSFER_SIZE) {
		XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
				XIICPS_MAX_TRANSFER_SIZE);
		InstancePtr->CurrByteCount = XIICPS_MAX_TRANSFER_SIZE;
		InstancePtr->UpdateTxSize = 1;
	}else {
		XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
			 ByteCount);
	}

	XIicPs_EnableInterrupts(BaseAddr,
		XIICPS_IXR_NACK_MASK | XIICPS_IXR_DATA_MASK |
		XIICPS_IXR_RX_OVR_MASK | XIICPS_IXR_COMP_MASK |
		XIICPS_IXR_ARB_LOST_MASK);
}
Example #4
0
/**
* This function initiates an interrupt-driven send in master mode.
*
* It tries to send the first FIFO-full of data, then lets the interrupt
* handler to handle the rest of the data if there is any.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	MsgPtr is the pointer to the send buffer.
* @param	ByteCount is the number of bytes to be sent.
* @param	SlaveAddr is the address of the slave we are sending to.
*
* @return	None.
*
* @note		This send routine is for interrupt-driven transfer only.
*
 ****************************************************************************/
void XIicPs_MasterSend(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount,
		 u16 SlaveAddr)
{
	u32 BaseAddr;
	u32 Platform = XGetPlatform_Info();

	/*
	 * Assert validates the input arguments.
	 */
	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(MsgPtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
	Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);


	BaseAddr = InstancePtr->Config.BaseAddress;
	InstancePtr->SendBufferPtr = MsgPtr;
	InstancePtr->SendByteCount = ByteCount;
	InstancePtr->RecvBufferPtr = NULL;
	InstancePtr->IsSend = 1;

	/*
	 * Set repeated start if sending more than FIFO of data.
	 */
	if (((InstancePtr->IsRepeatedStart) != 0)||
		((ByteCount > XIICPS_FIFO_DEPTH) != 0U)) {
		XIicPs_WriteReg(BaseAddr, (u32)XIICPS_CR_OFFSET,
			XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) |
				(u32)XIICPS_CR_HOLD_MASK);
	}

	/*
	 * Setup as a master sending role.
	 */
	(void)XIicPs_SetupMaster(InstancePtr, SENDING_ROLE);

	(void)TransmitFifoFill(InstancePtr);

	XIicPs_EnableInterrupts(BaseAddr,
		(u32)XIICPS_IXR_NACK_MASK | (u32)XIICPS_IXR_COMP_MASK |
		(u32)XIICPS_IXR_ARB_LOST_MASK);
	/*
	 * Do the address transfer to notify the slave.
	 */
	XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, (u32)SlaveAddr);

	/* Clear the Hold bit in ZYNQ if receive byte count is less than
	 * the FIFO depth to get the completion interrupt properly.
	 */
	if ((ByteCount < XIICPS_FIFO_DEPTH) && (Platform == (u32)XPLAT_ZYNQ))
	{
		XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
				XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) &
				(u32)(~XIICPS_CR_HOLD_MASK));
	}

}
Example #5
0
/**
* This function disables slave monitor mode.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
*
* @return	None.
*
* @note		None.
*
****************************************************************************/
void XIicPs_DisableSlaveMonitor(XIicPs *InstancePtr)
{
	u32 BaseAddr;

	Xil_AssertVoid(InstancePtr != NULL);

	BaseAddr = InstancePtr->Config.BaseAddress;

	/*
	 * Clear slave monitor control bit.
	 */
	XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
		XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET)
			& (~XIICPS_CR_SLVMON_MASK));

	/*
	 * wait for slv monitor control bit to be clear
	 */
	while (XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET)
				& XIICPS_CR_SLVMON_MASK);
	/*
	 * Clear interrupt flag for slave monitor interrupt.
	 */
	XIicPs_DisableInterrupts(BaseAddr, XIICPS_IXR_SLV_RDY_MASK);

	return;
}
Example #6
0
/**
*
* This function clears the options for the IIC device driver. The options
* control how the device behaves relative to the IIC bus. The device must be
* idle rather than busy transferring data before setting these device options.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	Options contains the specified options to be cleared. This is a
*		bit mask where a 1 means to turn the option off. One or more bit
*		values may be contained in the mask. See the bit definitions
*		named XIICPS_*_OPTION in xiicps.h.
*
* @return
*		- XST_SUCCESS if options are successfully set.
*		- XST_DEVICE_IS_STARTED if the device is currently transferring
*		data. The transfer must complete or be aborted before setting
*		options.
*
* @note		None
*
******************************************************************************/
int XIicPs_ClearOptions(XIicPs *InstancePtr, u32 Options)
{
	u32 ControlReg;
	unsigned int Index;

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

	ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
					XIICPS_CR_OFFSET);

	/*
	 * If repeated start option is cleared, set the flag.
	 * The hold bit in CR will be cleared by driver when the
	 * following transfer ends.
	 */
	if (Options & XIICPS_REP_START_OPTION) {
		InstancePtr->IsRepeatedStart = 0;
		Options = Options & (~XIICPS_REP_START_OPTION);
	}

	/*
	 * Loop through the options table and clear the specified options.
	 */
	for (Index = 0; Index < XIICPS_NUM_OPTIONS; Index++) {
 		if (Options & OptionsTable[Index].Option) {

			/*
			 * 10-bit option is specially treated, because it is
			 * using the 7-bit option, so clearing it means turning
			 * 7-bit option on.
			 */
			if (OptionsTable[Index].Option &
						XIICPS_10_BIT_ADDR_OPTION) {

				/* Turn 7-bit on */
				ControlReg |= OptionsTable[Index].Mask;
 			} else {

				/* Turn 7-bit off */
				ControlReg &= ~OptionsTable[Index].Mask;
			}
		}
	}


	/*
	 * Now write the control register. Leave it to the upper layers
	 * to restart the device.
	 */
	XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
			  ControlReg);

	/*
	 * Keep a copy of what options this instance has.
	 */
	InstancePtr->Options = XIicPs_GetOptions(InstancePtr);

	return XST_SUCCESS;
}
Example #7
0
/**
* This function initiates an interrupt-driven send in master mode.
*
* It tries to send the first FIFO-full of data, then lets the interrupt
* handler to handle the rest of the data if there is any.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	MsgPtr is the pointer to the send buffer.
* @param	ByteCount is the number of bytes to be sent.
* @param	SlaveAddr is the address of the slave we are sending to.
*
* @return	None.
*
* @note		This send routine is for interrupt-driven transfer only.
*
 ****************************************************************************/
void XIicPs_MasterSend(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount,
		 u16 SlaveAddr)
{
	u32 BaseAddr;

	/*
	 * Assert validates the input arguments.
	 */
	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(MsgPtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
	Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);


	BaseAddr = InstancePtr->Config.BaseAddress;
	InstancePtr->SendBufferPtr = MsgPtr;
	InstancePtr->SendByteCount = ByteCount;
	InstancePtr->RecvBufferPtr = NULL;
	InstancePtr->IsSend = 1;

	/*
	 * Set repeated start if sending more than FIFO of data.
	 */
	if ((InstancePtr->IsRepeatedStart) ||
		(ByteCount > XIICPS_FIFO_DEPTH)) {
		XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
			XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
				XIICPS_CR_HOLD_MASK);
	}

	/*
	 * Setup as a master sending role.
	 */
	XIicPs_SetupMaster(InstancePtr, SENDING_ROLE);

	/*
	 * Do the address transfer to notify the slave.
	 */
	XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);

	TransmitFifoFill(InstancePtr);

	XIicPs_EnableInterrupts(BaseAddr,
		XIICPS_IXR_NACK_MASK | XIICPS_IXR_COMP_MASK |
		XIICPS_IXR_ARB_LOST_MASK);
}
Example #8
0
/**
* This function perform the reset sequence to the given I2c interface by
* configuring the appropriate control bits in the I2c specifc registers
* the i2cps reset squence involves the following steps
*	Disable all the interuupts
*	Clear the status
*	Clear FIFO's and disable hold bit
*	Clear the line status
*	Update relevant config registers with reset values
*
* @param   BaseAddress of the interface
*
* @return N/A
*
* @note
* This function will not modify the slcr registers that are relavant for
* I2c controller
******************************************************************************/
void XIicPs_ResetHw(u32 BaseAddress)
{
	u32 RegVal;

	/* Disable all the interrupts */
	XIicPs_WriteReg(BaseAddress, XIICPS_IDR_OFFSET, XIICPS_IXR_ALL_INTR_MASK);
	/* Clear the interrupt status */
	RegVal = XIicPs_ReadReg(BaseAddress,XIICPS_ISR_OFFSET);
	XIicPs_WriteReg(BaseAddress, XIICPS_ISR_OFFSET, RegVal);
	/* Clear the hold bit,master enable bit and ack bit */
	RegVal = XIicPs_ReadReg(BaseAddress,XIICPS_CR_OFFSET);
	RegVal &= ~(XIICPS_CR_HOLD_MASK|XIICPS_CR_MS_MASK|XIICPS_CR_ACKEN_MASK);
	/* Clear the fifos */
	RegVal |= XIICPS_CR_CLR_FIFO_MASK;
	XIicPs_WriteReg(BaseAddress, XIICPS_CR_OFFSET, RegVal);
	/* Clear the timeout register */
	XIicPs_WriteReg(BaseAddress, XIICPS_TIME_OUT_OFFSET, 0x0);
	/* Clear the transfer size register */
	XIicPs_WriteReg(BaseAddress, XIICPS_TRANS_SIZE_OFFSET, 0x0);
	/* Clear the status register */
	RegVal = XIicPs_ReadReg(BaseAddress,XIICPS_SR_OFFSET);
	XIicPs_WriteReg(BaseAddress, XIICPS_SR_OFFSET, RegVal);
	/* Update the configuraqtion register with reset value */
	XIicPs_WriteReg(BaseAddress, XIICPS_CR_OFFSET, 0x0);
}
/**
*
* This function sets the options for the IIC device driver. The options control
* how the device behaves relative to the IIC bus. The device must be idle
* rather than busy transferring data before setting these device options.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	Options contains the specified options to be set. This is a bit
*		mask where a 1 means to turn the option on. One or more bit
*		values may be contained in the mask. See the bit definitions
*		named XIICPS_*_OPTION in xiicps.h.
*
* @return
*		- XST_SUCCESS if options are successfully set.
*		- XST_DEVICE_IS_STARTED if the device is currently transferring
*		data. The transfer must complete or be aborted before setting
*		options.
*
* @note		None.
*
******************************************************************************/
s32 XIicPs_SetOptions(XIicPs *InstancePtr, u32 Options)
{
	u32 ControlReg;
	u32 Index;
	u32 OptionsVar = Options;

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

	ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
				      XIICPS_CR_OFFSET);

	/*
	 * If repeated start option is requested, set the flag.
	 * The hold bit in CR will be written by driver when the next transfer
	 * is initiated.
	 */
	if ((OptionsVar & (u32)XIICPS_REP_START_OPTION) != (u32)0 ) {
		InstancePtr->IsRepeatedStart = 1;
		OptionsVar = OptionsVar & (~XIICPS_REP_START_OPTION);
	}

	/*
	 * Loop through the options table, turning the option on.
	 */
	for (Index = 0U; Index < XIICPS_NUM_OPTIONS; Index++) {
		if ((OptionsVar & OptionsTable[Index].Option) != (u32)0x0U) {
			/*
			 * 10-bit option is specially treated, because it is
			 * using the 7-bit option, so turning it on means
			 * turning 7-bit option off.
			 */
			if ((OptionsTable[Index].Option &
				XIICPS_10_BIT_ADDR_OPTION) != (u32)0x0U) {
				/* Turn 7-bit off */
				ControlReg &= ~OptionsTable[Index].Mask;
			} else {
				/* Turn 7-bit on */
				ControlReg |= OptionsTable[Index].Mask;
			}
		}
	}

	/*
	 * Now write to the control register. Leave it to the upper layers
	 * to restart the device.
	 */
	XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
			  ControlReg);

	/*
	 * Keep a copy of what options this instance has.
	 */
	InstancePtr->Options = XIicPs_GetOptions(InstancePtr);

	return (s32)XST_SUCCESS;
}
Example #10
0
/**
*
* Runs a 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.
*
* Upon successful return from the self-test, the device is reset.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
*
* @return
*		- XST_SUCCESS if successful.
*		- XST_REGISTER_ERROR indicates a register did not read or write
*		correctly
*
* @note		None.
*
******************************************************************************/
int XIicPs_SelfTest(XIicPs *InstancePtr)
{

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

	/*
	 * All the IIC registers should be in their default state right now.
	 */
	if ((XIICPS_CR_RESET_VALUE !=
		 XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
				  XIICPS_CR_OFFSET)) ||
		(XIICPS_TO_RESET_VALUE !=
		 XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
				  XIICPS_TIME_OUT_OFFSET)) ||
		(XIICPS_IXR_ALL_INTR_MASK !=
		 XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
				  XIICPS_IMR_OFFSET))) {
		return XST_FAILURE;
	}

	XIicPs_Reset(InstancePtr);

	/*
	 * Write, Read then write a register
	 */
	XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
			  XIICPS_SLV_PAUSE_OFFSET, REG_TEST_VALUE);

	if (REG_TEST_VALUE != XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
						   XIICPS_SLV_PAUSE_OFFSET)) {
		return XST_FAILURE;
	}

	XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
			  XIICPS_SLV_PAUSE_OFFSET, 0);

	XIicPs_Reset(InstancePtr);

	return XST_SUCCESS;
}
Example #11
0
/**
* This function enables the slave monitor mode.
*
* It enables slave monitor in the control register and enables
* slave ready interrupt. It then does an address transfer to slave.
* Interrupt handler will signal the caller if slave responds to
* the address transfer.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	SlaveAddr is the address of the slave we want to contact.
*
* @return	None.
*
* @note		None.
*
****************************************************************************/
void XIicPs_EnableSlaveMonitor(XIicPs *InstancePtr, u16 SlaveAddr)
{
	u32 BaseAddr;
	u32 ConfigReg;

	Xil_AssertVoid(InstancePtr != NULL);

	BaseAddr = InstancePtr->Config.BaseAddress;

	/* Clear transfer size register */
	XIicPs_WriteReg(BaseAddr, (u32)XIICPS_TRANS_SIZE_OFFSET, 0x0U);

	/*
	 * Enable slave monitor mode in control register.
	 */
	ConfigReg = XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET);
	ConfigReg |= (u32)XIICPS_CR_MS_MASK | (u32)XIICPS_CR_NEA_MASK |
			(u32)XIICPS_CR_CLR_FIFO_MASK | (u32)XIICPS_CR_SLVMON_MASK;
	ConfigReg &= (u32)(~XIICPS_CR_RD_WR_MASK);

	XIicPs_WriteReg(BaseAddr, (u32)XIICPS_CR_OFFSET, ConfigReg);

	/*
	 * Set up interrupt flag for slave monitor interrupt.
	 * Dont enable NACK.
	 */
	XIicPs_EnableInterrupts(BaseAddr, (u32)XIICPS_IXR_SLV_RDY_MASK);

	/*
	 * Initialize the slave monitor register.
	 */
	XIicPs_WriteReg(BaseAddr, (u32)XIICPS_SLV_PAUSE_OFFSET, 0xFU);

	/*
	 * Set the slave address to start the slave address transmission.
	 */
	XIicPs_WriteReg(BaseAddr, (u32)XIICPS_ADDR_OFFSET, (u32)SlaveAddr);

	return;
}
/**
*
* Aborts a transfer in progress by resetting the FIFOs. The byte counts are
* cleared.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
void XIicPs_Abort(XIicPs *InstancePtr)
{
	u32 IntrMaskReg;
	u32 IntrStatusReg;

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

	/*
	 * Enter a critical section, so disable the interrupts while we clear
	 * the FIFO and the status register.
	 */
	IntrMaskReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
					   XIICPS_IMR_OFFSET);
	XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
			  XIICPS_IDR_OFFSET, XIICPS_IXR_ALL_INTR_MASK);

	/*
	 * Clear the FIFOs.
	 */
	XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
			  XIICPS_CR_CLR_FIFO_MASK);

	/*
	 * Read, then write the interrupt status to make sure there are no
	 * pending interrupts.
	 */
	IntrStatusReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
					 XIICPS_ISR_OFFSET);
	XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
			  XIICPS_ISR_OFFSET, IntrStatusReg);

	/*
	 * Restore the interrupt state.
	 */
	IntrMaskReg = XIICPS_IXR_ALL_INTR_MASK & (~IntrMaskReg);
	XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
			  XIICPS_IER_OFFSET, IntrMaskReg);

}
/**
*
* Resets the IIC device. Reset must only be called after the driver has been
* initialized. The configuration of the device after reset is the same as its
* configuration after initialization.  Any data transfer that is in progress is
* aborted.
*
* The upper layer software is responsible for re-configuring (if necessary)
* and reenabling interrupts for the IIC device after the reset.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
void XIicPs_Reset(XIicPs *InstancePtr)
{

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

	/*
	 * Abort any transfer that is in progress.
	 */
	XIicPs_Abort(InstancePtr);

	/*
	 * Reset any values so the software state matches the hardware device.
	 */
	XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
			  XIICPS_CR_RESET_VALUE);
	XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
			  XIICPS_TIME_OUT_OFFSET, XIICPS_TO_RESET_VALUE);
	XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_IDR_OFFSET,
			  XIICPS_IXR_ALL_INTR_MASK);

}
Example #14
0
/**
*
* This function sets the options for the IIC device driver. The options control
* how the device behaves relative to the IIC bus. The device must be idle
* rather than busy transferring data before setting these device options.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	Options contains the specified options to be set. This is a bit
*		mask where a 1 means to turn the option on. One or more bit
*		values may be contained in the mask. See the bit definitions
*		named XIICPS_*_OPTION in xiicps.h.
*
* @return
*		- XST_SUCCESS if options are successfully set.
*		- XST_DEVICE_IS_STARTED if the device is currently transferring
*		data. The transfer must complete or be aborted before setting
*		options.
*
* @note		None.
*
******************************************************************************/
int XIicPs_SetOptions(XIicPs *InstancePtr, u32 Options)
{
	u32 ControlReg;
	unsigned int Index;

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

	ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
				      XIICPS_CR_OFFSET);

	/*
	 * Loop through the options table, turning the option on.
	 */
	for (Index = 0; Index < XIICPS_NUM_OPTIONS; Index++) {
 		if (Options & OptionsTable[Index].Option) {
			/*
			 * 10-bit option is specially treated, because it is
			 * using the 7-bit option, so turning it on means
			 * turning 7-bit option off.
			 */
			if (OptionsTable[Index].Option &
				XIICPS_10_BIT_ADDR_OPTION) {
				/* Turn 7-bit off */
				ControlReg &= ~OptionsTable[Index].Mask;
 			} else {
				/* Turn 7-bit on */
				ControlReg |= OptionsTable[Index].Mask;
			}
		}
	}

	/*
	 * Now write to the control register. Leave it to the upper layers
	 * to restart the device.
	 */
	XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
			  ControlReg);

	/*
	 * Keep a copy of what options this instance has.
	 */
	InstancePtr->Options = XIicPs_GetOptions(InstancePtr);

	return XST_SUCCESS;
}
Example #15
0
/*
* This function prepares a device to transfers as a master.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
*
* @param	Role specifies whether the device is sending or receiving.
*
* @return
*		- XST_SUCCESS if everything went well.
*		- XST_FAILURE if bus is busy.
*
* @note		Interrupts are always disabled, device which needs to use
*		interrupts needs to setup interrupts after this call.
*
****************************************************************************/
static int XIicPs_SetupMaster(XIicPs *InstancePtr, int Role)
{
	u32 ControlReg;
	u32 BaseAddr;
	u32 EnabledIntr = 0x0;

	Xil_AssertNonvoid(InstancePtr != NULL);

	BaseAddr = InstancePtr->Config.BaseAddress;
	ControlReg = XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET);


	/*
	 * Only check if bus is busy when repeated start option is not set.
	 */
	if ((ControlReg & XIICPS_CR_HOLD_MASK) == 0) {
		if (XIicPs_BusIsBusy(InstancePtr)) {
			return XST_FAILURE;
		}
	}

	/*
	 * Set up master, AckEn, nea and also clear fifo.
	 */
	ControlReg |= XIICPS_CR_ACKEN_MASK | XIICPS_CR_CLR_FIFO_MASK |
		 	XIICPS_CR_NEA_MASK | XIICPS_CR_MS_MASK;

	if (Role == RECVING_ROLE) {
		ControlReg |= XIICPS_CR_RD_WR_MASK;
		EnabledIntr = XIICPS_IXR_DATA_MASK |XIICPS_IXR_RX_OVR_MASK;
	}else {
		ControlReg &= ~XIICPS_CR_RD_WR_MASK;
	}
	EnabledIntr |= XIICPS_IXR_COMP_MASK | XIICPS_IXR_ARB_LOST_MASK;

	XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, ControlReg);

	XIicPs_DisableAllInterrupts(BaseAddr);

	return XST_SUCCESS;
}
Example #16
0
/*
* This function prepares a device to transfers as a master.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
*
* @param	Role specifies whether the device is sending or receiving.
*
* @return
*		- XST_SUCCESS if everything went well.
*		- XST_FAILURE if bus is busy.
*
* @note		Interrupts are always disabled, device which needs to use
*		interrupts needs to setup interrupts after this call.
*
****************************************************************************/
static s32 XIicPs_SetupMaster(XIicPs *InstancePtr, s32 Role)
{
	u32 ControlReg;
	u32 BaseAddr;

	Xil_AssertNonvoid(InstancePtr != NULL);

	BaseAddr = InstancePtr->Config.BaseAddress;
	ControlReg = XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET);


	/*
	 * Only check if bus is busy when repeated start option is not set.
	 */
	if ((ControlReg & XIICPS_CR_HOLD_MASK) == 0U) {
		if (XIicPs_BusIsBusy(InstancePtr) == (s32)1) {
			return (s32)XST_FAILURE;
		}
	}

	/*
	 * Set up master, AckEn, nea and also clear fifo.
	 */
	ControlReg |= (u32)XIICPS_CR_ACKEN_MASK | (u32)XIICPS_CR_CLR_FIFO_MASK |
			(u32)XIICPS_CR_NEA_MASK | (u32)XIICPS_CR_MS_MASK;

	if (Role == RECVING_ROLE) {
		ControlReg |= (u32)XIICPS_CR_RD_WR_MASK;
	}else {
		ControlReg &= (u32)(~XIICPS_CR_RD_WR_MASK);
	}

	XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, ControlReg);

	XIicPs_DisableAllInterrupts(BaseAddr);

	return (s32)XST_SUCCESS;
}
Example #17
0
/*
* This function handles continuation of sending data. It is invoked
* from interrupt handler.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
*
* @return	None.
*
* @note		None.
*
****************************************************************************/
static void MasterSendData(XIicPs *InstancePtr)
{
	TransmitFifoFill(InstancePtr);

	/*
	 * Clear hold bit if done, so stop can be sent out.
	 */
	if (InstancePtr->SendByteCount == 0) {

		/*
		 * If user has enabled repeated start as an option,
		 * do not disable it.
		 */
		if (!(InstancePtr->IsRepeatedStart)) {

			XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
				XIICPS_CR_OFFSET,
				XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
				XIICPS_CR_OFFSET) & ~ XIICPS_CR_HOLD_MASK);
		}
	}

	return;
}
Example #18
0
/**
* This function receives a buffer in polled mode as a slave.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	MsgPtr is the pointer to the receive buffer.
* @param	ByteCount is the number of bytes to be received.
*
* @return
*		- XST_SUCCESS if everything went well.
*		- XST_FAILURE if timed out.
*
* @note		This receive routine is for polled mode transfer only.
*
****************************************************************************/
s32 XIicPs_SlaveRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
{
	u32 IntrStatusReg;
	u32 StatusReg;
	u32 BaseAddr;
	s32 Count;

	/*
	 * Assert validates the input arguments.
	 */
	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(MsgPtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);

	BaseAddr = InstancePtr->Config.BaseAddress;
	InstancePtr->RecvBufferPtr = MsgPtr;
	InstancePtr->RecvByteCount = ByteCount;

	StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);

	/*
	 * Clear the interrupt status register.
	 */
	IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
	XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);

	/*
	 * Clear the status register.
	 */
	StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
	XIicPs_WriteReg(BaseAddr, XIICPS_SR_OFFSET, StatusReg);

	StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
	Count = InstancePtr->RecvByteCount;
	while (Count > (s32)0) {

		/* Wait for master to put data */
		while ((StatusReg & XIICPS_SR_RXDV_MASK) == 0U) {
		    StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);

			/*
			 * If master terminates the transfer before we get all
			 * the data or the master tries to read from us,
		 	 * it is an error.
			 */
			IntrStatusReg = XIicPs_ReadReg(BaseAddr,
						XIICPS_ISR_OFFSET);
			if (((IntrStatusReg & (XIICPS_IXR_DATA_MASK |
					XIICPS_IXR_COMP_MASK))!=0x0U) &&
				((StatusReg & XIICPS_SR_RXDV_MASK) == 0U) &&
				((InstancePtr->RecvByteCount > 0) != 0x0U)) {

				return (s32)XST_FAILURE;
			}

			/*
			 * Clear the interrupt status register.
			 */
			XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
			IntrStatusReg);
		}

		/*
		 * Read all data from FIFO.
		 */
		while (((StatusReg & XIICPS_SR_RXDV_MASK)!=0x0U) &&
			 ((InstancePtr->RecvByteCount > 0) != 0x0U)){

			XIicPs_RecvByte(InstancePtr);

			StatusReg = XIicPs_ReadReg(BaseAddr,
				XIICPS_SR_OFFSET);
		}
		Count = InstancePtr->RecvByteCount;
	}

	return (s32)XST_SUCCESS;
}
Example #19
0
/**
* The interrupt handler for the master mode. It does the protocol handling for
* the interrupt-driven transfers.
*
* Completion events and errors are signaled to upper layer for proper handling.
*
* <pre>
* The interrupts that are handled are:
* - DATA
*	This case is handled only for master receive data.
*	The master has to request for more data (if there is more data to
*	receive) and read the data from the FIFO .
*
* - COMP
*	If the Master is transmitting data and there is more data to be
*	sent then the data is written to the FIFO. If there is no more data to
*	be transmitted then a completion event is signalled to the upper layer
*	by calling the callback handler.
*
*	If the Master is receiving data then the data is read from the FIFO and
*	the Master has to request for more data (if there is more data to
*	receive). If all the data has been received then a completion event
*	is signalled to the upper layer by calling the callback handler.
*	It is an error if the amount of received data is more than expected.
*
* - NAK and SLAVE_RDY
*	This is signalled to the upper layer by calling the callback handler.
*
* - All Other interrupts
*	These interrupts are marked as error. This is signalled to the upper
*	layer by calling the callback handler.
*
* </pre>
*
* @param	InstancePtr is a pointer to the XIicPs instance.
*
* @return	None.
*
* @note 	None.
*
****************************************************************************/
void XIicPs_MasterInterruptHandler(XIicPs *InstancePtr)
{
	u32 IntrStatusReg;
	u32 StatusEvent = 0;
	u32 BaseAddr;
	int ByteCnt;
	int IsHold;

	/*
	 * Assert validates the input arguments.
	 */
	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	BaseAddr = InstancePtr->Config.BaseAddress;

	/*
	 * Read the Interrupt status register.
	 */
	IntrStatusReg = XIicPs_ReadReg(BaseAddr,
					 XIICPS_ISR_OFFSET);

	/*
	 * Write the status back to clear the interrupts so no events are
	 * missed while processing this interrupt.
	 */
	XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);

	/*
	 * Use the Mask register AND with the Interrupt Status register so
	 * disabled interrupts are not processed.
	 */
	IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET));

	ByteCnt = InstancePtr->CurrByteCount;

	IsHold = 0;
	if (XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) & XIICPS_CR_HOLD_MASK) {
		IsHold = 1;
	}

	/*
	 * Send
	 */
	if ((InstancePtr->IsSend) &&
		(0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK))) {
		if (InstancePtr->SendByteCount > 0) {
			MasterSendData(InstancePtr);
		} else {
			StatusEvent |= XIICPS_EVENT_COMPLETE_SEND;
		}
	}


	/*
	 * Receive
	 */
	if ((!(InstancePtr->IsSend)) &&
		((0 != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) ||
		(0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK)))){

		while (XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET) &
				XIICPS_SR_RXDV_MASK) {
			if ((InstancePtr->RecvByteCount <
				XIICPS_DATA_INTR_DEPTH) && IsHold &&
				(!(InstancePtr->IsRepeatedStart))) {
				IsHold = 0;
				XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
						XIicPs_ReadReg(BaseAddr,
						XIICPS_CR_OFFSET) &
						(~XIICPS_CR_HOLD_MASK));
			}
			XIicPs_RecvByte(InstancePtr);
			ByteCnt--;

			if (InstancePtr->UpdateTxSize &&
				(ByteCnt == XIICPS_FIFO_DEPTH + 1))
				break;
		}

		if (InstancePtr->UpdateTxSize &&
			(ByteCnt == XIICPS_FIFO_DEPTH + 1)) {
			/*
			 * wait while fifo is full
			 */
			while(XIicPs_ReadReg(BaseAddr,
				XIICPS_TRANS_SIZE_OFFSET) !=
				(ByteCnt - XIICPS_FIFO_DEPTH));

			if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) >
				XIICPS_MAX_TRANSFER_SIZE) {

				XIicPs_WriteReg(BaseAddr,
					XIICPS_TRANS_SIZE_OFFSET,
					XIICPS_MAX_TRANSFER_SIZE);
				ByteCnt = XIICPS_MAX_TRANSFER_SIZE +
						XIICPS_FIFO_DEPTH;
			}else {
				XIicPs_WriteReg(BaseAddr,
					XIICPS_TRANS_SIZE_OFFSET,
					InstancePtr->RecvByteCount -
					XIICPS_FIFO_DEPTH);
				InstancePtr->UpdateTxSize = 0;
				ByteCnt = InstancePtr->RecvByteCount;
			}
		}
		InstancePtr->CurrByteCount = ByteCnt;
	}

	if ((!(InstancePtr->IsSend)) &&
		(0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK))) {
		/*
		 * If all done, tell the application.
		 */
		if (InstancePtr->RecvByteCount == 0){
			if (!(InstancePtr->IsRepeatedStart)) {
				XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
						XIicPs_ReadReg(BaseAddr,
						XIICPS_CR_OFFSET) &
						(~XIICPS_CR_HOLD_MASK));
			}
			StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
		}
	}


	/*
	 * Slave ready interrupt, it is only meaningful for master mode.
	 */
	if (0 != (IntrStatusReg & XIICPS_IXR_SLV_RDY_MASK)) {
		StatusEvent |= XIICPS_EVENT_SLAVE_RDY;
	}

	if (0 != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {
		if (!(InstancePtr->IsRepeatedStart)) {
			XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
					XIicPs_ReadReg(BaseAddr,
					XIICPS_CR_OFFSET) &
					(~XIICPS_CR_HOLD_MASK));
		}
		StatusEvent |= XIICPS_EVENT_NACK;
	}

	/*
	 * All other interrupts are treated as error.
	 */
	if (0 != (IntrStatusReg & (XIICPS_IXR_NACK_MASK |
			XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_RX_UNF_MASK |
			XIICPS_IXR_TX_OVR_MASK | XIICPS_IXR_RX_OVR_MASK))) {
		if (!(InstancePtr->IsRepeatedStart)) {
			XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
					XIicPs_ReadReg(BaseAddr,
					XIICPS_CR_OFFSET) &
					(~XIICPS_CR_HOLD_MASK));
		}
		StatusEvent |= XIICPS_EVENT_ERROR;
	}

	/*
	 * Signal application if there are any events.
	 */
	if (0 != StatusEvent) {
		InstancePtr->StatusHandler(InstancePtr->CallBackRef,
					   StatusEvent);
	}

}
Example #20
0
/**
* The interrupt handler for the master mode. It does the protocol handling for
* the interrupt-driven transfers.
*
* Completion events and errors are signaled to upper layer for proper handling.
*
* <pre>
* The interrupts that are handled are:
* - DATA
*	This case is handled only for master receive data.
*	The master has to request for more data (if there is more data to
*	receive) and read the data from the FIFO .
*
* - COMP
*	If the Master is transmitting data and there is more data to be
*	sent then the data is written to the FIFO. If there is no more data to
*	be transmitted then a completion event is signalled to the upper layer
*	by calling the callback handler.
*
*	If the Master is receiving data then the data is read from the FIFO and
*	the Master has to request for more data (if there is more data to
*	receive). If all the data has been received then a completion event
*	is signalled to the upper layer by calling the callback handler.
*	It is an error if the amount of received data is more than expected.
*
* - NAK and SLAVE_RDY
*	This is signalled to the upper layer by calling the callback handler.
*
* - All Other interrupts
*	These interrupts are marked as error. This is signalled to the upper
*	layer by calling the callback handler.
*
* </pre>
*
* @param	InstancePtr is a pointer to the XIicPs instance.
*
* @return	None.
*
* @note 	None.
*
****************************************************************************/
void XIicPs_MasterInterruptHandler(XIicPs *InstancePtr)
{
	u32 IntrStatusReg;
	u32 StatusEvent = 0U;
	u32 BaseAddr;
	u16 SlaveAddr;
	s32 ByteCnt;
	s32 IsHold;
	u32 Platform;

	/*
	 * Assert validates the input arguments.
	 */
	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);

	BaseAddr = InstancePtr->Config.BaseAddress;

	Platform = XGetPlatform_Info();

	/*
	 * Read the Interrupt status register.
	 */
	IntrStatusReg = XIicPs_ReadReg(BaseAddr,
					 (u32)XIICPS_ISR_OFFSET);

	/*
	 * Write the status back to clear the interrupts so no events are
	 * missed while processing this interrupt.
	 */
	XIicPs_WriteReg(BaseAddr, (u32)XIICPS_ISR_OFFSET, IntrStatusReg);

	/*
	 * Use the Mask register AND with the Interrupt Status register so
	 * disabled interrupts are not processed.
	 */
	IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, (u32)XIICPS_IMR_OFFSET));

	ByteCnt = InstancePtr->CurrByteCount;

	IsHold = 0;
	if ((XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) & (u32)XIICPS_CR_HOLD_MASK) != 0U) {
		IsHold = 1;
	}

	/*
	 * Send
	 */
	if (((InstancePtr->IsSend) != 0) &&
		((u32)0U != (IntrStatusReg & (u32)XIICPS_IXR_COMP_MASK))) {
		if (InstancePtr->SendByteCount > 0) {
			MasterSendData(InstancePtr);
		} else {
			StatusEvent |= XIICPS_EVENT_COMPLETE_SEND;
		}
	}


	/*
	 * Receive
	 */
	if (((!(InstancePtr->IsSend))!= 0) &&
		((0 != (IntrStatusReg & (u32)XIICPS_IXR_DATA_MASK)) ||
		(0 != (IntrStatusReg & (u32)XIICPS_IXR_COMP_MASK)))){

		while ((XIicPs_ReadReg(BaseAddr, (u32)XIICPS_SR_OFFSET) &
				XIICPS_SR_RXDV_MASK) != 0U) {
			if (((InstancePtr->RecvByteCount <
				XIICPS_DATA_INTR_DEPTH)!= 0U)  && (IsHold != 0)  &&
				((!InstancePtr->IsRepeatedStart)!= 0) &&
				(InstancePtr->UpdateTxSize == 0)) {
				IsHold = 0;
				XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
						XIicPs_ReadReg(BaseAddr,
						XIICPS_CR_OFFSET) &
						(~XIICPS_CR_HOLD_MASK));
			}
			XIicPs_RecvByte(InstancePtr);
			ByteCnt--;

			if (Platform == (u32)XPLAT_ZYNQ) {
			    if ((InstancePtr->UpdateTxSize != 0) &&
				    (ByteCnt == (XIICPS_FIFO_DEPTH + 1))) {
				    break;
				}
			}
		}

		if (Platform == (u32)XPLAT_ZYNQ) {
			if ((InstancePtr->UpdateTxSize != 0) &&
				(ByteCnt == (XIICPS_FIFO_DEPTH + 1))) {
				/* wait while fifo is full */
				while (XIicPs_ReadReg(BaseAddr,
					XIICPS_TRANS_SIZE_OFFSET) !=
					(u32)(ByteCnt - XIICPS_FIFO_DEPTH)) {
				}

				if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) >
					(s32)XIICPS_MAX_TRANSFER_SIZE) {

					XIicPs_WriteReg(BaseAddr,
						XIICPS_TRANS_SIZE_OFFSET,
						XIICPS_MAX_TRANSFER_SIZE);
					ByteCnt = (s32)XIICPS_MAX_TRANSFER_SIZE +
							XIICPS_FIFO_DEPTH;
				} else {
					XIicPs_WriteReg(BaseAddr,
						XIICPS_TRANS_SIZE_OFFSET,
						InstancePtr->RecvByteCount -
						XIICPS_FIFO_DEPTH);
					InstancePtr->UpdateTxSize = 0;
					ByteCnt = InstancePtr->RecvByteCount;
				}
			}
		} else {
			if ((InstancePtr->RecvByteCount > 0) && (ByteCnt == 0)) {
				/*
				 * Clear the interrupt status register before use it to
				 * monitor.
				 */
				IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
				XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);

				SlaveAddr = (u16)XIicPs_ReadReg(BaseAddr, (u32)XIICPS_ADDR_OFFSET);
				XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);

				if ((InstancePtr->RecvByteCount) >
					(s32)XIICPS_MAX_TRANSFER_SIZE) {

					XIicPs_WriteReg(BaseAddr,
						XIICPS_TRANS_SIZE_OFFSET,
						XIICPS_MAX_TRANSFER_SIZE);
					ByteCnt = (s32)XIICPS_MAX_TRANSFER_SIZE;
				} else {
					XIicPs_WriteReg(BaseAddr,
						XIICPS_TRANS_SIZE_OFFSET,
						InstancePtr->RecvByteCount);
					InstancePtr->UpdateTxSize = 0;
					ByteCnt = InstancePtr->RecvByteCount;
				}
				XIicPs_EnableInterrupts(BaseAddr,
					(u32)XIICPS_IXR_NACK_MASK | (u32)XIICPS_IXR_DATA_MASK |
					(u32)XIICPS_IXR_RX_OVR_MASK | (u32)XIICPS_IXR_COMP_MASK |
					(u32)XIICPS_IXR_ARB_LOST_MASK);
			}
		}
		InstancePtr->CurrByteCount = ByteCnt;
	}

	if (((!(InstancePtr->IsSend)) != 0) &&
		(0U != (IntrStatusReg & XIICPS_IXR_COMP_MASK))) {
		/*
		 * If all done, tell the application.
		 */
		if (InstancePtr->RecvByteCount == 0){
			if ((!(InstancePtr->IsRepeatedStart)) != 0) {
				XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
						XIicPs_ReadReg(BaseAddr,
						XIICPS_CR_OFFSET) &
						(~XIICPS_CR_HOLD_MASK));
			}
			StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
		}
	}


	/*
	 * Slave ready interrupt, it is only meaningful for master mode.
	 */
	if (0U != (IntrStatusReg & XIICPS_IXR_SLV_RDY_MASK)) {
		StatusEvent |= XIICPS_EVENT_SLAVE_RDY;
	}

	if (0U != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {
		if ((!(InstancePtr->IsRepeatedStart)) != 0 ) {
			XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
					XIicPs_ReadReg(BaseAddr,
					XIICPS_CR_OFFSET) &
					(~XIICPS_CR_HOLD_MASK));
		}
		StatusEvent |= XIICPS_EVENT_NACK;
	}

	/*
	 * Arbitration lost interrupt
	 */
	if (0U != (IntrStatusReg & XIICPS_IXR_ARB_LOST_MASK)) {
		StatusEvent |= XIICPS_EVENT_ARB_LOST;
	}

	/*
	 * All other interrupts are treated as error.
	 */
	if (0U != (IntrStatusReg & (XIICPS_IXR_NACK_MASK |
			XIICPS_IXR_RX_UNF_MASK | XIICPS_IXR_TX_OVR_MASK |
			XIICPS_IXR_RX_OVR_MASK))) {
		if ((!(InstancePtr->IsRepeatedStart)) != 0) {
			XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
					XIicPs_ReadReg(BaseAddr,
					XIICPS_CR_OFFSET) &
					(~XIICPS_CR_HOLD_MASK));
		}
		StatusEvent |= XIICPS_EVENT_ERROR;
	}

	/*
	 * Signal application if there are any events.
	 */
	if (StatusEvent != 0U) {
		InstancePtr->StatusHandler(InstancePtr->CallBackRef,
					   StatusEvent);
	}

}
Example #21
0
/**
* This function initiates a polled mode receive in master mode.
*
* It repeatedly sets the transfer size register so the slave can
* send data to us. It polls the data register for data to come in.
* If slave fails to send us data, it fails with time out.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	MsgPtr is the pointer to the receive buffer.
* @param	ByteCount is the number of bytes to be received.
* @param	SlaveAddr is the address of the slave we are receiving from.
*
* @return
*		- XST_SUCCESS if everything went well.
*		- XST_FAILURE if timed out.
*
* @note		This receive routine is for polled mode transfer only.
*
****************************************************************************/
int XIicPs_MasterRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr,
				int ByteCount, u16 SlaveAddr)
{
	u32 IntrStatusReg;
	u32 Intrs;
	u32 StatusReg;
	u32 BaseAddr;
	int IsHold = 0;
	int UpdateTxSize = 0;

	/*
	 * Assert validates the input arguments.
	 */
	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(MsgPtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
	Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr);

	BaseAddr = InstancePtr->Config.BaseAddress;
	InstancePtr->RecvBufferPtr = MsgPtr;
	InstancePtr->RecvByteCount = ByteCount;

	if((ByteCount > XIICPS_DATA_INTR_DEPTH) ||
		(InstancePtr->IsRepeatedStart))
	{
		XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
				XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
						XIICPS_CR_HOLD_MASK);
		IsHold = 1;
	}

	XIicPs_SetupMaster(InstancePtr, RECVING_ROLE);

	/*
	 * Clear the interrupt status register before use it to monitor.
	 */
	IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
	XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);

	XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);

	/*
	 * Set up the transfer size register so the slave knows how much
	 * to send to us.
	 */
	if (ByteCount > XIICPS_MAX_TRANSFER_SIZE) {
		XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
				XIICPS_MAX_TRANSFER_SIZE);
		ByteCount = XIICPS_MAX_TRANSFER_SIZE;
		UpdateTxSize = 1;
	}else {
		XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
			 ByteCount);
	}

	/*
	 * Intrs keeps all the error-related interrupts.
	 */
	Intrs = XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_RX_OVR_MASK |
			XIICPS_IXR_RX_UNF_MASK | XIICPS_IXR_NACK_MASK;

	/*
	 * Poll the interrupt status register to find the errors.
	 */
	IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
	while ((InstancePtr->RecvByteCount > 0) &&
			((IntrStatusReg & Intrs) == 0)) {
		StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);

		while (StatusReg & XIICPS_SR_RXDV_MASK) {
			if ((InstancePtr->RecvByteCount <
				XIICPS_DATA_INTR_DEPTH) && IsHold &&
				(!(InstancePtr->IsRepeatedStart))) {
				IsHold = 0;
				XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
						XIicPs_ReadReg(BaseAddr,
						XIICPS_CR_OFFSET) &
						(~XIICPS_CR_HOLD_MASK));
			}
			XIicPs_RecvByte(InstancePtr);
			ByteCount --;

			if (UpdateTxSize &&
				(ByteCount == XIICPS_FIFO_DEPTH + 1))
				break;

			StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
		}

		if (UpdateTxSize && (ByteCount == XIICPS_FIFO_DEPTH + 1)) {
			/*
			 * wait while fifo is full
			 */
			while(XIicPs_ReadReg(BaseAddr,
				XIICPS_TRANS_SIZE_OFFSET) !=
				(ByteCount - XIICPS_FIFO_DEPTH));

			if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) >
				XIICPS_MAX_TRANSFER_SIZE) {

				XIicPs_WriteReg(BaseAddr,
					XIICPS_TRANS_SIZE_OFFSET,
					XIICPS_MAX_TRANSFER_SIZE);
				ByteCount = XIICPS_MAX_TRANSFER_SIZE +
						XIICPS_FIFO_DEPTH;
			}else {
				XIicPs_WriteReg(BaseAddr,
					XIICPS_TRANS_SIZE_OFFSET,
					InstancePtr->RecvByteCount -
					XIICPS_FIFO_DEPTH);
				UpdateTxSize = 0;
				ByteCount = InstancePtr->RecvByteCount;
			}
		}

		IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
	}

	if (!(InstancePtr->IsRepeatedStart)) {
		XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
				XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) &
						(~XIICPS_CR_HOLD_MASK));
	}

	if (IntrStatusReg & Intrs) {
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}
Example #22
0
/**
* This function initiates a polled mode send in master mode.
*
* It sends data to the FIFO and waits for the slave to pick them up.
* If slave fails to remove data from FIFO, the send fails with
* time out.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	MsgPtr is the pointer to the send buffer.
* @param	ByteCount is the number of bytes to be sent.
* @param	SlaveAddr is the address of the slave we are sending to.
*
* @return
*		- XST_SUCCESS if everything went well.
*		- XST_FAILURE if timed out.
*
* @note		This send routine is for polled mode transfer only.
*
****************************************************************************/
int XIicPs_MasterSendPolled(XIicPs *InstancePtr, u8 *MsgPtr,
		 int ByteCount, u16 SlaveAddr)
{
	u32 IntrStatusReg;
	u32 StatusReg;
	u32 BaseAddr;
	u32 Intrs;

	/*
	 * Assert validates the input arguments.
	 */
	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(MsgPtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
	Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr);

	BaseAddr = InstancePtr->Config.BaseAddress;
	InstancePtr->SendBufferPtr = MsgPtr;
	InstancePtr->SendByteCount = ByteCount;

	if ((InstancePtr->IsRepeatedStart) ||
		(ByteCount > XIICPS_FIFO_DEPTH)) {
		XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
				XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
						XIICPS_CR_HOLD_MASK);
	}

	XIicPs_SetupMaster(InstancePtr, SENDING_ROLE);

	XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);

	/*
	 * Intrs keeps all the error-related interrupts.
	 */
	Intrs = XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_TX_OVR_MASK |
		XIICPS_IXR_NACK_MASK;

	/*
	 * Clear the interrupt status register before use it to monitor.
	 */
	IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
	XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);

	/*
	 * Transmit first FIFO full of data.
	 */
	TransmitFifoFill(InstancePtr);

	IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);

	/*
	 * Continue sending as long as there is more data and
	 * there are no errors.
	 */
	while ((InstancePtr->SendByteCount > 0) &&
		((IntrStatusReg & Intrs) == 0)) {
		StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);

		/*
		 * Wait until transmit FIFO is empty.
		 */
		if ((StatusReg & XIICPS_SR_TXDV_MASK) != 0) {
			IntrStatusReg = XIicPs_ReadReg(BaseAddr,
					XIICPS_ISR_OFFSET);
			continue;
		}

		/*
		 * Send more data out through transmit FIFO.
		 */
		TransmitFifoFill(InstancePtr);
	}

	/*
	 * Check for completion of transfer.
	 */
	while ((IntrStatusReg & XIICPS_IXR_COMP_MASK) != XIICPS_IXR_COMP_MASK){

		IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
		/*
		 * If there is an error, tell the caller.
		 */
		if ((IntrStatusReg & Intrs) != 0) {
			return XST_FAILURE;
		}
	}

	if (!(InstancePtr->IsRepeatedStart)) {
		XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
				XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) &
						(~XIICPS_CR_HOLD_MASK));
	}

	return XST_SUCCESS;
}
Example #23
0
/**
* This function initiates a polled mode receive in master mode.
*
* It repeatedly sets the transfer size register so the slave can
* send data to us. It polls the data register for data to come in.
* If slave fails to send us data, it fails with time out.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	MsgPtr is the pointer to the receive buffer.
* @param	ByteCount is the number of bytes to be received.
* @param	SlaveAddr is the address of the slave we are receiving from.
*
* @return
*		- XST_SUCCESS if everything went well.
*		- XST_FAILURE if timed out.
*
* @note		This receive routine is for polled mode transfer only.
*
****************************************************************************/
s32 XIicPs_MasterRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr,
				s32 ByteCount, u16 SlaveAddr)
{
	u32 IntrStatusReg;
	u32 Intrs;
	u32 StatusReg;
	u32 BaseAddr;
	s32 BytesToRecv;
	s32 BytesToRead;
	s32 TransSize;
	u32 Status_Rcv;
	u32 Status;
	s32 Result;
	s32 IsHold;
	s32 UpdateTxSize = 0;
	s32 ByteCountVar = ByteCount;
	u32 Platform;

	/*
	 * Assert validates the input arguments.
	 */
	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(MsgPtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
	Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr);

	BaseAddr = InstancePtr->Config.BaseAddress;
	InstancePtr->RecvBufferPtr = MsgPtr;
	InstancePtr->RecvByteCount = ByteCountVar;

	Platform = XGetPlatform_Info();

	if((ByteCountVar > XIICPS_FIFO_DEPTH) ||
		((InstancePtr->IsRepeatedStart) !=0))
	{
		XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
				XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) |
						(u32)XIICPS_CR_HOLD_MASK);
		IsHold = 1;
	} else {
		IsHold = 0;
	}

	(void)XIicPs_SetupMaster(InstancePtr, RECVING_ROLE);

	/*
	 * Clear the interrupt status register before use it to monitor.
	 */
	IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
	XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);

	XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);

	/*
	 * Set up the transfer size register so the slave knows how much
	 * to send to us.
	 */
	if (ByteCountVar > XIICPS_MAX_TRANSFER_SIZE) {
		XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
				XIICPS_MAX_TRANSFER_SIZE);
		ByteCountVar = (s32)XIICPS_MAX_TRANSFER_SIZE;
		UpdateTxSize = 1;
	}else {
		XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
			 ByteCountVar);
	}

	/*
	 * Intrs keeps all the error-related interrupts.
	 */
	Intrs = (u32)XIICPS_IXR_ARB_LOST_MASK | (u32)XIICPS_IXR_RX_OVR_MASK |
			(u32)XIICPS_IXR_RX_UNF_MASK | (u32)XIICPS_IXR_NACK_MASK;
	/*
	 * Poll the interrupt status register to find the errors.
	 */
	IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
	while ((InstancePtr->RecvByteCount > 0) &&
			((IntrStatusReg & Intrs) == 0U)) {
		StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);

	    while ((StatusReg & XIICPS_SR_RXDV_MASK) != 0U) {
		    if (((InstancePtr->RecvByteCount <
			    XIICPS_DATA_INTR_DEPTH) != 0U) && (IsHold != 0) &&
			    ((!InstancePtr->IsRepeatedStart) != 0) &&
			    (UpdateTxSize == 0)) {
				IsHold = 0;
				XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
						XIicPs_ReadReg(BaseAddr,
						XIICPS_CR_OFFSET) &
						(~XIICPS_CR_HOLD_MASK));
			}
			XIicPs_RecvByte(InstancePtr);
		    ByteCountVar --;

			if (Platform == (u32)XPLAT_ZYNQ) {
			    if ((UpdateTxSize != 0) &&
				    (ByteCountVar == (XIICPS_FIFO_DEPTH + 1))) {
				    break;
				}
			}

			StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
		}
		if (Platform == (u32)XPLAT_ZYNQ) {
			if ((UpdateTxSize != 0) &&
				(ByteCountVar == (XIICPS_FIFO_DEPTH + 1))) {
			    /*  wait while fifo is full */
			    while (XIicPs_ReadReg(BaseAddr,
				    XIICPS_TRANS_SIZE_OFFSET) !=
				    (u32)(ByteCountVar - XIICPS_FIFO_DEPTH)) { ;
				}

				if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) >
					XIICPS_MAX_TRANSFER_SIZE) {

					XIicPs_WriteReg(BaseAddr,
						XIICPS_TRANS_SIZE_OFFSET,
						XIICPS_MAX_TRANSFER_SIZE);
				    ByteCountVar = (s32)XIICPS_MAX_TRANSFER_SIZE +
							XIICPS_FIFO_DEPTH;
				} else {
					XIicPs_WriteReg(BaseAddr,
						XIICPS_TRANS_SIZE_OFFSET,
						InstancePtr->RecvByteCount -
						XIICPS_FIFO_DEPTH);
					UpdateTxSize = 0;
				    ByteCountVar = InstancePtr->RecvByteCount;
				}
			}
		} else {
		    if ((InstancePtr->RecvByteCount > 0) && (ByteCountVar == 0)) {
				/*
				 * Clear the interrupt status register before use it to
				 * monitor.
				 */
				IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
				XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);

				XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);

				if ((InstancePtr->RecvByteCount) >
					XIICPS_MAX_TRANSFER_SIZE) {

					XIicPs_WriteReg(BaseAddr,
						XIICPS_TRANS_SIZE_OFFSET,
						XIICPS_MAX_TRANSFER_SIZE);
				    ByteCountVar = (s32)XIICPS_MAX_TRANSFER_SIZE;
				} else {
					XIicPs_WriteReg(BaseAddr,
						XIICPS_TRANS_SIZE_OFFSET,
						InstancePtr->RecvByteCount);
					UpdateTxSize = 0;
				    ByteCountVar = InstancePtr->RecvByteCount;
				}
			}
		}

		IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
	}

	if ((!(InstancePtr->IsRepeatedStart)) != 0) {
		XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
				XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) &
						(~XIICPS_CR_HOLD_MASK));
	}
	if ((IntrStatusReg & Intrs) != 0x0U) {
		Result = (s32)XST_FAILURE;
	}
	else {
		Result =  (s32)XST_SUCCESS;
	}

	return Result;
}
/**
*
* This function sets the serial clock rate for the IIC device. The device
* must be idle rather than busy transferring data before setting these device
* options.
*
* The data rate is set by values in the control register. The formula for
* determining the correct register values is:
* Fscl = Fpclk/(22 x (divisor_a+1) x (divisor_b+1))
* See the hardware data sheet for a full explanation of setting the serial
* clock rate.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	FsclHz is the clock frequency in Hz. The two most common clock
*		rates are 100KHz and 400KHz.
*
* @return
*		- XST_SUCCESS if options are successfully set.
*		- XST_DEVICE_IS_STARTED if the device is currently transferring
*		data. The transfer must complete or be aborted before setting
*		options.
*		- XST_FAILURE if the Fscl frequency can not be set.
*
* @note		The clock can not be faster than the input clock divide by 22.
*
******************************************************************************/
s32 XIicPs_SetSClk(XIicPs *InstancePtr, u32 FsclHz)
{
	u32 Div_a;
	u32 Div_b;
	u32 ActualFscl;
	u32 Temp;
	u32 TempLimit;
	u32 LastError;
	u32 BestError;
	u32 CurrentError;
	u32 ControlReg;
	u32 CalcDivA;
	u32 CalcDivB;
	u32 BestDivA;
	u32 BestDivB;
	u32 FsclHzVar = FsclHz;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
	Xil_AssertNonvoid(FsclHzVar > 0U);

	if (0U != XIicPs_In32((InstancePtr->Config.BaseAddress) +
					XIICPS_TRANS_SIZE_OFFSET)) {
		return (s32)XST_DEVICE_IS_STARTED;
	}

	/*
	 * Assume Div_a is 0 and calculate (divisor_a+1) x (divisor_b+1).
	 */
	Temp = (InstancePtr->Config.InputClockHz) / ((u32)22U * FsclHzVar);

	/*
	 * If the answer is negative or 0, the Fscl input is out of range.
	 */
	if ((u32)(0U) == Temp) {
		return (s32)XST_FAILURE;
	}

	/*
	 * If frequency 400KHz is selected, 384.6KHz should be set.
	 * If frequency 100KHz is selected, 90KHz should be set.
	 * This is due to a hardware limitation.
	 */
	if(FsclHzVar > (u32)384600U) {
		FsclHzVar = (u32)384600U;
	}

	if((FsclHzVar <= (u32)100000U) && (FsclHzVar > (u32)90000U)) {
		FsclHzVar = (u32)90000U;
	}

	/*
	 * TempLimit helps in iterating over the consecutive value of Temp to
	 * find the closest clock rate achievable with divisors.
	 * Iterate over the next value only if fractional part is involved.
	 */
	TempLimit = (((InstancePtr->Config.InputClockHz) %
			((u32)22 * FsclHzVar)) != 	(u32)0x0U) ?
						Temp + (u32)1U : Temp;
	BestError = FsclHzVar;

	BestDivA = 0U;
	BestDivB = 0U;
	for ( ; Temp <= TempLimit ; Temp++)
	{
		LastError = FsclHzVar;
		CalcDivA = 0U;
		CalcDivB = 0U;

		for (Div_b = 0U; Div_b < 64U; Div_b++) {

			Div_a = Temp / (Div_b + 1U);

			if (Div_a != 0U){
				Div_a = Div_a - (u32)1U;
			}
			if (Div_a > 3U){
				continue;
			}
			ActualFscl = (InstancePtr->Config.InputClockHz) /
						(22U * (Div_a + 1U) * (Div_b + 1U));

			if (ActualFscl > FsclHzVar){
				CurrentError = (ActualFscl - FsclHzVar);}
			else{
				CurrentError = (FsclHzVar - ActualFscl);}

			if (LastError > CurrentError) {
				CalcDivA = Div_a;
				CalcDivB = Div_b;
				LastError = CurrentError;
			}
		}

		/*
		 * Used to capture the best divisors.
		 */
		if (LastError < BestError) {
			BestError = LastError;
			BestDivA = CalcDivA;
			BestDivB = CalcDivB;
		}
	}


	/*
	 * Read the control register and mask the Divisors.
	 */
	ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
					  (u32)XIICPS_CR_OFFSET);
	ControlReg &= ~((u32)XIICPS_CR_DIV_A_MASK | (u32)XIICPS_CR_DIV_B_MASK);
	ControlReg |= (BestDivA << XIICPS_CR_DIV_A_SHIFT) |
		(BestDivB << XIICPS_CR_DIV_B_SHIFT);

	XIicPs_WriteReg(InstancePtr->Config.BaseAddress, (u32)XIICPS_CR_OFFSET,
			  ControlReg);

	return (s32)XST_SUCCESS;
}
Example #25
0
/**
* The interrupt handler for slave mode. It does the protocol handling for
* the interrupt-driven transfers.
*
* Completion events and errors are signaled to upper layer for proper
* handling.
*
* <pre>
*
* The interrupts that are handled are:
* - DATA
*	If the instance is sending, it means that the master wants to read more
*	data from us. Send more data, and check whether we are done with this
*	send.
*
*	If the instance is receiving, it means that the master has writen
* 	more data to us. Receive more data, and check whether we are done with
*	with this receive.
*
* - COMP
*	This marks that stop sequence has been sent from the master, transfer
*	is about to terminate. However, for receiving, the master may have
*	written us some data, so receive that first.
*
*	It is an error if the amount of transfered data is less than expected.
*
* - NAK
*	This marks that master does not want our data. It is for send only.
*
* - Other interrupts
*	These interrupts are marked as error.
*
* </pre>
*
* @param	InstancePtr is a pointer to the XIicPs instance.
*
* @return	None.
*
* @note 	None.
*
****************************************************************************/
void XIicPs_SlaveInterruptHandler(XIicPs *InstancePtr)
{
	u32 IntrStatusReg;
	u32 IsSend = 0U;
	u32 StatusEvent = 0U;
	s32 LeftOver;
	u32 BaseAddr;

	/*
	 * Assert validates the input arguments.
	 */
	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);

	BaseAddr = InstancePtr->Config.BaseAddress;

	/*
	 * Read the Interrupt status register.
	 */
	IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);

	/*
	 * Write the status back to clear the interrupts so no events are missed
	 * while processing this interrupt.
	 */
	XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);

	/*
	 * Use the Mask register AND with the Interrupt Status register so
	 * disabled interrupts are not processed.
	 */
	IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET));

	/*
	 * Determine whether the device is sending.
	 */
	if (InstancePtr->RecvBufferPtr == NULL) {
		IsSend = 1U;
	}

	/* Data interrupt
	 *
	 * This means master wants to do more data transfers.
	 * Also check for completion of transfer, signal upper layer if done.
	 */
	if ((u32)0U != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) {
		if (IsSend != 0x0U) {
			LeftOver = TransmitFifoFill(InstancePtr);
				/*
				 * We may finish send here
				 */
				if (LeftOver == 0) {
					StatusEvent |=
						XIICPS_EVENT_COMPLETE_SEND;
				}
		} else {
			LeftOver = SlaveRecvData(InstancePtr);

			/* We may finish the receive here */
			if (LeftOver == 0) {
				StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
			}
		}
	}

	/*
	 * Complete interrupt.
	 *
	 * In slave mode, it means the master has done with this transfer, so
	 * we signal the application using completion event.
	 */
	if (0U != (IntrStatusReg & XIICPS_IXR_COMP_MASK)) {
		if (IsSend != 0x0U) {
			if (InstancePtr->SendByteCount > 0) {
				StatusEvent |= XIICPS_EVENT_ERROR;
			}else {
				StatusEvent |= XIICPS_EVENT_COMPLETE_SEND;
			}
		} else {
			LeftOver = SlaveRecvData(InstancePtr);
			if (LeftOver > 0) {
				StatusEvent |= XIICPS_EVENT_ERROR;
			} else {
				StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
			}
		}
	}

	/*
	 * Nack interrupt, pass this information to application.
	 */
	if (0U != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {
		StatusEvent |= XIICPS_EVENT_NACK;
	}

	/*
	 * All other interrupts are treated as error.
	 */
	if (0U != (IntrStatusReg & (XIICPS_IXR_TO_MASK |
				XIICPS_IXR_RX_UNF_MASK |
				XIICPS_IXR_TX_OVR_MASK |
				XIICPS_IXR_RX_OVR_MASK))){

		StatusEvent |= XIICPS_EVENT_ERROR;
	}

	/*
	 * Signal application if there are any events.
	 */
	if (0U != StatusEvent) {
		InstancePtr->StatusHandler(InstancePtr->CallBackRef,
					   StatusEvent);
	}
}
Example #26
0
/*
 * Set IIC Clock
 */
int SetIiCSClk(XIicPs *InstancePtr, u32 FsclHz) {
	u32 Div_a;
	u32 Div_b;
	u32 ActualFscl;
	u32 Temp;
	u32 TempLimit;
	u32 LastError;
	u32 BestError;
	u32 CurrentError;
	u32 ControlReg;
	u32 CalcDivA;
	u32 CalcDivB;
	u32 BestDivA = 0;
	u32 BestDivB = 0;

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

//	if (0 != XIicPs_In32((InstancePtr->Config.BaseAddress) +
//					XIICPS_TRANS_SIZE_OFFSET)) {
//		return XST_DEVICE_IS_STARTED;
//	}

	/*
	 * Assume Div_a is 0 and calculate (divisor_a+1) x (divisor_b+1).
	 */
	Temp = (InstancePtr->Config.InputClockHz) / (22 * FsclHz);

	/*
	 * If the answer is negative or 0, the Fscl input is out of range.
	 */
	if (0 == Temp) {
		return XST_FAILURE;
	}

	/*
	 * If frequency 400KHz is selected, 384.6KHz should be set.
	 * If frequency 100KHz is selected, 90KHz should be set.
	 * This is due to a hardware limitation.
	 */
	if (FsclHz > 384600) {
		FsclHz = 384600;
	}

	if ((FsclHz <= 100000) && (FsclHz > 90000)) {
		FsclHz = 90000;
	}

	/*
	 * TempLimit helps in iterating over the consecutive value of Temp to
	 * find the closest clock rate achievable with divisors.
	 * Iterate over the next value only if fractional part is involved.
	 */
	TempLimit =
			((InstancePtr->Config.InputClockHz) % (22 * FsclHz)) ?
					Temp + 1 : Temp;
	BestError = FsclHz;

	for (; Temp <= TempLimit; Temp++) {
		LastError = FsclHz;
		CalcDivA = 0;
		CalcDivB = 0;
		CurrentError = 0;

		for (Div_b = 0; Div_b < 64; Div_b++) {

			Div_a = Temp / (Div_b + 1);

			if (Div_a != 0)
				Div_a = Div_a - 1;

			if (Div_a > 3)
				continue;

			ActualFscl = (InstancePtr->Config.InputClockHz)
					/ (22 * (Div_a + 1) * (Div_b + 1));

			if (ActualFscl > FsclHz)
				CurrentError = (ActualFscl - FsclHz);
			else
				CurrentError = (FsclHz - ActualFscl);

			if (LastError > CurrentError) {
				CalcDivA = Div_a;
				CalcDivB = Div_b;
				LastError = CurrentError;
			}
		}

		/*
		 * Used to capture the best divisors.
		 */
		if (LastError < BestError) {
			BestError = LastError;
			BestDivA = CalcDivA;
			BestDivB = CalcDivB;
		}
	}

	/*
	 * Read the control register and mask the Divisors.
	 */
	ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
			XIICPS_CR_OFFSET);
	ControlReg &= ~(XIICPS_CR_DIV_A_MASK | XIICPS_CR_DIV_B_MASK);
	ControlReg |= (BestDivA << XIICPS_CR_DIV_A_SHIFT)
			| (BestDivB << XIICPS_CR_DIV_B_SHIFT);

	XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
			ControlReg);

	return XST_SUCCESS;
}
Example #27
0
/**
* This function sends  a buffer in polled mode as a slave.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	MsgPtr is the pointer to the send buffer.
* @param	ByteCount is the number of bytes to be sent.
*
* @return
*		- XST_SUCCESS if everything went well.
*		- XST_FAILURE if master sends us data or master terminates the
*		transfer before all data has sent out.
*
* @note		This send routine is for polled mode transfer only.
*
****************************************************************************/
s32 XIicPs_SlaveSendPolled(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
{
	u32 IntrStatusReg;
	u32 StatusReg;
	u32 BaseAddr;
	s32 Tmp;
	s32 BytesToSend;
	s32 Error = 0;
	s32 Status = (s32)XST_SUCCESS;
	u32 Value;

	/*
	 * Assert validates the input arguments.
	 */
	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(MsgPtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);

	BaseAddr = InstancePtr->Config.BaseAddress;
	InstancePtr->SendBufferPtr = MsgPtr;
	InstancePtr->SendByteCount = ByteCount;

	/*
	 * Use RXRW bit in status register to wait master to start a read.
	 */
	StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
	while (((StatusReg & XIICPS_SR_RXRW_MASK) == 0U) &&
				((!Error) != 0)) {

		/*
		 * If master tries to send us data, it is an error.
		 */
		if ((StatusReg & XIICPS_SR_RXDV_MASK) != 0x0U) {
			Error = 1;
		}

		StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
	}

	if (Error != 0) {
		Status = (s32)XST_FAILURE;
	} else {

		/*
		 * Clear the interrupt status register.
		 */
		IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
		XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);

		/*
		 * Send data as long as there is more data to send and
		 * there are no errors.
		 */
		Value = (InstancePtr->SendByteCount > (s32)0) &&
						((!Error) != 0);
		while (Value != (u32)0x00U) {

			/*
			 * Find out how many can be sent.
			 */
			BytesToSend = InstancePtr->SendByteCount;
			if (BytesToSend > (s32)(XIICPS_FIFO_DEPTH)) {
				BytesToSend = (s32)(XIICPS_FIFO_DEPTH);
			}

			for(Tmp = 0; Tmp < BytesToSend; Tmp ++) {
				XIicPs_SendByte(InstancePtr);
			}

			StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);

			/*
			 * Wait for master to read the data out of fifo.
			 */
			while (((StatusReg & XIICPS_SR_TXDV_MASK) != (u32)0x00U) &&
							((!Error) != 0)) {

				/*
				 * If master terminates the transfer before all data is
				 * sent, it is an error.
				 */
				IntrStatusReg = XIicPs_ReadReg(BaseAddr,
				XIICPS_ISR_OFFSET);
				if ((IntrStatusReg & XIICPS_IXR_NACK_MASK) != 0x0U) {
					Error = 1;
				}

				/* Clear ISR.
				 */
				XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
							IntrStatusReg);

				StatusReg = XIicPs_ReadReg(BaseAddr,
						XIICPS_SR_OFFSET);
			}
			Value = (InstancePtr->SendByteCount > (s32)0U) &&
							((!Error) != 0);
		}
	}
	if (Error != 0) {
	Status = (s32)XST_FAILURE;
	}

	return Status;
}
Example #28
0
/**
*
* This function sets the serial clock rate for the IIC device. The device
* must be idle rather than busy transferring data before setting these device
* options.
*
* The data rate is set by values in the control register. The formula for
* determining the correct register values is:
* Fscl = Fpclk/(22 x (divisor_a+1) x (divisor_b+1))
* See the hardware data sheet for a full explanation of setting the serial
* clock rate.
*
* @param	InstancePtr is a pointer to the XIicPs instance.
* @param	FsclHz is the clock frequency in Hz. The two most common clock
*		rates are 100KHz and 400KHz.
*
* @return
*		- XST_SUCCESS if options are successfully set.
*		- XST_DEVICE_IS_STARTED if the device is currently transferring
*		data. The transfer must complete or be aborted before setting
*		options.
*		- XST_FAILURE if the Fscl frequency can not be set.
*
* @note		The clock can not be faster than the input clock divide by 22.
*
******************************************************************************/
int XIicPs_SetSClk(XIicPs *InstancePtr, u32 FsclHz)
{
	u32 Div_a;
	u32 Div_b;
	u32 ActualFscl;
	u32 Temp;
	u32 LastError;
	u32 CurrentError;
	u32 ControlReg;
	u32 BestDivA;
	u32 BestDivB;

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

	if (0 != XIicPs_In32((InstancePtr->Config.BaseAddress) +
					XIICPS_TRANS_SIZE_OFFSET)) {
		return XST_DEVICE_IS_STARTED;
	}

	/*
	 * Assume Div_a is 0 and calculate (divisor_a+1) x (divisor_b+1).
	 */
	Temp = (InstancePtr->Config.InputClockHz) / (22 * FsclHz);

	/*
	 * If the answer is negative or 0, the Fscl input is out of range.
	 */
	if (0 == Temp) {
		return XST_FAILURE;
	}

	LastError = FsclHz;
	BestDivA = 0;
	BestDivB = 0;

	for (Div_a = 0; Div_a < 4; Div_a++) {
		Div_b = (Temp / (Div_a + 1)) - 1;
		ActualFscl = (InstancePtr->Config.InputClockHz) /
			(22 * (Div_a + 1) * (Div_b + 1));

		CurrentError = ((ActualFscl > FsclHz) ? (ActualFscl - FsclHz) :
				(FsclHz - ActualFscl));
		if (LastError > CurrentError) {
			BestDivA = Div_a;
			BestDivB = Div_b;
			LastError = CurrentError;
		}
	}

	/*
	 * Read the control register and mask the Divisors.
	 */
	ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
					  XIICPS_CR_OFFSET);
	ControlReg &= ~(XIICPS_CR_DIV_A_MASK | XIICPS_CR_DIV_B_MASK);
	ControlReg |= (BestDivA << XIICPS_CR_DIV_A_SHIFT) |
		(BestDivB << XIICPS_CR_DIV_B_SHIFT);

	XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
			  ControlReg);

	return XST_SUCCESS;
}