risc-v/mpfs: serial: add termios support and init device clocks
This commit is contained in:
parent
aa057e25f2
commit
7db3456824
@ -57,14 +57,6 @@
|
||||
#define MPFS_UART_RTO_OFFSET 0x004C /* UART Receiver time-out register */
|
||||
#define MPFS_UART_ADR_OFFSET 0x0050 /* UART Address register */
|
||||
|
||||
/* Register virtual addresses ***********************************************/
|
||||
|
||||
#define MPFS250_UART0_VADDR MPFS_UART0_BASE
|
||||
#define MPFS250_UART1_VADDR MPFS_UART1_BASE
|
||||
#define MPFS250_UART2_VADDR MPFS_UART2_BASE
|
||||
#define MPFS250_UART3_VADDR MPFS_UART3_BASE
|
||||
#define MPFS250_UART4_VADDR MPFS_UART4_BASE
|
||||
|
||||
/* Register bit field definitions *******************************************/
|
||||
|
||||
/* UART Receive Buffer Register */
|
||||
@ -89,7 +81,6 @@
|
||||
#define UART_IER_ETBEI (1 << 1) /* Bit 1: Enable Transmit Holding Register Empty Interrupt */
|
||||
#define UART_IER_ELSI (1 << 2) /* Bit 2: Enable Receiver Line Status Interrupt */
|
||||
#define UART_IER_EDSSI (1 << 3) /* Bit 3: Enable Modem Status Interrupt */
|
||||
#define UART_IER_PTIME (1 << 7) /* Bit 7: Programmable THRE Interrupt Mode Enable */
|
||||
#define UART_IER_ALLIE 0x0000008f
|
||||
|
||||
/* UART Interrupt Identity Register */
|
||||
|
@ -48,6 +48,8 @@
|
||||
# define MPFS_CONSOLE_BITS CONFIG_UART0_BITS
|
||||
# define MPFS_CONSOLE_PARITY CONFIG_UART0_PARITY
|
||||
# define MPFS_CONSOLE_2STOP CONFIG_UART0_2STOP
|
||||
# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_MMUART0
|
||||
# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_MMUART0
|
||||
# define HAVE_UART
|
||||
#elif defined(CONFIG_UART1_SERIAL_CONSOLE)
|
||||
# define MPFS_CONSOLE_BASE MPFS_UART1_BASE
|
||||
@ -55,6 +57,8 @@
|
||||
# define MPFS_CONSOLE_BITS CONFIG_UART1_BITS
|
||||
# define MPFS_CONSOLE_PARITY CONFIG_UART1_PARITY
|
||||
# define MPFS_CONSOLE_2STOP CONFIG_UART1_2STOP
|
||||
# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_MMUART1
|
||||
# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_MMUART1
|
||||
# define HAVE_UART
|
||||
#elif defined(CONFIG_UART2_SERIAL_CONSOLE)
|
||||
# define MPFS_CONSOLE_BASE MPFS_UART2_BASE
|
||||
@ -62,6 +66,8 @@
|
||||
# define MPFS_CONSOLE_BITS CONFIG_UART2_BITS
|
||||
# define MPFS_CONSOLE_PARITY CONFIG_UART2_PARITY
|
||||
# define MPFS_CONSOLE_2STOP CONFIG_UART2_2STOP
|
||||
# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_MMUART2
|
||||
# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_MMUART2
|
||||
# define HAVE_UART
|
||||
# elif defined(CONFIG_UART3_SERIAL_CONSOLE)
|
||||
# define MPFS_CONSOLE_BASE MPFS_UART3_BASE
|
||||
@ -69,6 +75,8 @@
|
||||
# define MPFS_CONSOLE_BITS CONFIG_UART3_BITS
|
||||
# define MPFS_CONSOLE_PARITY CONFIG_UART3_PARITY
|
||||
# define MPFS_CONSOLE_2STOP CONFIG_UART3_2STOP
|
||||
# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_MMUART3
|
||||
# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_MMUART3
|
||||
# define HAVE_UART
|
||||
# elif defined(CONFIG_UART4_SERIAL_CONSOLE)
|
||||
# define MPFS_CONSOLE_BASE MPFS_UART4_BASE
|
||||
@ -76,6 +84,8 @@
|
||||
# define MPFS_CONSOLE_BITS CONFIG_UART4BITS
|
||||
# define MPFS_CONSOLE_PARITY CONFIG_UART4_PARITY
|
||||
# define MPFS_CONSOLE_2STOP CONFIG_UART4_2STOP
|
||||
# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_MMUART4
|
||||
# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_MMUART4
|
||||
# define HAVE_UART
|
||||
# elif defined(HAVE_UART)
|
||||
# error "No CONFIG_UARTn_SERIAL_CONSOLE Setting"
|
||||
@ -178,14 +188,24 @@ void mpfs_lowsetup(void)
|
||||
|
||||
/* Enable and configure the selected console device */
|
||||
|
||||
/* REVISIT: bringup UART from reset and set clocking.
|
||||
* Currently done by HSS bootloader
|
||||
*/
|
||||
|
||||
#if defined(HAVE_SERIAL_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG)
|
||||
uint32_t lcr = 0;
|
||||
|
||||
lcr = 0;
|
||||
/* reset on */
|
||||
|
||||
modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET,
|
||||
0, MPFS_CONSOLE_RESETBIT);
|
||||
|
||||
/* reset off */
|
||||
|
||||
modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET,
|
||||
0, MPFS_CONSOLE_CLOCKBIT);
|
||||
|
||||
/* clock on */
|
||||
|
||||
modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET,
|
||||
MPFS_CONSOLE_RESETBIT, 0);
|
||||
|
||||
switch (MPFS_CONSOLE_BITS)
|
||||
{
|
||||
case 5:
|
||||
|
@ -35,17 +35,21 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
# include <termios.h>
|
||||
#endif
|
||||
|
||||
#include "riscv_arch.h"
|
||||
#include "riscv_internal.h"
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "mpfs.h"
|
||||
#include "mpfs_config.h"
|
||||
#include "mpfs_clockconfig.h"
|
||||
#include "riscv_arch.h"
|
||||
#include "riscv_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
@ -341,7 +345,7 @@ static uart_dev_t g_uart4port =
|
||||
},
|
||||
.xmit =
|
||||
{
|
||||
.size = CONFIG_UART3_TXBUFSIZE,
|
||||
.size = CONFIG_UART4_TXBUFSIZE,
|
||||
.buffer = g_uart4txbuffer,
|
||||
},
|
||||
.ops = &g_uart_ops,
|
||||
@ -417,6 +421,64 @@ static inline void up_enablebreaks(struct up_dev_s *priv, bool enable)
|
||||
up_serialout(priv, MPFS_UART_LCR_OFFSET, lcr);
|
||||
}
|
||||
|
||||
static void up_enable_uart(struct up_dev_s *priv, bool enable)
|
||||
{
|
||||
uint32_t clock_bit = 0;
|
||||
uint32_t reset_bit = 0;
|
||||
|
||||
switch (priv->uartbase)
|
||||
{
|
||||
case MPFS_UART0_BASE:
|
||||
clock_bit = SYSREG_SUBBLK_CLOCK_CR_MMUART0;
|
||||
reset_bit = SYSREG_SOFT_RESET_CR_MMUART0;
|
||||
break;
|
||||
case MPFS_UART1_BASE:
|
||||
clock_bit = SYSREG_SUBBLK_CLOCK_CR_MMUART1;
|
||||
reset_bit = SYSREG_SOFT_RESET_CR_MMUART1;
|
||||
break;
|
||||
case MPFS_UART2_BASE:
|
||||
clock_bit = SYSREG_SUBBLK_CLOCK_CR_MMUART2;
|
||||
reset_bit = SYSREG_SOFT_RESET_CR_MMUART2;
|
||||
break;
|
||||
case MPFS_UART3_BASE:
|
||||
clock_bit = SYSREG_SUBBLK_CLOCK_CR_MMUART3;
|
||||
reset_bit = SYSREG_SOFT_RESET_CR_MMUART3;
|
||||
break;
|
||||
case MPFS_UART4_BASE:
|
||||
clock_bit = SYSREG_SUBBLK_CLOCK_CR_MMUART4;
|
||||
reset_bit = SYSREG_SOFT_RESET_CR_MMUART4;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* reset on */
|
||||
|
||||
modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET,
|
||||
0, reset_bit);
|
||||
|
||||
if (enable)
|
||||
{
|
||||
/* reset off */
|
||||
|
||||
modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET,
|
||||
0, reset_bit);
|
||||
|
||||
/* clock on */
|
||||
|
||||
modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET,
|
||||
clock_bit, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clock off */
|
||||
|
||||
modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET,
|
||||
clock_bit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_config_baud_divisors
|
||||
*
|
||||
@ -465,46 +527,21 @@ static void up_config_baud_divisors(struct up_dev_s *priv, uint32_t baudrate)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_setup
|
||||
* Name: up_set_format
|
||||
*
|
||||
* Description:
|
||||
* Configure the UART baud, bits, parity, etc. This method is called the
|
||||
* first time that the serial port is opened.
|
||||
* Set the serial line format and speed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int up_setup(struct uart_dev_s *dev)
|
||||
{
|
||||
#ifndef CONFIG_SUPPRESS_UART_CONFIG
|
||||
static void up_set_format(struct uart_dev_s *dev)
|
||||
{
|
||||
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
|
||||
uint32_t lcr;
|
||||
|
||||
/* Clear fifos */
|
||||
|
||||
up_serialout(priv, MPFS_UART_FCR_OFFSET,
|
||||
(UART_FCR_RFIFOR | UART_FCR_XFIFOR));
|
||||
|
||||
/* set filter to minimum value */
|
||||
|
||||
up_serialout(priv, MPFS_UART_GFR_OFFSET, 0);
|
||||
|
||||
/* set default TX time guard */
|
||||
|
||||
up_serialout(priv, MPFS_UART_TTG_OFFSET, 0);
|
||||
|
||||
/* Set trigger */
|
||||
|
||||
up_serialout(priv, MPFS_UART_FCR_OFFSET,
|
||||
(UART_FCR_FIFOE | UART_FCR_RT_HALF));
|
||||
|
||||
/* Set up the IER */
|
||||
|
||||
priv->ier = up_serialin(priv, MPFS_UART_IER_OFFSET);
|
||||
uint32_t lcr = 0;
|
||||
|
||||
/* Set up the LCR */
|
||||
|
||||
lcr = 0;
|
||||
|
||||
switch (priv->bits)
|
||||
{
|
||||
case 5:
|
||||
@ -550,6 +587,49 @@ static int up_setup(struct uart_dev_s *dev)
|
||||
/* Clear DLAB */
|
||||
|
||||
up_serialout(priv, MPFS_UART_LCR_OFFSET, lcr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_setup
|
||||
*
|
||||
* Description:
|
||||
* Configure the UART baud, bits, parity, etc. This method is called the
|
||||
* first time that the serial port is opened.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int up_setup(struct uart_dev_s *dev)
|
||||
{
|
||||
#ifndef CONFIG_SUPPRESS_UART_CONFIG
|
||||
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
|
||||
|
||||
/* enable clock */
|
||||
|
||||
up_enable_uart(priv, true);
|
||||
|
||||
/* Disable interrupts */
|
||||
|
||||
priv->ier = 0;
|
||||
up_serialout(priv, MPFS_UART_IER_OFFSET, 0);
|
||||
up_serialout(priv, MPFS_UART_IEM_OFFSET, 0);
|
||||
|
||||
/* Clear fifos */
|
||||
|
||||
up_serialout(priv, MPFS_UART_FCR_OFFSET,
|
||||
(UART_FCR_RFIFOR | UART_FCR_XFIFOR));
|
||||
|
||||
/* set filter to minimum value */
|
||||
|
||||
up_serialout(priv, MPFS_UART_GFR_OFFSET, 0);
|
||||
|
||||
/* set default TX time guard */
|
||||
|
||||
up_serialout(priv, MPFS_UART_TTG_OFFSET, 0);
|
||||
|
||||
/* Configure the UART line format and speed. */
|
||||
|
||||
up_set_format(dev);
|
||||
|
||||
/* Configure the FIFOs */
|
||||
|
||||
@ -582,6 +662,8 @@ static void up_shutdown(struct uart_dev_s *dev)
|
||||
/* Disable interrupts */
|
||||
|
||||
up_disableuartint(priv, NULL);
|
||||
|
||||
up_enable_uart(priv, false);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -749,7 +831,108 @@ static int uart_interrupt(int irq, void *context, void *arg)
|
||||
|
||||
static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
return -ENOTTY;
|
||||
#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT)
|
||||
struct inode *inode = filep->f_inode;
|
||||
struct uart_dev_s *dev = inode->i_private;
|
||||
|
||||
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
|
||||
#endif
|
||||
|
||||
int ret = OK;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
|
||||
case TIOCSERGSTRUCT:
|
||||
{
|
||||
struct up_dev_s *user = (struct up_dev_s *)arg;
|
||||
if (!user)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(user, dev, sizeof(struct up_dev_s));
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
case TCGETS:
|
||||
{
|
||||
struct termios *termiosp = (struct termios *)arg;
|
||||
|
||||
if (!termiosp)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_OFLOWCONTROL
|
||||
#endif
|
||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||
#endif
|
||||
termiosp->c_cflag =
|
||||
((priv->parity != 0) ? PARENB : 0) |
|
||||
((priv->parity == 1) ? PARODD : 0) |
|
||||
((priv->stopbits2) ? CSTOPB : 0) |
|
||||
((priv->bits == 5) ? CS5 : 0) |
|
||||
((priv->bits == 6) ? CS6 : 0) |
|
||||
((priv->bits == 7) ? CS7 : 0) |
|
||||
((priv->bits == 8) ? CS8 : 0);
|
||||
|
||||
cfsetispeed(termiosp, priv->baud);
|
||||
}
|
||||
break;
|
||||
|
||||
case TCSETS:
|
||||
{
|
||||
struct termios *termiosp = (struct termios *)arg;
|
||||
|
||||
if (!termiosp)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (termiosp->c_cflag & PARENB)
|
||||
{
|
||||
priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->parity = 0;
|
||||
}
|
||||
|
||||
priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0;
|
||||
|
||||
priv->bits = (termiosp->c_cflag & CS5) ? 5 : 0;
|
||||
priv->bits = (termiosp->c_cflag & CS6) ? 6 : 0;
|
||||
priv->bits = (termiosp->c_cflag & CS7) ? 7 : 0;
|
||||
priv->bits = (termiosp->c_cflag & CS8) ? 8 : 0;
|
||||
|
||||
/* Note that only cfgetispeed is used because we have knowledge
|
||||
* that only one speed is supported.
|
||||
*/
|
||||
|
||||
priv->baud = cfgetispeed(termiosp);
|
||||
|
||||
/* Effect the changes immediately - note that we do not implement
|
||||
* TCSADRAIN / TCSAFLUSH
|
||||
*/
|
||||
|
||||
up_set_format(dev);
|
||||
}
|
||||
break;
|
||||
#endif /* CONFIG_SERIAL_TERMIOS */
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -869,7 +1052,7 @@ static void up_txint(struct uart_dev_s *dev, bool enable)
|
||||
* Name: up_txready
|
||||
*
|
||||
* Description:
|
||||
* Return true if the tranmsit data register is not full
|
||||
* Return true if the transmit data register is not full
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -883,7 +1066,7 @@ static bool up_txready(struct uart_dev_s *dev)
|
||||
* Name: up_txempty
|
||||
*
|
||||
* Description:
|
||||
* Return true if the tranmsit data register is empty
|
||||
* Return true if the transmit data register is empty
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -905,9 +1088,8 @@ static bool up_txempty(struct uart_dev_s *dev)
|
||||
* Description:
|
||||
* Performs the low level UART initialization early in debug so that the
|
||||
* serial console will be available during bootup. This must be called
|
||||
* before riscv_serialinit. NOTE: This function depends on GPIO pin
|
||||
* configuration performed in up_consoleinit() and main clock iniialization
|
||||
* performed in up_clkinitialize().
|
||||
* before riscv_serialinit. NOTE: This function depends on
|
||||
* main clock initialization performed in up_clkinitialize().
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user