/* $Id: xuartns550.c,v 1.13 2005/01/04 18:09:33 moleres Exp $ */
/*****************************************************************************
*
*       XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
*       AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
*       SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,
*       OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
*       APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
*       THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
*       AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
*       FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY
*       WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
*       IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
*       REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
*       INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*       FOR A PARTICULAR PURPOSE.
*
*       (c) Copyright 2002 Xilinx Inc.
*       All rights reserved.
*
*****************************************************************************/
/****************************************************************************/
/**
*
* @file xuartns550.c
*
* This file contains the required functions for the 16450/16550 UART driver.
* Refer to the header file xuartns550.h for more detailed information.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver   Who  Date     Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a ecm  08/16/01 First release
* 1.00b jhl  03/11/02 Repartitioned driver for smaller files.
* 1.00b rmm  05/14/03 Fixed diab compiler warnings relating to asserts.
* </pre>
*
*****************************************************************************/

/***************************** Include Files ********************************/

#include "xstatus.h"
#include "xparameters.h"
#include "xuartns550.h"
#include "xuartns550_i.h"
#include "xio.h"

/************************** Constant Definitions ****************************/

#ifndef XPAR_DEFAULT_BAUD_RATE
#define XPAR_DEFAULT_BAUD_RATE 19200
#endif

/* The following constant defines the amount of error that is allowed for
 * a specified baud rate. This error is the difference between the actual
 * baud rate that will be generated using the specified clock and the
 * desired baud rate.
 */
#define XUN_MAX_BAUD_ERROR_RATE         3    /* max % error allowed */

/**************************** Type Definitions ******************************/


/***************** Macros (Inline Functions) Definitions ********************/


/************************** Variable Definitions ****************************/


/************************** Function Prototypes *****************************/

static void XUartNs550_StubHandler(void *CallBackRef, Xuint32 Event,
                                   unsigned int ByteCount);

/****************************************************************************/
/**
*
* Initializes a specific XUartNs550 instance such that it is ready to be used.
* The data format of the device is setup for 8 data bits, 1 stop bit, and no
* parity by default. The baud rate is set to a default value specified by
* XPAR_DEFAULT_BAUD_RATE if the symbol is defined, otherwise it is set to
* 19.2K baud. If the device has FIFOs (16550), they are enabled and the a
* receive FIFO threshold is set for 8 bytes. The default operating mode of the
* driver is polled mode.
*
* @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.
* @param    DeviceId is the unique id of the device controlled by this
*           XUartNs550 instance. Passing in a device id associates the generic
*           XUartNs550 instance to a specific device, as chosen by the caller
*           or application developer.
*
* @return
*
* - XST_SUCCESS if initialization was successful
* - XST_DEVICE_NOT_FOUND if the device ID could not be found in the
*           configuration table
* - XST_UART_BAUD_ERROR if the baud rate is not possible because the input
*           clock frequency is not divisible with an acceptable amount of error
*
* @note
*
* None.
*
*****************************************************************************/
XStatus XUartNs550_Initialize(XUartNs550 *InstancePtr, Xuint16 DeviceId)
{
    XStatus Status;
    Xuint8 LcrRegister;
    XUartNs550_Config *UartNs550ConfigPtr;

    /*
     * Assert validates the input arguments
     */
    XASSERT_NONVOID(InstancePtr != XNULL);

    /*
     * Lookup the device configuration in the temporary CROM table. Use this
     * configuration info down below when initializing this component.
     */
    UartNs550ConfigPtr = XUartNs550_LookupConfig(DeviceId);

    if (UartNs550ConfigPtr == (XUartNs550_Config *)XNULL)
    {
        return XST_DEVICE_NOT_FOUND;
    }

    /*
     * Setup the data that is from the configuration information
     */
    InstancePtr->BaseAddress = UartNs550ConfigPtr->BaseAddress;
    InstancePtr->InputClockHz = UartNs550ConfigPtr->InputClockHz;

    /*
     * Initialize the instance data to some default values and setup a default
     * handler
     */
    InstancePtr->Handler = XUartNs550_StubHandler;

    InstancePtr->SendBuffer.NextBytePtr = XNULL;
    InstancePtr->SendBuffer.RemainingBytes = 0;
    InstancePtr->SendBuffer.RequestedBytes = 0;

    InstancePtr->ReceiveBuffer.NextBytePtr = XNULL;
    InstancePtr->ReceiveBuffer.RemainingBytes = 0;
    InstancePtr->ReceiveBuffer.RequestedBytes = 0;

    /*
     * Indicate the instance is now ready to use, initialized without error
     */
    InstancePtr->IsReady = XCOMPONENT_IS_READY;

    /*
     * set the default Baud rate here, can be changed prior to
     * starting the device
     */

    Status = XUartNs550_SetBaudRate(InstancePtr, XPAR_DEFAULT_BAUD_RATE);

    if (Status != XST_SUCCESS)
    {
        InstancePtr->IsReady = 0;
        return Status;
    }


    /*
     * Set up the default format for the data, 8 bit data, 1 stop bit, no
     * parity
     */
    LcrRegister = XIo_In8(InstancePtr->BaseAddress + XUN_LCR_OFFSET);
    XIo_Out8(InstancePtr->BaseAddress + XUN_LCR_OFFSET,
             XUN_FORMAT_8_BITS);

    /* Enable the FIFOs assuming they are present and set the receive FIFO
     * trigger level for 8 bytes assuming that this will work best with most
     * baud rates, enabling the FIFOs also clears them, note that this must
     * be done with 2 writes, 1st enabling the FIFOs then set the trigger level
     */
    XIo_Out8(InstancePtr->BaseAddress + XUN_FCR_OFFSET,
             XUN_FIFO_ENABLE);
    XIo_Out8(InstancePtr->BaseAddress + XUN_FCR_OFFSET,
             XUN_FIFO_ENABLE | XUN_FIFO_RX_TRIG_MSB);
    /*
     * Clear the statistics for this driver
     */
    XUartNs550_mClearStats(InstancePtr);

    return XST_SUCCESS;
}

