| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- /*
- * 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
- * Date: 2022-02-10 14:53:42
- * LastEditTime: 2022-02-18 09:06:45
- * Description: This files is for uart option setting
- *
- * Modify History:
- * Ver Who Date Changes
- * ----- ------ -------- --------------------------------------
- */
- /***************************** 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))
- continue;
- 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);
- }
- }
- /**
- * @name: FPl011SetSpecificOptions
- * @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))
- continue;
- 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))) ||
- (format_p->parity > ((u32)(FPL011_FORMAT_PARITY_MASK))) ||
- (format_p->stopbits > ((u32)(FPL011_FORMAT_PARITY_MASK)))
- )
- {
- 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);
- fifo_trig_reg &= ~(FPL011IFLS_TXIFLSEL_MASK | 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: 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)
- {
- case FPL011_OPER_MODE_NORMAL:
- ctrl_reg |= FPL011CR_MODE_NORMAL;
- break;
- case FPL011_OPER_MODE_LOCAL_LOOP:
- ctrl_reg |= FPL011CR_LBE;
- break;
- default:
- break;
- }
- /* Setup the Control Register with the passed argument.*/
- FPl011ProgramCtlReg(uart_p, ctrl_reg);
- }
|