embeddedsw/XilinxProcessorIPLib/drivers/uartns550/src/xuartns550_options.c
Jagannadha Sutradharudu Teki 2c8f92039d embeddesw: Add initial code support
Added initial support Xilinx Embedded Software.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
2014-06-24 16:45:01 +05:30

525 lines
17 KiB
C
Executable file

/******************************************************************************
*
* Copyright (C) 2002 - 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 THE
* XILINX CONSORTIUM 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 xuartns550_options.c
*
* The implementation of the options functions for the XUartNs550 driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00b jhl 03/11/02 Repartitioned driver for smaller files.
* 1.00b rpm 04/12/05 Added critical section protection in ReadFcrRegister
* 1.11a sv 03/20/07 Updated to use the new coding guidelines.
* 1.13a sdm 07/10/09 Added receive line interrupt option to OptionsTable[].
* 2.00a sdm 09/22/09 Converted all register accesses to 32 bit access.
* 2.00a ktn 10/20/09 Converted all register accesses to 32 bit access.
* Updated to use HAL Processor APIs. _m is removed from the
* name of all the macro definitions.
* </pre>
*
*****************************************************************************/
/***************************** Include Files ********************************/
#include "xuartns550.h"
#include "xuartns550_i.h"
#include "xil_io.h"
/************************** Constant Definitions ****************************/
/**************************** Type Definitions ******************************/
/***************** Macros (Inline Functions) Definitions ********************/
/************************** Variable Definitions ****************************/
/*
* The following data type maps an option to a register and the bits of the
* regiser such that getting and setting the options may be table driven.
*/
typedef struct {
u16 Option;
u16 RegisterOffset;
u8 Mask;
} Mapping;
/*
* Create the table which contains options which are to be processed to get/set
* the options. These options are table driven to allow easy maintenance and
* expansion of the options.
*/
static Mapping OptionsTable[] = {
{ XUN_OPTION_SET_BREAK, XUN_LCR_OFFSET, XUN_LCR_SET_BREAK },
{ XUN_OPTION_LOOPBACK, XUN_MCR_OFFSET, XUN_MCR_LOOP },
{ XUN_OPTION_DATA_INTR, XUN_IER_OFFSET, XUN_IER_RX_DATA },
{ XUN_OPTION_MODEM_INTR, XUN_IER_OFFSET, XUN_IER_MODEM_STATUS },
{ XUN_OPTION_FIFOS_ENABLE, XUN_FCR_OFFSET, XUN_FIFO_ENABLE },
{ XUN_OPTION_RESET_TX_FIFO, XUN_FCR_OFFSET, XUN_FIFO_TX_RESET },
{ XUN_OPTION_RESET_RX_FIFO, XUN_FCR_OFFSET, XUN_FIFO_RX_RESET },
{ XUN_OPTION_ASSERT_OUT2, XUN_MCR_OFFSET, XUN_MCR_OUT_2 },
{ XUN_OPTION_ASSERT_OUT1, XUN_MCR_OFFSET, XUN_MCR_OUT_1 },
{ XUN_OPTION_ASSERT_RTS, XUN_MCR_OFFSET, XUN_MCR_RTS },
{ XUN_OPTION_ASSERT_DTR, XUN_MCR_OFFSET, XUN_MCR_DTR },
{ XUN_OPTION_RXLINE_INTR, XUN_IER_OFFSET, XUN_IER_RX_LINE }
};
/* Create a constants for the number of entries in the table */
#define XUN_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(Mapping))
/************************** Function Prototypes *****************************/
static u32 ReadFcrRegister(u32 BaseAddress);
/****************************************************************************/
/**
*
* Gets the options for the specified driver instance. The options are
* implemented as bit masks such that multiple options may be enabled or
* disabled simulataneously.
*
* @param InstancePtr is a pointer to the XUartNs550 instance.
*
* @return The current options for the UART. The optionss are bit masks
* that are contained in the file xuartns550.h and
* named XUN_OPTION_*.
*
* @note None.
*
*****************************************************************************/
u16 XUartNs550_GetOptions(XUartNs550 *InstancePtr)
{
u16 Options = 0;
u32 Register;
u32 Index;
/*
* Assert validates the input arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Loop thru the options table to map the physical options in the
* registers of the UART to the logical options to be returned
*/
for (Index = 0; Index < XUN_NUM_OPTIONS; Index++) {
/*
* If the FIFO control register is being read, the make sure to
* setup the line control register so it can be read
*/
if (OptionsTable[Index].RegisterOffset == XUN_FCR_OFFSET) {
Register = ReadFcrRegister(InstancePtr->BaseAddress);
} else {
Register = XUartNs550_ReadReg(InstancePtr->BaseAddress,
OptionsTable[Index].RegisterOffset);
}
/*
* If the bit in the register which correlates to the option
* is set, then set the corresponding bit in the options,
* ignoring any bits which are zero since the options variable
* is initialized to zero
*/
if (Register & OptionsTable[Index].Mask) {
Options |= OptionsTable[Index].Option;
}
}
return Options;
}
/****************************************************************************/
/**
*
* Sets the options for the specified driver instance. The options are
* implemented as bit masks such that multiple options may be enabled or
* disabled simultaneously.
*
* The GetOptions function may be called to retrieve the currently enabled
* options. The result is ORed in the desired new settings to be enabled and
* ANDed with the inverse to clear the settings to be disabled. The resulting
* value is then used as the options for the SetOption function call.
*
* @param InstancePtr is a pointer to the XUartNs550 instance.
* @param Options contains the options to be set which are bit masks
* contained in the file xuartns550.h and named XUN_OPTION_*.
*
* @return
* - XST_SUCCESS if the options were set successfully.
* - XST_UART_CONFIG_ERROR if the options could not be set because
* the hardware does not support FIFOs
*
* @note None.
*
*****************************************************************************/
int XUartNs550_SetOptions(XUartNs550 *InstancePtr, u16 Options)
{
u32 Index;
u32 Register;
/*
* Assert validates the input arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Loop thru the options table to map the logical options to the
* physical options in the registers of the UART
*/
for (Index = 0; Index < XUN_NUM_OPTIONS; Index++) {
/*
* If the FIFO control register is being read, this is a
* special case that requires special register processing
*/
if (OptionsTable[Index].RegisterOffset == XUN_FCR_OFFSET) {
Register = ReadFcrRegister(InstancePtr->BaseAddress);
} else {
/*
* Read the register which contains option so that the
* register can be changed without destoying any other
* bits of the register
*/
Register = XUartNs550_ReadReg(InstancePtr->BaseAddress,
OptionsTable[Index].RegisterOffset);
}
/*
* If the option is set in the input, then set the
* corresponding bit in the specified register, otherwise
* clear the bit in the register
*/
if (Options & OptionsTable[Index].Option) {
Register |= OptionsTable[Index].Mask;
} else {
Register &= ~OptionsTable[Index].Mask;
}
/*
* Write the new value to the register to set the option
*/
XUartNs550_WriteReg(InstancePtr->BaseAddress,
OptionsTable[Index].RegisterOffset, Register);
}
/* To be done, add error checks for enabling/resetting FIFOs */
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* This function gets the receive FIFO trigger level. The receive trigger
* level indicates the number of bytes in the receive FIFO that cause a receive
* data event (interrupt) to be generated.
*
* @param InstancePtr is a pointer to the XUartNs550 instance.
*
* @return The current receive FIFO trigger level. Constants which
* define each trigger level are contained in the file
* xuartns550.h and named XUN_FIFO_TRIGGER_*.
*
* @note None.
*
*****************************************************************************/
u8 XUartNs550_GetFifoThreshold(XUartNs550 *InstancePtr)
{
u32 FcrRegister;
/*
* Assert validates the input arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Read the value of the FIFO control register so that the threshold
* can be retrieved, this read takes special register processing
*/
FcrRegister = ReadFcrRegister(InstancePtr->BaseAddress);
/*
* Return only the trigger level from the register value
*/
return (u8)(FcrRegister & XUN_FIFO_RX_TRIGGER);
}
/****************************************************************************/
/**
*
* This functions sets the receive FIFO trigger level. The receive trigger
* level specifies the number of bytes in the receive FIFO that cause a receive
* data event (interrupt) to be generated. The FIFOs must be enabled to set the
* trigger level.
*
* @param InstancePtr is a pointer to the XUartNs550 instance.
* @param TriggerLevel contains the trigger level to set. Constants which
* define each trigger level are contained in the file xuartns550.h
* and named XUN_FIFO_TRIGGER_*.
*
* @return
* - XST_SUCCESS if the trigger level was set
* - XST_UART_CONFIG_ERROR if the trigger level could not be set,
* either the hardware does not support the FIFOs or FIFOs
* are not enabled
*
* @note None.
*
*****************************************************************************/
int XUartNs550_SetFifoThreshold(XUartNs550 *InstancePtr, u8 TriggerLevel)
{
u32 FcrRegister;
/*
* Assert validates the input arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid((TriggerLevel == XUN_FIFO_TRIGGER_14) ||
(TriggerLevel == XUN_FIFO_TRIGGER_08) ||
(TriggerLevel == XUN_FIFO_TRIGGER_04) ||
(TriggerLevel == XUN_FIFO_TRIGGER_01));
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Read the value of the FIFO control register, this read takes special
* register processing
*/
FcrRegister = ReadFcrRegister(InstancePtr->BaseAddress);
/*
* If the FIFO control register indicates that FIFOs are disabled, then
* either they are just disabled or it has no FIFOs, return an error
*/
if ((FcrRegister & XUN_FIFO_ENABLE) == 0) {
return XST_UART_CONFIG_ERROR;
}
/*
* Set the receive FIFO trigger level by clearing out the old level in
* the FIFO control register and writing in the new level
*/
FcrRegister &= ~XUN_FIFO_RX_TRIGGER;
FcrRegister |= (u32) TriggerLevel;
/*
* Write the new value for the FIFO control register to it such that the
* threshold is changed, writing to it is normal unlike reading from it
*/
XUartNs550_WriteReg(InstancePtr->BaseAddress,
XUN_FCR_OFFSET, FcrRegister);
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* This function returns the last errors that have occurred in the specified
* UART. It also clears the errors such that they cannot be retrieved again.
* The errors include parity error, receive overrun error, framing error, and
* break detection.
*
* The last errors is an accumulation of the errors each time an error is
* discovered in the driver. A status is checked for each received byte and
* this status is accumulated in the last errors.
*
* If this function is called after receiving a buffer of data, it will indicate
* any errors that occurred for the bytes of the buffer. It does not indicate
* which bytes contained errors.
*
* @param InstancePtr is a pointer to the XUartNs550 instance.
*
* @return The last errors that occurred. The errors are bit masks
* that are contained in the file xuartns550.h and
* named XUN_ERROR_*.
*
* @note None.
*
*****************************************************************************/
u8 XUartNs550_GetLastErrors(XUartNs550 *InstancePtr)
{
u8 Temp = InstancePtr->LastErrors;
/*
* Assert validates the input arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
/*
* Clear the last errors and return the previous value
*/
InstancePtr->LastErrors = 0;
/*
* Only return the bits that are reported errors which include
* receive overrun, framing, parity and break detection, the last errors
* variable holds an accumulation of the line status register bits which
* have been set
*/
return Temp & XUN_LSR_ERROR_BREAK;
}
/****************************************************************************/
/**
*
* This function gets the modem status from the specified UART. The modem
* status indicates any changes of the modem signals. This function allows
* the modem status to be read in a polled mode. The modem status is updated
* whenever it is read such that reading it twice may not yield the same
* results.
*
* @param InstancePtr is a pointer to the XUartNs550 instance .
*
* @return The modem status which are bit masks that are contained in
* the file xuartns550.h and named XUN_MODEM_*.
*
* @note
*
* The bit masks used for the modem status are the exact bits of the modem
* status register with no abstraction.
*
*****************************************************************************/
u8 XUartNs550_GetModemStatus(XUartNs550 *InstancePtr)
{
u32 ModemStatusRegister;
/*
* Assert validates the input arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
/*
* Read the modem status register to return
*/
ModemStatusRegister = XUartNs550_ReadReg(InstancePtr->BaseAddress,
XUN_MSR_OFFSET);
return (u8) ModemStatusRegister;
}
/****************************************************************************/
/**
*
* This function determines if the specified UART is sending data. If the
* transmitter register is not empty, it is sending data.
*
* @param InstancePtr is a pointer to the XUartNs550 instance.
*
* @return A value of TRUE if the UART is sending data, otherwise FALSE.
*
* @note None.
*
*****************************************************************************/
int XUartNs550_IsSending(XUartNs550 *InstancePtr)
{
u32 LsrRegister;
/*
* Assert validates the input arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
/*
* Read the line status register to determine if the transmitter is
* empty
*/
LsrRegister = XUartNs550_GetLineStatusReg(InstancePtr->BaseAddress);
/*
* If the transmitter is not empty then indicate that the UART is still
* sending some data
*/
return ((LsrRegister & XUN_LSR_TX_EMPTY) == 0);
}
/****************************************************************************/
/**
*
* This functions reads the FIFO control register. It's primary purpose is to
* isolate the special processing for reading this register. It is necessary
* to write to the line control register, then read the FIFO control register,
* and then restore the line control register.
*
* @param BaseAddress contains the base address of the registers in the
* device.
*
* @return The contents of the FIFO control register.
*
* @note None.
*
*****************************************************************************/
static u32 ReadFcrRegister(u32 BaseAddress)
{
u32 LcrRegister;
u32 FcrRegister;
u32 IerRegister;
/*
* Enter a critical section here by disabling Uart interrupts. We do
* not want to receive an interrupt while we have the FCR latched since
* the interrupt handler may want to read the IIR
*/
IerRegister = XUartNs550_ReadReg(BaseAddress, XUN_IER_OFFSET);
XUartNs550_WriteReg(BaseAddress, XUN_IER_OFFSET, 0);
/*
* Get the line control register contents and set the divisor latch
* access bit so the FIFO control register can be read, this can't
* be done with a true 16550, but is a feature in the Xilinx device
*/
LcrRegister = XUartNs550_GetLineControlReg(BaseAddress);
XUartNs550_SetLineControlReg(BaseAddress, LcrRegister | XUN_LCR_DLAB);
/*
* Read the FIFO control register so it can be returned
*/
FcrRegister = XUartNs550_ReadReg(BaseAddress, XUN_FCR_OFFSET);
/*
* Restore the line control register to it's original contents such
* that the DLAB bit is no longer set and return the register
*/
XUartNs550_SetLineControlReg(BaseAddress, LcrRegister);
/*
* Exit the critical section by restoring the IER
*/
XUartNs550_WriteReg(BaseAddress, XUN_IER_OFFSET, IerRegister);
return FcrRegister;
}