/****************************************************************************/
/**
*
* This functions sends the specified buffer of data using the UART in either
* polled or interrupt driven modes. This function is non-blocking such that it
* will return before the data has been sent by the UART. If the UART is busy
* sending data, it will return and indicate zero bytes were sent.
*
* In a polled mode, this function will only send as much data as the UART can
* buffer, either in the transmitter or in the FIFO if present and enabled. The
* application may need to call it repeatedly to send a buffer.
*
* In interrupt mode, this function will start sending the specified buffer and
* then the interrupt handler of the driver will continue sending data until the
* buffer has been sent. A callback function, as specified by the application,
* will be called to indicate the completion of sending the buffer.
*
* @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.
* @param    BufferPtr is pointer to a buffer of data to be sent.
* @param    NumBytes contains the number of bytes to be sent. A value of zero
*           will stop a previous send operation that is in progress in interrupt
*           mode. Any data that was already put into the transmit FIFO will be
*           sent.
*
* @return
*
* The number of bytes actually sent.
*
* @note
*
* The number of bytes is not asserted so that this function may be called with
* a value of zero to stop an operation that is already in progress.
* <br><br>
* This function and the XUartNs550_SetOptions() function modify shared data
* such that there may be a need for mutual exclusion in a multithreaded
* environment and if XUartNs550_SetOptions() if called from a handler.
*
*****************************************************************************/
unsigned int XUartNs550_Send(XUartNs550 *InstancePtr, Xuint8 *BufferPtr,
                             unsigned int NumBytes)
{
    unsigned int BytesSent;
    Xuint8 IerRegister;

    /*
     * Assert validates the input arguments
     */
    XASSERT_NONVOID(InstancePtr != XNULL);
    XASSERT_NONVOID(BufferPtr != XNULL);
    XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
    XASSERT_NONVOID(((signed)NumBytes) >= 0);

    /* Enter a critical region by disabling the UART transmit interrupts to
     * allow this call to stop a previous operation that may be interrupt
     * driven, only stop the transmit interrupt since this critical region is
     * not really exited in the normal manner
     */
    IerRegister = XIo_In8(InstancePtr->BaseAddress + XUN_IER_OFFSET);
    XIo_Out8(InstancePtr->BaseAddress + XUN_IER_OFFSET,
             IerRegister & ~XUN_IER_TX_EMPTY);

    /* Setup the specified buffer to be sent by setting the instance
     * variables so it can be sent with polled or interrupt mode
     */
    InstancePtr->SendBuffer.RequestedBytes = NumBytes;
    InstancePtr->SendBuffer.RemainingBytes = NumBytes;
    InstancePtr->SendBuffer.NextBytePtr = BufferPtr;

    /* Send the buffer using the UART and return the number of bytes sent */

    BytesSent = XUartNs550_SendBuffer(InstancePtr);

    /* The critical region is not exited in this function because of the way
     * the transmit interrupts work.  The other function called enables the
     * tranmit interrupt such that this function can't restore a value to the
     * interrupt enable register and does not need to exit the critical region.
     */
    return BytesSent;
}

