embeddedsw/lib/sw_apps/lwip_echo_server/src/i2c_access.c
Nava kishore Manne 1726f14574 lib:sw_apps:standalone drivers license changes
Signed-off-by: Nava kishore Manne <navam@xilinx.com>
2015-05-16 14:37:24 +05:30

424 lines
13 KiB
C

/******************************************************************************
*
* Copyright (C) 2013 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file i2c_lib.c
*
* This file contains library functions to initialize, control and access
* IIC devices.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 1.0 srt 10/19/13 Initial Version
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h"
#ifdef __arm__
#if XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1 || \
XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1
#include "xil_exception.h"
#include "xil_printf.h"
#include "xiicps.h"
#include "sleep.h"
#include "xscugic.h"
/************************** Constant Definitions *****************************/
#define IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID
#define XIIC XIicPs
#define XIICCFG XIicPs_Config
#define I2cSetStatusHandler XIicPs_SetStatusHandler
#define I2cLookupConfig XIicPs_LookupConfig
#define I2cCfgInitialize XIicPs_CfgInitialize
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define IIC_INTR_ID XPAR_XIICPS_0_INTR
#define INTC_HANDLER XScuGic_InterruptHandler
#define IIC_HANDLER XIicPs_IntrHandler
#define INTC XScuGic
#define IIC_SCLK_RATE 100000
/**************************** Type Definitions *******************************/
typedef struct {
XIIC I2cInstance;
INTC IntcInstance;
volatile u8 TransmitComplete; /* Flag to check completion of Transmission */
volatile u8 ReceiveComplete; /* Flag to check completion of Reception */
volatile u32 TotalErrorCount;
} XIIC_LIB;
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int I2cPhyWrite(XIIC_LIB *I2cLibPtr, u8 PhyAddr, u8 Reg, u16 Data, u16 SlaveAddr);
int I2cPhyRead(XIIC_LIB *I2cLibPtr, u8 PhyAddr, u8 Reg, u16 *Data, u16 SlaveAddr);
int I2cSetupHardware(XIIC_LIB *I2cLibPtr);
int I2cWriteData(XIIC_LIB *I2cLibPtr, u8 *WrBuffer, u16 ByteCount, u16 SlaveAddr);
int I2cReadData(XIIC_LIB *I2cLibPtr, u8 *RdBuffer, u16 ByteCount, u16 SlaveAddr);
static int SetupInterruptSystem(XIIC_LIB *I2cLibPtr);
static void StatusHandler(XIIC_LIB *I2cLibPtr, int Event);
/************************* Global Definitions *****************************/
/************************** Function Definitions *****************************/
/*****************************************************************************/
/**
* This function configures the IIC hardware.
*
* @param I2cLibPtr contains a pointer to the instance of the IIC library
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
******************************************************************************/
int I2cSetupHardware(XIIC_LIB *I2cLibPtr)
{
int Status;
XIICCFG *ConfigPtr;
XIIC *I2cInstancePtr;
I2cInstancePtr = &I2cLibPtr->I2cInstance;
/*
* Initialize the IIC driver so that it is ready to use.
*/
ConfigPtr = I2cLookupConfig(IIC_DEVICE_ID);
if (ConfigPtr == NULL) {
return XST_FAILURE;
}
Status = I2cCfgInitialize(I2cInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* GPIO Code to pull MUX out of reset.
*/
Xil_Out32(0xe000a204, 0x2000);
Xil_Out32(0xe000a208, 0x2000);
Xil_Out32(0xe000a040, 0x2000);
/*
* Setup the Interrupt System.
*/
Status = SetupInterruptSystem(I2cLibPtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
I2cSetStatusHandler(I2cInstancePtr, I2cLibPtr, (IIC_HANDLER) StatusHandler);
/*
* Set the IIC serial clock rate.
*/
XIicPs_SetSClk(I2cInstancePtr, IIC_SCLK_RATE);
I2cLibPtr->TotalErrorCount = 0;
I2cLibPtr->TransmitComplete = FALSE;
I2cLibPtr->ReceiveComplete = FALSE;
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function writes data to the PHY.
*
* @param I2cLibPtr contains a pointer to the instance of the IIC library
* @param PhyAddr is the address of PHY to be written
* @param Reg is the register address to be written to
* @param Data is the pointer which contains the data to be written
* @param SlaveAddr is the address of the slave we are sending to.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
******************************************************************************/
int I2cPhyWrite(XIIC_LIB *I2cLibPtr, u8 PhyAddr, u8 Reg, u16 Data, u16 SlaveAddr)
{
int Status;
u8 WrBuffer[3];
WrBuffer[0] = Reg;
WrBuffer[1] = Data >> 8;
WrBuffer[2] = Data;
Status = I2cWriteData(I2cLibPtr, WrBuffer, 3, SlaveAddr);
if (Status != XST_SUCCESS) {
xil_printf("PhyWrite: Writing data failed\n\r");
return Status;
}
return Status;
}
/*****************************************************************************/
/**
* This function reads data from the PHY.
*
* @param I2cLibPtr contains a pointer to the instance of the IIC library
* @param PhyAddr is the address of PHY to be read from
* @param Reg is the register address to be read from
* @param Data is the pointer which stores the data read
* @param SlaveAddr is the address of the slave we are sending to.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
******************************************************************************/
int I2cPhyRead(XIIC_LIB *I2cLibPtr, u8 PhyAddr, u8 Reg, u16 *Data, u16 SlaveAddr)
{
int Status;
u8 WrBuffer[2];
u8 RdBuffer[2];
WrBuffer[0] = Reg;
Status = I2cWriteData(I2cLibPtr, WrBuffer, 1, SlaveAddr);
if (Status != XST_SUCCESS) {
xil_printf("PhyWrite: Writing data failed\n\r");
return Status;
}
Status = I2cReadData(I2cLibPtr, RdBuffer, 2, SlaveAddr);
if (Status != XST_SUCCESS) {
xil_printf("PhyRead: Reading data failed\n\r");
return Status;
}
*Data = RdBuffer[0] << 8 | RdBuffer[1];
return Status;
}
/*****************************************************************************/
/**
* This function writes a buffer of data to the IIC Device.
*
* @param I2cLibPtr contains a pointer to the instance of the IIC library
* @param WrBuffer is the buffer which contains data to be written
* @param ByteCount contains the number of bytes in the buffer to be
* written.
* @param SlaveAddr is the address of the slave we are sending to.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
******************************************************************************/
int I2cWriteData(XIIC_LIB *I2cLibPtr, u8 *WrBuffer, u16 ByteCount,
u16 SlaveAddr)
{
XIIC *I2cInstancePtr;
I2cInstancePtr = &I2cLibPtr->I2cInstance;
I2cLibPtr->TransmitComplete = FALSE;
/*
* Send the Data.
*/
XIicPs_MasterSend(I2cInstancePtr, WrBuffer, ByteCount, SlaveAddr);
/*
* Wait for the entire buffer to be sent, letting the interrupt
* processing work in the background, this function may get
* locked up in this loop if the interrupts are not working
* correctly.
*/
while (I2cLibPtr->TransmitComplete == FALSE) {
if (0 != I2cLibPtr->TotalErrorCount) {
xil_printf("I2cWriteData: Failed due to errors\n\r");
return XST_FAILURE;
}
}
/*
* Wait until bus is idle to start another transfer.
*/
while (XIicPs_BusIsBusy(I2cInstancePtr));
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function read data from the IIC Device.
*
* @param I2cLibPtr contains a pointer to the instance of the IIC library
* @param RdBuffer is the buffer into which data read
* @param ByteCount contains the number of bytes in the buffer to be
* written.
* @param SlaveAddr is the address of the slave we are sending to.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
******************************************************************************/
int I2cReadData(XIIC_LIB *I2cLibPtr, u8 *RdBuffer, u16 ByteCount, u16 SlaveAddr)
{
XIIC *I2cInstancePtr;
I2cInstancePtr = &I2cLibPtr->I2cInstance;
I2cLibPtr->ReceiveComplete = FALSE;
/*
* Receive the Data.
*/
XIicPs_MasterRecv(I2cInstancePtr, RdBuffer, ByteCount, SlaveAddr);
while (I2cLibPtr->ReceiveComplete == FALSE) {
if (0 != I2cLibPtr->TotalErrorCount) {
xil_printf("I2cReadData: Failed due to errors %d\n\r",
I2cLibPtr->TotalErrorCount);
return XST_FAILURE;
}
}
/*
* Wait until bus is idle to start another transfer.
*/
while (XIicPs_BusIsBusy(I2cInstancePtr))
;
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function setups the interrupt system so interrupts can occur for the
* IIC device. The function is application-specific since the actual system may
* or may not have an interrupt controller. The IIC device could be directly
* connected to a processor without an interrupt controller. The user should
* modify this function to fit the application.
*
* @param IicInstPtr contains a pointer to the instance of the IIC device
* which is going to be connected to the interrupt controller.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
static int SetupInterruptSystem(XIIC_LIB *I2cLibPtr)
{
int Status;
XIIC *I2cInstancePtr;
INTC *IntcPtr;
I2cInstancePtr = &I2cLibPtr->I2cInstance;
IntcPtr = &I2cLibPtr->IntcInstance;
XScuGic_Config *IntcConfig;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcPtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XScuGic_SetPriorityTriggerType(IntcPtr, IIC_INTR_ID, 0xA0, 0x3);
/*
* Connect the interrupt handler that will be called when an
* interrupt occurs for the device.
*/
Status = XScuGic_Connect(IntcPtr, IIC_INTR_ID,
(Xil_InterruptHandler) XIicPs_MasterInterruptHandler,
I2cInstancePtr);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Enable the interrupt for the IIC device.
*/
XScuGic_Enable(IntcPtr, IIC_INTR_ID);
/*
* Initialize the exception table and register the interrupt
* controller handler with the exception table
*/
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler) INTC_HANDLER, IntcPtr);
/* Enable non-critical exceptions */Xil_ExceptionEnable();
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This Status handler is called asynchronously from an interrupt
* context and indicates the events that have occurred.
*
* @param InstancePtr is a pointer to the IIC driver instance for which
* the handler is being called for.
* @param Event indicates the condition that has occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void StatusHandler(XIIC_LIB *I2cLibPtr, int Event)
{
/*
* All of the data transfer has been finished.
*/
if (0 != (Event & XIICPS_EVENT_COMPLETE_RECV)) {
I2cLibPtr->ReceiveComplete = TRUE;
} else if (0 != (Event & XIICPS_EVENT_COMPLETE_SEND)) {
I2cLibPtr->TransmitComplete = TRUE;
} else if (0 == (Event & XIICPS_EVENT_SLAVE_RDY)) {
/*
* If it is other interrupt but not slave ready interrupt, it is
* an error.
* Data was received with an error.
*/
I2cLibPtr->TotalErrorCount++;
}
}
#endif
#endif