2022-11-10 22:22:48 +08:00
|
|
|
|
/*
|
|
|
|
|
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
|
|
|
|
* All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
|
|
|
|
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
|
|
|
|
* either version 1.0 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
|
|
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
* See the Phytium Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* FilePath: fpl011_options.c
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* Date: 2021-11-02 14:53:42
|
2022-11-10 22:22:48 +08:00
|
|
|
|
* LastEditTime: 2022-02-18 09:06:45
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* Description: This file is for uart option setting
|
2022-11-10 22:22:48 +08:00
|
|
|
|
*
|
|
|
|
|
* Modify History:
|
|
|
|
|
* Ver Who Date Changes
|
|
|
|
|
* ----- ------ -------- --------------------------------------
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* 1.0 huanghe 2021/11/2 first commit
|
|
|
|
|
* 1.1 liushengming 2022/02/18 fix bug
|
2022-11-10 22:22:48 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***************************** Include Files *********************************/
|
|
|
|
|
|
|
|
|
|
#include "fpl011.h"
|
|
|
|
|
#include "fpl011_hw.h"
|
|
|
|
|
#include "ftypes.h"
|
|
|
|
|
|
|
|
|
|
/************************** Variable Definitions ****************************/
|
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
|
|
|
/**************************** Type Definitions *******************************/
|
|
|
|
|
/*
|
|
|
|
|
* The following data type is a map from an option to the offset in the
|
|
|
|
|
* register to which it belongs as well as its bit mask in that register.
|
|
|
|
|
*/
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
u32 option;
|
|
|
|
|
u32 register_offset;
|
|
|
|
|
u32 mask;
|
|
|
|
|
} Mapping;
|
|
|
|
|
|
|
|
|
|
static Mapping option_table[] =
|
|
|
|
|
{
|
|
|
|
|
{FPL011_OPTION_UARTEN, FPL011CR_OFFSET, FPL011CR_UARTEN},
|
|
|
|
|
{FPL011_OPTION_RXEN, FPL011CR_OFFSET, FPL011CR_RXE},
|
|
|
|
|
{FPL011_OPTION_TXEN, FPL011CR_OFFSET, FPL011CR_TXE},
|
|
|
|
|
{FPL011_OPTION_FIFOEN, FPL011LCR_H_OFFSET, FPL011LCR_H_FEN},
|
|
|
|
|
{FPL011_OPTION_RTS, FPL011CR_OFFSET, FPL011CR_RTS},
|
|
|
|
|
{FPL011_OPTION_DTR, FPL011CR_OFFSET, FPL011CR_DTR},
|
|
|
|
|
{FPL011_OPTION_RTSEN, FPL011CR_OFFSET, FPL011CR_RTSEN},
|
|
|
|
|
{FPL011_OPTION_CTSEN, FPL011CR_OFFSET, FPL011CR_CTSEN},
|
|
|
|
|
{FPL011_OPTION_TXDMAEN, FPL011DMACR_OFFSET, FPL011DMACR_TXDMAE},
|
|
|
|
|
{FPL011_OPTION_RXDMAEN, FPL011DMACR_OFFSET, FPL011DMACR_RXDMAE}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/***************** Macros (Inline Functions) Definitions *********************/
|
|
|
|
|
|
|
|
|
|
#define FUART_NUM_OPITIONS (sizeof(option_table) / sizeof(Mapping))
|
|
|
|
|
/************************** Function Prototypes ******************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPl011SetOptions
|
|
|
|
|
* @msg: 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.
|
|
|
|
|
* @param uart_p is a pointer to the uart instance.
|
|
|
|
|
* @param options contains the options to be set which are bit masks
|
|
|
|
|
* contained in the file FPl011_uart.h and named FUART_OPTION_*.
|
|
|
|
|
*/
|
|
|
|
|
void FPl011SetOptions(FPl011 *uart_p, u32 options)
|
|
|
|
|
{
|
|
|
|
|
u32 index;
|
|
|
|
|
u32 reg_value;
|
|
|
|
|
FASSERT(uart_p != NULL);
|
|
|
|
|
FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY);
|
|
|
|
|
|
|
|
|
|
for (index = 0; index < FUART_NUM_OPITIONS; index++)
|
|
|
|
|
{
|
|
|
|
|
reg_value = FUART_READREG32(uart_p->config.base_address, option_table[index].register_offset);
|
|
|
|
|
|
|
|
|
|
if ((options & option_table[index].option) != (u32)(0))
|
|
|
|
|
{
|
|
|
|
|
reg_value |= option_table[index].mask;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
reg_value &= ~option_table[index].mask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FUART_WRITEREG32(uart_p->config.base_address, option_table[index].register_offset, reg_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPl011SetSpecificOptions
|
|
|
|
|
* @msg: Sets the options for the specified driver instance.
|
|
|
|
|
* @param {FPl011} *uart_p is a pointer to the uart instance.
|
|
|
|
|
* @param {u32} options contains the options to be set which are bit masks
|
|
|
|
|
* contained in the file FPl011_uart.h and named FUART_OPTION_*.
|
|
|
|
|
*/
|
|
|
|
|
void FPl011SetSpecificOptions(FPl011 *uart_p, u32 options)
|
|
|
|
|
{
|
|
|
|
|
u32 index;
|
|
|
|
|
u32 reg_value;
|
|
|
|
|
FASSERT(uart_p != NULL);
|
|
|
|
|
|
|
|
|
|
for (index = 0; index < FUART_NUM_OPITIONS; index++)
|
|
|
|
|
{
|
|
|
|
|
if ((options & option_table[index].option) == (u32)(0))
|
2023-05-11 10:25:21 +08:00
|
|
|
|
{
|
2022-11-10 22:22:48 +08:00
|
|
|
|
continue;
|
2023-05-11 10:25:21 +08:00
|
|
|
|
}
|
2022-11-10 22:22:48 +08:00
|
|
|
|
reg_value = FUART_READREG32(uart_p->config.base_address, option_table[index].register_offset);
|
|
|
|
|
|
|
|
|
|
/* set specific options */
|
|
|
|
|
reg_value |= option_table[index].mask;
|
|
|
|
|
FUART_WRITEREG32(uart_p->config.base_address, option_table[index].register_offset, reg_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* @name: FPl011ClearSpecificOptions
|
2022-11-10 22:22:48 +08:00
|
|
|
|
* @msg: Clear the options for the specified driver instance.
|
|
|
|
|
* @param uart_p is a pointer to the uart instance.
|
|
|
|
|
* @param options contains the options to be set which are bit masks
|
|
|
|
|
* contained in the file FPl011_uart.h and named FUART_OPTION_*.
|
|
|
|
|
*/
|
|
|
|
|
void FPl011ClearSpecificOptions(FPl011 *uart_p, u32 options)
|
|
|
|
|
{
|
|
|
|
|
u32 index;
|
|
|
|
|
u32 reg_value;
|
|
|
|
|
FASSERT(uart_p != NULL);
|
|
|
|
|
|
|
|
|
|
for (index = 0; index < FUART_NUM_OPITIONS; index++)
|
|
|
|
|
{
|
|
|
|
|
if ((options & option_table[index].option) == (u32)(0))
|
2023-05-11 10:25:21 +08:00
|
|
|
|
{
|
2022-11-10 22:22:48 +08:00
|
|
|
|
continue;
|
2023-05-11 10:25:21 +08:00
|
|
|
|
}
|
2022-11-10 22:22:48 +08:00
|
|
|
|
reg_value = FUART_READREG32(uart_p->config.base_address, option_table[index].register_offset);
|
|
|
|
|
|
|
|
|
|
/* remove specific options */
|
|
|
|
|
reg_value &= ~option_table[index].mask;
|
|
|
|
|
FUART_WRITEREG32(uart_p->config.base_address, option_table[index].register_offset, reg_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPl011SetDataFormat
|
|
|
|
|
* @msg: Sets the data format for the specified UART.
|
|
|
|
|
* @param uart_p is a pointer to the uart instance.
|
|
|
|
|
* @param format_p is a pointer to a format structure that will
|
|
|
|
|
* contain the data format after this call completes.
|
|
|
|
|
* @return
|
|
|
|
|
* FT_SUCCESS if everything configured as expected
|
|
|
|
|
* FPL011_ERROR_PARAM if one of the parameters was not valid.
|
|
|
|
|
*/
|
|
|
|
|
FError FPl011SetDataFormat(FPl011 *uart_p, FPl011Format *format_p)
|
|
|
|
|
{
|
|
|
|
|
FError ret ;
|
|
|
|
|
u32 line_ctrl_reg ;
|
|
|
|
|
FPl011Config *config_p;
|
|
|
|
|
FASSERT(uart_p != NULL);
|
|
|
|
|
FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY);
|
|
|
|
|
FASSERT(format_p != NULL) ;
|
|
|
|
|
|
|
|
|
|
config_p = &uart_p->config;
|
|
|
|
|
|
|
|
|
|
if ((format_p->data_bits > ((u32)(FPL011_FORMAT_WORDLENGTH_8BIT))) ||
|
2023-05-11 10:25:21 +08:00
|
|
|
|
(format_p->parity > ((u32)(FPL011_FORMAT_PARITY_MASK))) ||
|
|
|
|
|
(format_p->stopbits > ((u32)(FPL011_FORMAT_PARITY_MASK)))
|
2022-11-10 22:22:48 +08:00
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
return FPL011_ERROR_PARAM ;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Try to set the baud rate and if it's not successful then
|
|
|
|
|
* don't continue altering the data format, this is done
|
|
|
|
|
* first to avoid the format from being altered when an
|
|
|
|
|
* error occurs
|
|
|
|
|
*/
|
|
|
|
|
ret = FPl011SetBaudRate(uart_p, format_p->baudrate) ;
|
|
|
|
|
if (ret != FT_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
line_ctrl_reg = FUART_READREG32(config_p->base_address, FPL011LCR_H_OFFSET);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set the length of data (8,7,6) by first clearing
|
|
|
|
|
* out the bits that control it in the register,
|
|
|
|
|
* then set the length in the register
|
|
|
|
|
*/
|
|
|
|
|
line_ctrl_reg &= ~(u32)FPL011LCR_H_WLEN ;
|
|
|
|
|
line_ctrl_reg |= (format_p->data_bits <<
|
|
|
|
|
FPL011LCR_H_WLEN_SHIFT);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set the number of stop bits in the mode register by
|
|
|
|
|
* first clearing out the bits that control it in the
|
|
|
|
|
* register, then set the number of stop bits in the
|
|
|
|
|
* register.
|
|
|
|
|
*/
|
|
|
|
|
line_ctrl_reg &= ~FPL011LCR_H_STP_MASK;
|
|
|
|
|
line_ctrl_reg |= (format_p->stopbits <<
|
|
|
|
|
FPL011LCR_H_STP_SHIFT);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set the parity by first clearing out the bits that
|
|
|
|
|
* control it in the register, then set the bits in
|
|
|
|
|
* the register, the default is no parity after
|
|
|
|
|
* clearing the register bits
|
|
|
|
|
*/
|
|
|
|
|
line_ctrl_reg &= ~FPL011LCR_H_PARITY_MASK;
|
|
|
|
|
line_ctrl_reg |= ((format_p->parity &
|
|
|
|
|
FPL011_FORMAT_EN_PARITY) <<
|
|
|
|
|
FPL011LCR_H_PARITY_SHIFT);
|
|
|
|
|
|
|
|
|
|
/* Even/Odd parity set */
|
|
|
|
|
line_ctrl_reg |= ((format_p->parity &
|
|
|
|
|
FPL011_FORMAT_EVEN_PARITY) <<
|
|
|
|
|
FPL011_FORMAT_EVEN_PARITY_SHIFT);
|
|
|
|
|
|
|
|
|
|
/* Stick parity enable/disable */
|
|
|
|
|
line_ctrl_reg |= ((format_p->parity &
|
|
|
|
|
FPL011_FORMAT_EN_STICK_PARITY) <<
|
|
|
|
|
FPL011_FORMAT_EN_STICK_PARITY_SHIFT);
|
|
|
|
|
|
|
|
|
|
/* Update the Line control register */
|
|
|
|
|
FUART_WRITEREG32(config_p->base_address, FPL011LCR_H_OFFSET, line_ctrl_reg) ;
|
|
|
|
|
|
|
|
|
|
return FT_SUCCESS ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPl011GetDataFormat
|
|
|
|
|
* @msg: Gets the data format for the specified UART.
|
|
|
|
|
* @param uart_p is a pointer to the uart instance.
|
|
|
|
|
* @param format_p is a pointer to a format structure that will
|
|
|
|
|
* contain the data format after this call completes.
|
|
|
|
|
*/
|
|
|
|
|
void FPl011GetDataFormat(FPl011 *uart_p, FPl011Format *format_p)
|
|
|
|
|
{
|
|
|
|
|
u32 line_ctrl_reg ;
|
|
|
|
|
FPl011Config *config_p;
|
|
|
|
|
/* Assert validates the input arguments */
|
|
|
|
|
FASSERT(uart_p != NULL);
|
|
|
|
|
FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY);
|
|
|
|
|
FASSERT(format_p != NULL) ;
|
|
|
|
|
|
|
|
|
|
config_p = &uart_p->config;
|
|
|
|
|
/*
|
|
|
|
|
* Get the baud rate from the instance, this is not retrieved from
|
|
|
|
|
* the hardware because it is only kept as a divisor such that it
|
|
|
|
|
* is more difficult to get back to the baud rate
|
|
|
|
|
*/
|
|
|
|
|
format_p->baudrate = uart_p->config.baudrate ;
|
|
|
|
|
|
|
|
|
|
line_ctrl_reg = FUART_READREG32(config_p->base_address, FPL011LCR_H_OFFSET);
|
|
|
|
|
|
|
|
|
|
/* Get the length of data (8,7,6,5) */
|
|
|
|
|
format_p->data_bits = ((line_ctrl_reg & FPL011LCR_H_WLEN) >> FPL011LCR_H_WLEN_SHIFT) ;
|
|
|
|
|
|
|
|
|
|
/* Get the number of stop bits */
|
|
|
|
|
format_p->stopbits = (u8)((line_ctrl_reg & FPL011LCR_H_STP_MASK) >> FPL011LCR_H_STP_SHIFT) ;
|
|
|
|
|
|
|
|
|
|
/* Determine what parity is */
|
|
|
|
|
format_p->parity = (u32)((line_ctrl_reg & (u32)FPL011LCR_H_PARITY_MASK) >> FPL011LCR_H_PARITY_SHIFT) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPl011SetTxFifoThreadHold
|
|
|
|
|
* @msg: This functions sets the Tx FIFO trigger level to the 'TriggerLevel'
|
|
|
|
|
* argument.
|
|
|
|
|
* @param uart_p is a pointer to the uart instance.
|
|
|
|
|
* @param trigger_level contains the trigger level to set. This is a value
|
|
|
|
|
* from 0-32 (FPL011IFLS_TXIFLSEL_1_8 - FPL011IFLS_TXIFLSEL_7_8)
|
|
|
|
|
*/
|
|
|
|
|
void FPl011SetTxFifoThreadHold(FPl011 *uart_p, u8 trigger_level)
|
|
|
|
|
{
|
|
|
|
|
u32 fifo_trig_reg;
|
|
|
|
|
FPl011Config *config_p;
|
|
|
|
|
FASSERT(uart_p != NULL);
|
|
|
|
|
FASSERT(trigger_level <= (u8)FPL011IFLS_TXIFLSEL_MASK) ;
|
|
|
|
|
FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY);
|
|
|
|
|
config_p = &uart_p->config;
|
|
|
|
|
|
|
|
|
|
trigger_level = trigger_level & (u8)FPL011IFLS_TXIFLSEL_MASK;
|
|
|
|
|
|
|
|
|
|
fifo_trig_reg = FUART_READREG32(config_p->base_address,
|
|
|
|
|
FPL011IFLS_OFFSET);
|
|
|
|
|
|
2023-05-11 10:25:21 +08:00
|
|
|
|
fifo_trig_reg &= ~(FPL011IFLS_TXIFLSEL_MASK);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
|
|
|
|
|
fifo_trig_reg |= (u32)trigger_level;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Write the new value for the FIFO control register to it such that
|
|
|
|
|
* the threshold is changed
|
|
|
|
|
*/
|
|
|
|
|
FUART_WRITEREG32(config_p->base_address,
|
|
|
|
|
FPL011IFLS_OFFSET, fifo_trig_reg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPl011SetRxFifoThreadhold
|
|
|
|
|
* @msg: This functions sets the Rx FIFO trigger level to the 'TriggerLevel'
|
|
|
|
|
* argument.
|
|
|
|
|
* @param uart_p is a pointer to the uart instance.
|
|
|
|
|
* @param trigger_level contains the trigger level to set. This is a value
|
|
|
|
|
* from 0-32 (FPL011IFLS_RXIFLSEL_1_8 - FPL011IFLS_RXIFLSEL_7_8)
|
|
|
|
|
*/
|
|
|
|
|
void FPl011SetRxFifoThreadhold(FPl011 *uart_p, u8 trigger_level)
|
|
|
|
|
{
|
|
|
|
|
u32 fifo_trig_reg;
|
|
|
|
|
FPl011Config *config_p;
|
|
|
|
|
FASSERT(uart_p != NULL);
|
|
|
|
|
FASSERT(trigger_level <= (u8)FPL011IFLS_RXIFLSEL_MASK) ;
|
|
|
|
|
FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY);
|
|
|
|
|
config_p = &uart_p->config;
|
|
|
|
|
|
|
|
|
|
trigger_level = trigger_level & (u8)FPL011IFLS_RXIFLSEL_MASK;
|
|
|
|
|
|
|
|
|
|
fifo_trig_reg = FUART_READREG32(config_p->base_address,
|
|
|
|
|
FPL011IFLS_OFFSET);
|
|
|
|
|
|
|
|
|
|
fifo_trig_reg &= ~FPL011IFLS_RXIFLSEL_MASK;
|
|
|
|
|
|
|
|
|
|
fifo_trig_reg |= (u32)trigger_level ;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Write the new value for the FIFO control register to it such that
|
|
|
|
|
* the threshold is changed
|
|
|
|
|
*/
|
|
|
|
|
FUART_WRITEREG32(config_p->base_address,
|
|
|
|
|
FPL011IFLS_OFFSET, fifo_trig_reg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPl011SetBaudRate
|
|
|
|
|
* @msg: Sets the baud rate for the device.
|
|
|
|
|
* @param uart_p is a pointer to the FPl011 instance
|
|
|
|
|
* @param BaudRate to be set
|
|
|
|
|
* @return
|
|
|
|
|
* FT_SUCCESS if everything configured as expected
|
|
|
|
|
* FPL011_ERROR_PARAM if the requested rate is not available
|
|
|
|
|
* because there was too much error
|
|
|
|
|
*/
|
|
|
|
|
FError FPl011SetBaudRate(FPl011 *uart_p, u32 baudrate)
|
|
|
|
|
{
|
|
|
|
|
u32 temp;
|
|
|
|
|
u32 divider;
|
|
|
|
|
u32 remainder;
|
|
|
|
|
u32 fraction;
|
|
|
|
|
|
|
|
|
|
FASSERT(NULL != uart_p);
|
|
|
|
|
if ((baudrate * 2) > uart_p->config.ref_clock_hz)
|
|
|
|
|
{
|
|
|
|
|
return FPL011_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* calculate baud rate divisor */
|
|
|
|
|
temp = 16 * baudrate;
|
|
|
|
|
divider = uart_p->config.ref_clock_hz / temp;
|
|
|
|
|
remainder = uart_p->config.ref_clock_hz % temp;
|
|
|
|
|
temp = (128 * remainder) / temp;
|
|
|
|
|
fraction = temp / 2;
|
|
|
|
|
|
|
|
|
|
if (0 != (temp & 1))
|
|
|
|
|
{
|
|
|
|
|
fraction++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FPl011ClearSpecificOptions(uart_p, FPL011_OPTION_RXEN | FPL011_OPTION_TXEN);
|
|
|
|
|
/* set baud register */
|
|
|
|
|
FUART_WRITEREG32(uart_p->config.base_address, FPL011IBRD_OFFSET, divider);
|
|
|
|
|
FUART_WRITEREG32(uart_p->config.base_address, FPL011FBRD_OFFSET, fraction);
|
|
|
|
|
FPl011SetSpecificOptions(uart_p, FPL011_OPTION_RXEN | FPL011_OPTION_TXEN);
|
|
|
|
|
uart_p->config.baudrate = baudrate;
|
|
|
|
|
return FT_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPl011ProgramCtlReg
|
|
|
|
|
* @msg: This function reprograms the control register according to the following
|
|
|
|
|
* sequence mentioned in the TRM
|
|
|
|
|
* @param uart_p is a pointer to the FPl011 instance
|
|
|
|
|
* @param ctrl_reg value to be written
|
|
|
|
|
*/
|
|
|
|
|
void FPl011ProgramCtlReg(FPl011 *uart_p, u32 ctrl_reg)
|
|
|
|
|
{
|
|
|
|
|
u32 line_ctrl_reg;
|
|
|
|
|
u32 temp_ctrl_reg;
|
|
|
|
|
u32 isbusy;
|
|
|
|
|
u32 addr = uart_p->config.base_address;
|
|
|
|
|
FASSERT(uart_p);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check is TX completed. If Uart is disabled in the middle, cannot
|
|
|
|
|
* recover. So, keep this check before disable.
|
|
|
|
|
*/
|
|
|
|
|
isbusy = FUART_ISTRANSMITBUSY(addr);
|
|
|
|
|
while (isbusy == (u32)TRUE)
|
|
|
|
|
{
|
|
|
|
|
isbusy = (u32)FUART_ISTRANSMITBUSY(addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Disable UART */
|
|
|
|
|
temp_ctrl_reg = FUART_READREG32(addr, FPL011CR_OFFSET);
|
|
|
|
|
temp_ctrl_reg &= (~FPL011CR_UARTEN);
|
|
|
|
|
FUART_WRITEREG32(addr, FPL011CR_OFFSET, temp_ctrl_reg);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Flush the transmit FIFO by setting the FEN bit to 0 in the
|
|
|
|
|
* Line Control Register
|
|
|
|
|
*/
|
|
|
|
|
line_ctrl_reg = FUART_READREG32(addr, FPL011LCR_H_OFFSET);
|
|
|
|
|
line_ctrl_reg &= ~FPL011LCR_H_FEN;
|
|
|
|
|
FUART_WRITEREG32(addr, FPL011LCR_H_OFFSET, line_ctrl_reg);
|
|
|
|
|
|
|
|
|
|
/* Setup the Control Register with the passed argument.*/
|
|
|
|
|
FUART_WRITEREG32(addr, FPL011CR_OFFSET, ctrl_reg);
|
|
|
|
|
|
|
|
|
|
/* By default, driver works in FIFO mode, so set FEN as it is
|
|
|
|
|
* cleared above
|
|
|
|
|
*/
|
|
|
|
|
line_ctrl_reg |= FPL011LCR_H_FEN;
|
|
|
|
|
FUART_WRITEREG32(addr, FPL011LCR_H_OFFSET, line_ctrl_reg);
|
|
|
|
|
|
|
|
|
|
/* Enable UART */
|
|
|
|
|
temp_ctrl_reg = FUART_READREG32(addr, FPL011CR_OFFSET);
|
|
|
|
|
temp_ctrl_reg |= FPL011CR_UARTEN;
|
|
|
|
|
FUART_WRITEREG32(addr, FPL011CR_OFFSET, temp_ctrl_reg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPl011SetOperMode
|
|
|
|
|
* @msg: This function sets the operational mode of the UART. The UART can operate
|
|
|
|
|
* in one of four modes: Normal, Local Loopback.
|
|
|
|
|
* @param uart_p is a pointer to the FPl011 instance.
|
|
|
|
|
* @param operation_mode is the mode of the UART.
|
|
|
|
|
*/
|
|
|
|
|
void FPl011SetOperMode(FPl011 *uart_p, u8 operation_mode)
|
|
|
|
|
{
|
|
|
|
|
u32 ctrl_reg;
|
|
|
|
|
FPl011Config *config_p;
|
|
|
|
|
FASSERT(uart_p != NULL);
|
|
|
|
|
FASSERT(operation_mode <= (u8)FPL011_OPER_MODE_LOCAL_LOOP) ;
|
|
|
|
|
FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY);
|
|
|
|
|
config_p = &uart_p->config;
|
|
|
|
|
|
|
|
|
|
ctrl_reg = FUART_READREG32(config_p->base_address, FPL011CR_OFFSET) ;
|
|
|
|
|
|
|
|
|
|
/* Set the correct value by masking the bits, then ORing the const. */
|
|
|
|
|
ctrl_reg &= ~(u32)FPL011CR_LBE;
|
|
|
|
|
|
|
|
|
|
switch (operation_mode)
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
case FPL011_OPER_MODE_NORMAL:
|
|
|
|
|
ctrl_reg |= FPL011CR_MODE_NORMAL;
|
|
|
|
|
break;
|
|
|
|
|
case FPL011_OPER_MODE_LOCAL_LOOP:
|
|
|
|
|
ctrl_reg |= FPL011CR_LBE;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Setup the Control Register with the passed argument.*/
|
|
|
|
|
FPl011ProgramCtlReg(uart_p, ctrl_reg);
|
|
|
|
|
}
|