/****************************************************************************/
/**
*
* This function will attempt to receive a specified number of bytes of data
* from the UART and store it into the specified buffer. This function is
* designed for either polled or interrupt driven modes. It is non-blocking
* such that it will return if no data has already received by the UART.
*
* In a polled mode, this function will only receive as much data as the UART
* can buffer, either in the receiver or in the FIFO if present and enabled.
* The application may need to call it repeatedly to receive a buffer. Polled
* mode is the default mode of operation for the driver.
*
* In interrupt mode, this function will start receiving and then the interrupt
* handler of the driver will continue receiving data until the buffer has been
* received. A callback function, as specified by the application, will be called
* to indicate the completion of receiving the buffer or when any receive errors
* or timeouts occur. Interrupt mode must be enabled using the SetOptions function.
*
* @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.
* @param    BufferPtr is pointer to buffer for data to be received into
* @param    NumBytes is the number of bytes to be received. A value of zero will
*           stop a previous receive operation that is in progress in interrupt mode.
*
* @return
*
* The number of bytes received.
*
* @note
*
* The number of bytes is not asserted so that this function may be called with
* a value of zero to stop an operation that is already in progress.
*
*****************************************************************************/
unsigned int XUartNs550_Recv(XUartNs550 *InstancePtr,
                             Xuint8 *BufferPtr,
                             unsigned int NumBytes)
{
    unsigned int ReceivedCount;
    Xuint8 IerRegister;

    /*
     * Assert validates the input arguments
     */
    XASSERT_NONVOID(InstancePtr != XNULL);
    XASSERT_NONVOID(BufferPtr != XNULL);
    XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
    XASSERT_NONVOID(((signed)NumBytes) >= 0);

    /* Enter a critical region by disabling all the UART interrupts to allow
     * this call to stop a previous operation that may be interrupt driven
     */
    IerRegister = XIo_In8(InstancePtr->BaseAddress + XUN_IER_OFFSET);
    XIo_Out8(InstancePtr->BaseAddress + XUN_IER_OFFSET, 0);

    /* Setup the specified buffer to be received by setting the instance
     * variables so it can be received with polled or interrupt mode
     */
    InstancePtr->ReceiveBuffer.RequestedBytes = NumBytes;
    InstancePtr->ReceiveBuffer.RemainingBytes = NumBytes;
    InstancePtr->ReceiveBuffer.NextBytePtr = BufferPtr;

    /* Receive the data from the UART and return the number of bytes
     * received
     */
    ReceivedCount = XUartNs550_ReceiveBuffer(InstancePtr);

    /* Restore the interrupt enable register to it's previous value such
     * that the critical region is exited
     */
    XIo_Out8(InstancePtr->BaseAddress + XUN_IER_OFFSET, IerRegister);

    return ReceivedCount;
}

