diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_uart.h b/arch/risc-v/src/mpfs/hardware/mpfs_uart.h index 2d3b0ccf91e..672a2f904a2 100755 --- a/arch/risc-v/src/mpfs/hardware/mpfs_uart.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_uart.h @@ -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 */ diff --git a/arch/risc-v/src/mpfs/mpfs_lowputc.c b/arch/risc-v/src/mpfs/mpfs_lowputc.c index a294e720298..fc27d074f8a 100755 --- a/arch/risc-v/src/mpfs/mpfs_lowputc.c +++ b/arch/risc-v/src/mpfs/mpfs_lowputc.c @@ -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: diff --git a/arch/risc-v/src/mpfs/mpfs_serial.c b/arch/risc-v/src/mpfs/mpfs_serial.c index 4bee2bc2616..1f337719825 100755 --- a/arch/risc-v/src/mpfs/mpfs_serial.c +++ b/arch/risc-v/src/mpfs/mpfs_serial.c @@ -35,17 +35,21 @@ #include #include +#include #include -#include +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif -#include "riscv_arch.h" -#include "riscv_internal.h" +#include #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(). * ****************************************************************************/