/****************************************************************************/
/**
*
* This function sends a buffer that has been previously specified by setting
* up the instance variables of the instance. This function is designed to be
* an internal function for the XUartNs550 component such that it may be called
* from a shell function that sets up the buffer or from an interrupt handler.
*
* This function sends the specified buffer of data to the UART in either
* polled or interrupt driven modes. This function is non-blocking such that
* it will return before the data has been sent by the UART.
*
* In a polled mode, this function will only send as much data as the UART can
* buffer, either in the transmitter or in the FIFO if present and enabled.
* The application may need to call it repeatedly to send a buffer.
*
* In interrupt mode, this function will start sending the specified buffer and
* then the interrupt handler of the driver will continue until the buffer
* has been sent. A callback function, as specified by the application, will
* be called to indicate the completion of sending the buffer.
*
* @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.
*
* @return
*
* NumBytes is the number of bytes actually sent (put into the UART tranmitter
* and/or FIFO).
*
* @note
*
* None.
*
*****************************************************************************/
unsigned int XUartNs550_SendBuffer(XUartNs550 *InstancePtr)
{
    unsigned int SentCount = 0;
    unsigned int BytesToSend = 0;   /* default to not send anything */
    unsigned int FifoSize;
    Xuint8 LsrRegister;
    Xuint8 IirRegister;
    Xuint8 IerRegister;

    /* Read the line status register to determine if the transmitter is
     * empty
     */
    LsrRegister = XIo_In8(InstancePtr->BaseAddress + XUN_LSR_OFFSET);

    /* If the transmitter is not empty then don't send any data, the empty
     * room in the FIFO is not available
     */
    if (LsrRegister & XUN_LSR_TX_BUFFER_EMPTY)
    {
        /*
         * Read the interrupt ID register to determine if FIFOs are enabled,
         */
        IirRegister = XIo_In8(InstancePtr->BaseAddress + XUN_IIR_OFFSET);

        /* When there are FIFOs, send up to the FIFO size. When there are
         * no FIFOs, only send 1 byte of data.
         */
        if (IirRegister & XUN_INT_ID_FIFOS_ENABLED)
        {
            /* Determine how many bytes can be sent depending on if the
             * transmitter is empty, a FIFO size of N is really N - 1 plus
             * the transmitter register
             */
            if (LsrRegister & XUN_LSR_TX_EMPTY)
            {
                FifoSize = XUN_FIFO_SIZE;
            }
            else
            {
                FifoSize = XUN_FIFO_SIZE - 1;
            }
            /* FIFOs are enabled, if the number of bytes to send is less than
             * the size of the FIFO, then send all bytes, otherwise fill the
             * FIFO
             */
            if (InstancePtr->SendBuffer.RemainingBytes < FifoSize)
            {
                BytesToSend = InstancePtr->SendBuffer.RemainingBytes;
            }
            else
            {
                BytesToSend = FifoSize;
            }
        }
        else if (InstancePtr->SendBuffer.RemainingBytes > 0)
        {
            /*
             * Without FIFOs, we can only send 1 byte. We needed to check
             * for non-zero remaining bytes in case this routine was called
             * only to kick the transmitter and enable the UART interrupt.
             */
            BytesToSend = 1;
        }

        /*
         * Fill the FIFO if it's present or the transmitter only from the
         * the buffer that was specified
         */
        for (SentCount = 0; SentCount < BytesToSend; SentCount++)
        {
            XIo_Out8(InstancePtr->BaseAddress + XUN_THR_OFFSET,
                     InstancePtr->SendBuffer.NextBytePtr[SentCount]);
        }
    }
    /*
     * Update the buffer to reflect the bytes that were sent from it
     */
    InstancePtr->SendBuffer.NextBytePtr += SentCount;
    InstancePtr->SendBuffer.RemainingBytes -= SentCount;

    /*
     * Increment associated counters
     */
     InstancePtr->Stats.CharactersTransmitted += SentCount;

    /* If interrupts are enabled as indicated by the receive interrupt, then
     * enable the transmit interrupt, it is not enabled continuously because it
     * causes an interrupt whenever the FIFO is empty
     */
    IerRegister = XIo_In8(InstancePtr->BaseAddress + XUN_IER_OFFSET);
    if (IerRegister & XUN_IER_RX_DATA)
    {
        XIo_Out8(InstancePtr->BaseAddress + XUN_IER_OFFSET,
                 IerRegister | XUN_IER_TX_EMPTY);
    }
    /*
     * Return the number of bytes that were sent, althought they really were
     * only put into the FIFO, not completely sent yet
     */
    return SentCount;
}

/****************************************************************************/
/**
*
* This function receives a buffer that has been previously specified by setting
* up the instance variables of the instance. This function is designed to be
* an internal function for the XUartNs550 component such that it may be called
* from a shell function that sets up the buffer or from an interrupt handler.
*
* This function will attempt to receive a specified number of bytes of data
* from the UART and store it into the specified buffer. This function is
* designed for either polled or interrupt driven modes. It is non-blocking
* such that it will return if there is no data has already received by the
* UART.
*
* In a polled mode, this function will only receive as much data as the UART
* can buffer, either in the receiver or in the FIFO if present and enabled.
* The application may need to call it repeatedly to receive a buffer. Polled
* mode is the default mode of operation for the driver.
*
* In interrupt mode, this function will start receiving and then the interrupt
* handler of the driver will continue until the buffer has been received. A
* callback function, as specified by the application, will be called to indicate
* the completion of receiving the buffer or when any receive errors or timeouts
* occur. Interrupt mode must be enabled using the SetOptions function.
*
* @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.
*
* @return
*
* The number of bytes received.
*
* @note
*
* None.
*
*****************************************************************************/
unsigned int XUartNs550_ReceiveBuffer(XUartNs550 *InstancePtr)
{
    Xuint8 LsrRegister;
    unsigned int ReceivedCount = 0;

    /* Loop until there is not more data buffered by the UART or the specified
     * number of bytes is received
     */
    while (ReceivedCount < InstancePtr->ReceiveBuffer.RemainingBytes)
    {
        /* Read the Line Status Register to determine if there is any data in
         * the receiver/FIFO
         */
        LsrRegister = XIo_In8(InstancePtr->BaseAddress +
                  XUN_LSR_OFFSET);

        /* If there is a break condition then a zero data byte was put into
         * the receiver, just read it and dump it and update the stats
         */
        if (LsrRegister & XUN_LSR_BREAK_INT)
        {
            (void)XIo_In8(InstancePtr->BaseAddress + XUN_RBR_OFFSET);
            XUartNs550_mUpdateStats(InstancePtr, LsrRegister);
        }

        /* If there is data ready to be removed, then put the next byte
         * received into the specified buffer and update the stats to reflect
         * any receive errors for the byte
         */
        else if (LsrRegister & XUN_LSR_DATA_READY)
        {
            InstancePtr->ReceiveBuffer.NextBytePtr[ReceivedCount++] =
                XIo_In8(InstancePtr->BaseAddress + XUN_RBR_OFFSET);

            XUartNs550_mUpdateStats(InstancePtr, LsrRegister);
        }

        /* There's no more data buffered, so exit such that this function does
         * not block waiting for data
         */
        else
        {
            break;
        }
    }

    /* Update the receive buffer to reflect the number of bytes that was
     * received
     */
    InstancePtr->ReceiveBuffer.NextBytePtr += ReceivedCount;
    InstancePtr->ReceiveBuffer.RemainingBytes -= ReceivedCount;

    /*
     * Increment associated counters in the statistics
     */
    InstancePtr->Stats.CharactersReceived += ReceivedCount;

    return ReceivedCount;
}

/*****************************************************************************
*
* Sets the baud rate for the specified UART. Checks the input value for
* validity and also verifies that the requested rate can be configured to
* within the 3 percent error range for RS-232 communications. If the provided
* rate is not valid, the current setting is unchanged.
*
* This function is designed to be an internal function only used within the
* XUartNs550 component. It is necessary for initialization and for the user
* available function that sets the data format.
*
* @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.
* @param    BaudRate to be set in the hardware.
*
* @return
*
* - XST_SUCCESS if everything configures as expected
* - XST_UART_BAUD_ERROR if the requested rate is not available because
*       there was too much error due to the input clock
*
* @note
*
* None.
*
*****************************************************************************/
XStatus XUartNs550_SetBaudRate(XUartNs550 *InstancePtr, Xuint32 BaudRate)
{

    Xuint8 BaudLSB;
    Xuint8 BaudMSB;
    Xuint8 LcrRegister;
    Xuint32 Divisor;
    Xuint32 TargetRate;
    Xuint32 Error;
    Xuint32 PercentError;

    /*
     * Assert validates the input arguments
     */
    XASSERT_NONVOID(InstancePtr != XNULL);
    XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

    /*
     * Determine what the divisor should be to get the specified baud
     * rater based upon the input clock frequency and a baud clock prescaler
     * of 16
     */
    Divisor = InstancePtr->InputClockHz / (BaudRate * 16UL);

    /*
     * check for too much error between the baud rate that will be generated
     * using the divisor and the expected baud rate, integer division also
     * truncates always positive
     */
    TargetRate = Divisor * BaudRate * 16UL;
    Error = InstancePtr->InputClockHz - TargetRate;

    /*
     * Error has total error now compute the percentage multiplied by 100 to
     * avoid floating point calculations, should be less than 3% as per RS-232
     * spec
     */
    PercentError = (Error * 100UL) / InstancePtr->InputClockHz;
    if (PercentError > XUN_MAX_BAUD_ERROR_RATE)
    {
        return XST_UART_BAUD_ERROR;

    }

    /* Get the least significant and most significant bytes of the divisor
     * so they can be written to 2 byte registers
     */
    BaudLSB = Divisor & XUN_DIVISOR_BYTE_MASK;
    BaudMSB = (Divisor >> 8) & XUN_DIVISOR_BYTE_MASK;

    /* Save the baud rate in the instance so that the get baud rate function
     * won't have to calculate it from the divisor
     */
    InstancePtr->BaudRate = BaudRate;

    /* Get the line control register contents and set the divisor latch
     * access bit so the baud rate can be set
     */
    LcrRegister = XIo_In8(InstancePtr->BaseAddress + XUN_LCR_OFFSET);

    XIo_Out8(InstancePtr->BaseAddress + XUN_LCR_OFFSET,
             LcrRegister | XUN_LCR_DLAB);

    /*
     * Set the baud Divisors to set rate, the initial write of 0xFF is to keep
     * the divisor from being 0 which is not recommended as per the NS16550D
     * spec sheet
     */
    XIo_Out8(InstancePtr->BaseAddress + XUN_DRLS_OFFSET, 0xFF);
    XIo_Out8(InstancePtr->BaseAddress + XUN_DRLM_OFFSET, BaudMSB);
    XIo_Out8(InstancePtr->BaseAddress + XUN_DRLS_OFFSET, BaudLSB);

    /*
     * Clear the Divisor latch access bit, DLAB to allow nornal
     * operation and write to the line control register
     */
    XIo_Out8(InstancePtr->BaseAddress + XUN_LCR_OFFSET, LcrRegister);

    return XST_SUCCESS;
}

/****************************************************************************/
/**
*
* Looks up the device configuration based on the unique device ID. A table
* contains the configuration info for each device in the system.
*
* @param    DeviceId contains the ID of the device to look up the configuration
*           for.
*
* @return
*
* A pointer to the configuration found or XNULL if the specified device ID was
* not found.
*
* @note
*
* None.
*
******************************************************************************/
XUartNs550_Config *XUartNs550_LookupConfig(Xuint16 DeviceId)
{
    XUartNs550_Config *CfgPtr = XNULL;

    int i;

    for (i=0; i < XPAR_XUARTNS550_NUM_INSTANCES; i++)
    {
        if (XUartNs550_ConfigTable[i].DeviceId == DeviceId)
        {
            CfgPtr = &XUartNs550_ConfigTable[i];
            break;
        }
    }

    return CfgPtr;
}

/****************************************************************************/
/**
*
* This function is a stub handler that is the default handler such that if the
* application has not set the handler when interrupts are enabled, this
* function will be called. The function interface has to match the interface
* specified for a handler even though none of the arguments are used.
*
* @param    CallBackRef is unused by this function.
* @param    Event is unused by this function.
* @param    ByteCount is unused by this function.
*
* @return
*
* None.
*
* @note
*
* None.
*
*****************************************************************************/
static void XUartNs550_StubHandler(void *CallBackRef, Xuint32 Event,
                                   unsigned int ByteCount)
{
    /*
     * Assert occurs always since this is a stub and should never be called
     */

    XASSERT_VOID_ALWAYS();
}

