acassis commented on code in PR #7443:
URL: https://github.com/apache/incubator-nuttx/pull/7443#discussion_r1006931732


##########
arch/sparc/src/s698pm/chip.h:
##########
@@ -0,0 +1,48 @@
+/****************************************************************************
+ * arch/sparc/src/s698pm/chip.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_SPARC_SRC_S698PM_CHIP_H
+#define __ARCH_SPARC_SRC_S698PM_CHIP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/* Include only the memory map.  Other chip hardware files should then
+ * include this file for the proper setup
+ */
+
+#include "s698pm-memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Define features for supported chip in the SPARC family */
+
+#if 1
+#else
+#  error "Unsupported SPARC chip"
+#endif

Review Comment:
   Which features? Maybe it could be removed for now.



##########
arch/sparc/src/s698pm/s698pm-irq.c:
##########
@@ -0,0 +1,533 @@
+/****************************************************************************
+ * arch/sparc/src/s698pm/s698pm-irq.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+
+#include <arch/irq.h>
+
+#include "up_internal.h"
+#include "s698pm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 7
+
+#if defined(CONFIG_SMP)
+#  define INTSTACK_ALLOC (CONFIG_SMP_NCPUS * INTSTACK_SIZE)
+#else
+#  define INTSTACK_ALLOC (INTSTACK_SIZE)
+#endif
+
+#endif
+
+/* IRQ to CPU and CPU interrupts mapping:
+ *
+ * Encoding: CCCIIIII
+ *  C: CPU that enabled the interrupt (0 ~ 3).
+ *  I: Associated CPU interrupt (0 ~ 31).
+ */
+
+#define IRQ_UNMAPPED      0xff
+#define IRQ_GETCPU(m)     (((m) & 0xe0) >> 0x05)
+#define IRQ_GETCPUINT(m)  ((m) & 0x1f)
+#define IRQ_MKMAP(c, i)   (((c) << 0x05) | (i))
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+static volatile uint8_t g_irqmap[NR_IRQS];
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 7
+/* In the SMP configuration, we will need custom interrupt stacks.
+ * These definitions provide the aligned stack allocations.
+ */
+
+static uint64_t g_intstack_alloc[INTSTACK_ALLOC >> 3];
+
+/* These definitions provide the "top" of the push-down stacks. */
+
+uintptr_t g_cpu_intstack_top[CONFIG_SMP_NCPUS] =
+{
+  (uintptr_t)g_intstack_alloc + INTSTACK_SIZE,
+#if defined(CONFIG_SMP)
+
+#if CONFIG_SMP_NCPUS > 1
+  (uintptr_t)g_intstack_alloc + (2 * INTSTACK_SIZE),
+#if CONFIG_SMP_NCPUS > 2
+  (uintptr_t)g_intstack_alloc + (3 * INTSTACK_SIZE),
+#if CONFIG_SMP_NCPUS > 3
+  (uintptr_t)g_intstack_alloc + (4 * INTSTACK_SIZE),
+#endif /* CONFIG_SMP_NCPUS > 3 */
+#endif /* CONFIG_SMP_NCPUS > 2 */
+#endif /* CONFIG_SMP_NCPUS > 1 */
+
+#endif /* defined(CONFIG_SMP) */
+};
+#endif /* if CONFIG_ARCH_INTERRUPTSTACK > 7 */
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#ifndef CONFIG_ARCH_IRQPRIO
+static int up_prioritize_irq(int irq, int priority);
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_irqinitialize
+ ****************************************************************************/
+
+void up_irqinitialize(void)
+{
+  int irq = 0;
+
+  for (irq = 0; irq < NR_IRQS; irq++)
+    {
+      g_irqmap[irq] = IRQ_UNMAPPED;
+    }
+
+  /* Initialize CPU interrupts */
+
+  s698pm_cpuint_initialize();
+
+  /* Set interrupts priority */
+
+  for (irq = 0x11; irq < 0x20; irq++)
+    {
+      /* Set all interrupts to the default (low) priority */
+
+      (void)up_prioritize_irq(irq, 0);
+    }
+
+  /* Attach software interrupts */
+
+  irq_attach(S698PM_IRQ_SW_SYSCALL_TA0, up_swint0, NULL);
+  irq_attach(S698PM_IRQ_SW_SYSCALL_TA8, up_swint1, NULL);
+
+  /* And finally, enable cpu interrupts */
+
+#ifndef CONFIG_SUPPRESS_INTERRUPTS
+  up_irq_enable();
+#endif
+}
+
+/****************************************************************************
+ * Name:  s698pm_cpuint_initialize
+ *
+ * Description:
+ *   Initialize CPU interrupts
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success; A negated errno value is returned on
+ *   any failure.
+ *
+ ****************************************************************************/
+
+int s698pm_cpuint_initialize(void)
+{
+  uintptr_t regaddr;
+  int cpu = 0;
+
+#ifdef CONFIG_SMP
+  /* Which CPU are we initializing */
+
+  cpu = up_cpu_index();
+  DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS);
+#endif
+
+  /* get Interrupt_Mask reg address of cpu */
+
+  regaddr = S698PM_IRQREG_P0_MASK + 4 * cpu;
+
+  /* Disable all CPU interrupts on this CPU */
+
+  putreg32(0, regaddr);
+
+#if defined CONFIG_SMP
+  /* Attach IPI interrupts */
+
+  irq_attach(S698PM_IPI_IRQ, s698pm_pause_handler, NULL);
+
+  (void)s698pm_setup_irq(cpu, S698PM_IPI_IRQ, 0);
+
+  /* And enable the IPI interrupt */
+
+  up_enable_irq(S698PM_IPI_IRQ);
+#endif
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name:  s698pm_setup_irq
+ *
+ * Description:
+ *   This function sets up the IRQ. It allocates a CPU interrupt of the given
+ *   priority andattaches it to the given irq.
+ *
+ * Input Parameters:
+ *   cpu      - The CPU to receive the interrupt 0~3
+ *   irq      - The irq number from irq.h to be assigned to a EXT interrupt.
+ *   priority - Interrupt's priority (0~1).
+ *
+ * Returned Value:
+ *   The allocated CPU interrupt on success, a negated errno value on
+ *   failure.
+ *
+ ****************************************************************************/
+
+int s698pm_setup_irq(int cpu, int irq, int priority)
+{
+  irqstate_t irqstate;
+  int cpuint;
+
+  irqstate = enter_critical_section();
+
+  if (irq >= S698PM_IRQ_FIRST_INT && irq <= S698PM_IRQ_LAST_INT)
+    {
+      cpuint = irq - S698PM_IRQ_FIRST_INT + 1;
+    }
+  else if (irq > S698PM_IRQ_LAST && irq < NR_IRQS)
+    {
+      cpuint = irq - 240;

Review Comment:
   What is 240? Please avoid hard-coded value that could be difficult to track 
later



##########
arch/sparc/src/s698pm/s698pm-serial.c:
##########
@@ -0,0 +1,1037 @@
+/****************************************************************************
+ * arch/sparc/src/s698pm/s698pm-serial.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#ifdef CONFIG_SERIAL_TERMIOS
+#  include <termios.h>
+#endif
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/serial/serial.h>
+#include <nuttx/spinlock.h>
+#include <arch/board/board.h>
+
+#include "up_internal.h"
+#include "s698pm-config.h"
+#include "chip.h"
+#include "s698pm-uart.h"
+#include "s698pm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* If we are not using the serial driver for the console, then we still must
+ * provide some minimal implementation of up_putc.
+ */
+
+#ifdef USE_SERIALDRIVER
+
+/* Which UART with be tty0/console and which tty1?  The console will always
+ * be ttyS0.  If there is no console then will use the lowest numbered UART.
+ */
+
+/* First pick the console and ttys0.  This could be any of UART1-4 */
+
+#if defined(CONFIG_UART1_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart1port /* UART1 is console */
+#    define TTYS0_DEV           g_uart1port /* UART1 is ttyS0 */
+#    define UART1_ASSIGNED      1
+#elif defined(CONFIG_UART2_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart2port /* UART2 is console */
+#    define TTYS0_DEV           g_uart2port /* UART2 is ttyS0 */
+#    define UART2_ASSIGNED      1
+#elif defined(CONFIG_UART3_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart3port /* UART3 is console */
+#    define TTYS0_DEV           g_uart3port /* UART3 is ttyS0 */
+#    define UART3_ASSIGNED      1
+#elif defined(CONFIG_UART4_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart4port /* UART4 is console */
+#    define TTYS0_DEV           g_uart4port /* UART4 is ttyS0 */
+#    define UART4_ASSIGNED      1
+#else
+#  undef CONSOLE_DEV                        /* No console */
+#  if defined(CONFIG_S698PM_UART1)
+#    define TTYS0_DEV           g_uart1port /* UART1 is ttyS0 */
+#    define UART1_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART2)
+#    define TTYS0_DEV           g_uart2port /* UART2 is ttyS0 */
+#    define UART2_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART3)
+#    define TTYS0_DEV           g_uart3port /* UART3 is ttyS0 */
+#    define UART3_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART4)
+#    define TTYS0_DEV           g_uart4port /* UART4 is ttyS0 */
+#    define UART4_ASSIGNED      1
+#  endif
+#endif
+
+/* Pick ttys1.  This could be any of UART1-4 excluding the console UART. */
+
+#if defined(CONFIG_S698PM_UART1) && !defined(UART1_ASSIGNED)
+#  define TTYS1_DEV           g_uart1port /* UART1 is ttyS1 */
+#  define UART1_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART2) && !defined(UART2_ASSIGNED)
+#  define TTYS1_DEV           g_uart2port /* UART2 is ttyS1 */
+#  define UART2_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS1_DEV           g_uart3port /* UART3 is ttyS1 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS1_DEV           g_uart4port /* UART4 is ttyS1 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Pick ttys2.  This could be one of UART2-4. It can't be UART1 because that
+ * was either assigned as ttyS0 or ttys1.  One of UART 1-4 could also be the
+ * console.
+ */
+
+#if defined(CONFIG_S698PM_UART2) && !defined(UART2_ASSIGNED)
+#  define TTYS2_DEV           g_uart2port /* UART2 is ttyS2 */
+#  define UART2_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS2_DEV           g_uart3port /* UART3 is ttyS2 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS2_DEV           g_uart4port /* UART4 is ttyS2 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Pick ttys3. This could be one of UART3-4. It can't be UART1-2 because
+ * those have already been assigned to ttsyS0, 1, or 2.  One of
+ * UART 2-4 could also be the console.
+ */
+
+#if defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS3_DEV           g_uart3port /* UART3 is ttyS3 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS3_DEV           g_uart4port /* UART4 is ttyS3 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Common initialization logic will not not know that the all of the UARTs
+ * have been disabled.  So, as a result, we may still have to provide
+ * stub implementations of up_earlyserialinit(), up_serialinit(), and
+ * up_putc().
+ */
+
+#ifdef HAVE_UART_DEVICE
+
+/* These values describe the set of enabled interrupts */
+
+#define RX_ENABLED(im)    (((im) & MSK_UART_ENABLE_RX) != 0)
+#define TX_ENABLED(im)    (((im) & MSK_UART_ENABLE_TX) != 0)
+
+#define ENABLE_RX(im)     do { (im) |= MSK_UART_ENABLE_RX; } while (0)
+#define ENABLE_TX(im)     do { (im) |= MSK_UART_ENABLE_TX; } while (0)
+
+#define DISABLE_RX(im)    do { (im) &= ~MSK_UART_ENABLE_RX; } while (0)
+#define DISABLE_TX(im)    do { (im) &= ~MSK_UART_ENABLE_TX; } while (0)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct up_dev_s
+{
+  uintptr_t uartbase;  /* Base address of UART registers */
+  uint32_t  baud;      /* Configured baud */
+  uint8_t   irq;       /* IRQ associated with this UART (for attachment) */
+  uint8_t   im;        /* Interrupt mask state */
+  uint8_t   parity;    /* 0=none, 1=odd, 2=even */
+  uint8_t   bits;      /* Number of bits (5, 6, 7 or 8) */
+  bool      stopbits2; /* true: Configure with 2 stop bits instead of 1 */
+  spinlock_t lock;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Low-level helpers */
+
+static inline uint32_t up_serialin(struct up_dev_s *priv, int offset);
+static inline void up_serialout(struct up_dev_s *priv, int offset,
+                                uint32_t value);
+static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im);
+static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im);
+
+/* Serial driver methods */
+
+static int  up_setup(struct uart_dev_s *dev);
+static void up_shutdown(struct uart_dev_s *dev);
+static int  up_attach(struct uart_dev_s *dev);
+static void up_detach(struct uart_dev_s *dev);
+static int  up_interrupt(int irq, void *context, void *arg);
+static int  up_ioctl(struct file *filep, int cmd, unsigned long arg);
+static int  up_receive(struct uart_dev_s *dev, uint32_t *status);
+static void up_rxint(struct uart_dev_s *dev, bool enable);
+static bool up_rxavailable(struct uart_dev_s *dev);
+static void up_send(struct uart_dev_s *dev, int ch);
+static void up_txint(struct uart_dev_s *dev, bool enable);
+static bool up_txready(struct uart_dev_s *dev);
+static bool up_txempty(struct uart_dev_s *dev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct uart_ops_s g_uart_ops =
+{
+  .setup          = up_setup,
+  .shutdown       = up_shutdown,
+  .attach         = up_attach,
+  .detach         = up_detach,
+  .ioctl          = up_ioctl,
+  .receive        = up_receive,
+  .rxint          = up_rxint,
+  .rxavailable    = up_rxavailable,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  .rxflowcontrol  = NULL,
+#endif
+  .send           = up_send,
+  .txint          = up_txint,
+  .txready        = up_txready,
+  .txempty        = up_txempty,
+};
+
+/* I/O buffers */
+
+#ifdef CONFIG_S698PM_UART1
+static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE];
+static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART2
+static char g_uart2rxbuffer[CONFIG_UART2_RXBUFSIZE];
+static char g_uart2txbuffer[CONFIG_UART2_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART3
+static char g_uart3rxbuffer[CONFIG_UART3_RXBUFSIZE];
+static char g_uart3txbuffer[CONFIG_UART3_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART4
+static char g_uart3rxbuffer[CONFIG_UART4_RXBUFSIZE];
+static char g_uart3txbuffer[CONFIG_UART4_TXBUFSIZE];
+#endif
+
+/* This describes the state of the S698PM UART1 port. */
+
+#ifdef CONFIG_S698PM_UART1
+static struct up_dev_s g_uart1priv =
+{
+  .uartbase  = S698PM_UART1_BASE,
+  .baud      = CONFIG_UART1_BAUD,
+  .irq       = S698PM_IRQ_UART_1_RX_TX,
+  .parity    = CONFIG_UART1_PARITY,
+  .bits      = CONFIG_UART1_BITS,
+  .stopbits2 = CONFIG_UART1_2STOP,
+};
+
+static uart_dev_t g_uart1port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART1_RXBUFSIZE,
+    .buffer  = g_uart1rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART1_TXBUFSIZE,
+    .buffer  = g_uart1txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart1priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART2 port. */
+
+#ifdef CONFIG_S698PM_UART2
+static struct up_dev_s g_uart2priv =
+{
+  .uartbase  = S698PM_UART2_BASE,
+  .baud      = CONFIG_UART2_BAUD,
+  .irq       = S698PM_IRQ_UART_2_RX_TX,
+  .parity    = CONFIG_UART2_PARITY,
+  .bits      = CONFIG_UART2_BITS,
+  .stopbits2 = CONFIG_UART2_2STOP,
+};
+
+static uart_dev_t g_uart2port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART2_RXBUFSIZE,
+    .buffer  = g_uart2rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART2_TXBUFSIZE,
+    .buffer  = g_uart2txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart2priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART3 port. */
+
+#ifdef CONFIG_S698PM_UART3
+static struct up_dev_s g_uart3priv =
+{
+  .uartbase  = S698PM_UART3_BASE,
+  .baud      = CONFIG_UART3_BAUD,
+  .irq       = S698PM_IRQ_UART_3_RX_TX,
+  .parity    = CONFIG_UART3_PARITY,
+  .bits      = CONFIG_UART3_BITS,
+  .stopbits2 = CONFIG_UART3_2STOP,
+};
+
+static uart_dev_t g_uart3port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART3_RXBUFSIZE,
+    .buffer  = g_uart3rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART3_TXBUFSIZE,
+    .buffer  = g_uart3txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart3priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART4 port. */
+
+#ifdef CONFIG_S698PM_UART4
+static struct up_dev_s g_uart4priv =
+{
+  .uartbase  = S698PM_UART4_BASE,
+  .baud      = CONFIG_UART4_BAUD,
+  .irq       = S698PM_IRQ_UART_4_RX_TX,
+  .parity    = CONFIG_UART4_PARITY,
+  .bits      = CONFIG_UART4_BITS,
+  .stopbits2 = CONFIG_UART4_2STOP,
+};
+
+static uart_dev_t g_uart4port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART4_RXBUFSIZE,
+    .buffer  = g_uart4rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART4_TXBUFSIZE,
+    .buffer  = g_uart4txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart4priv,
+};
+#endif
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_serialin
+ ****************************************************************************/
+
+static inline uint32_t up_serialin(struct up_dev_s *priv, int offset)
+{
+  return getreg32(priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_serialout
+ ****************************************************************************/
+
+static inline void up_serialout(struct up_dev_s *priv, int offset,
+                                uint32_t value)
+{
+  putreg32(value, priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_setuartint
+ ****************************************************************************/
+
+static inline void up_setuartint(struct up_dev_s *priv)
+{
+  uint8_t regval;
+
+  regval   = up_serialin(priv, S698PM_UART_CTRLREG_OFFSET);
+  regval  &= ~MSK_UART_ALLINTS;
+  regval  |= priv->im;
+  up_serialout(priv, S698PM_UART_CTRLREG_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: up_restoreuartint
+ ****************************************************************************/
+
+static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  irqstate_t flags;
+
+  /* Re-enable/re-disable interrupts corresponding to the state of bits
+   * in im
+   */
+
+  flags = spin_lock_irqsave(&priv->lock);
+  priv->im  &= ~MSK_UART_ALLINTS;
+  priv->im  |= im;
+  up_setuartint(priv);
+  spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/****************************************************************************
+ * Name: up_disableuartint
+ ****************************************************************************/
+
+static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&priv->lock);
+  if (im)
+    {
+      *im = priv->im;
+    }
+
+  /* Disable all interrupts */
+
+  DISABLE_RX(priv->im);
+  DISABLE_TX(priv->im);
+  up_setuartint(priv);
+  spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/****************************************************************************
+ * 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;
+
+  /* Configure the UART as an RS-232 UART */
+
+  s698pm_uartconfigure(priv->uartbase, priv->baud, priv->parity,
+                        priv->bits, priv->stopbits2);
+#endif
+
+#ifdef CONFIG_ARCH_IRQPRIO
+  /* Set up the interrupt priority */
+
+  up_prioritize_irq(priv->irq, priv->irqprio);
+#endif
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: up_shutdown
+ *
+ * Description:
+ *   Disable the UART.  This method is called when the serial
+ *   port is closed
+ *
+ ****************************************************************************/
+
+static void up_shutdown(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* Disable interrupts */
+
+  up_disableuartint(dev, NULL);
+
+  /* Reset hardware and disable Rx and Tx */
+
+  s698pm_uartreset(priv->uartbase);
+}
+
+/****************************************************************************
+ * Name: up_attach
+ *
+ * Description:
+ *   Configure the UART to operation in interrupt driven mode. This method is
+ *   called when the serial port is opened.  Normally, this is just after the
+ *   the setup() method is called, however, the serial console may operate in
+ *   a non-interrupt driven mode during the boot phase.
+ *
+ *   RX and TX interrupts are not enabled by the attach method (unless the
+ *   hardware supports multiple levels of interrupt enabling).  The RX and TX
+ *   interrupts are not enabled until the txint() and rxint() methods are
+ *   called.
+ *
+ ****************************************************************************/
+
+static int up_attach(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  int ret;
+
+  /* Attach and enable the IRQ */
+
+  ret = irq_attach(priv->irq, up_interrupt, dev);
+  if (ret == OK)
+    {
+      /* Set up to uart interrupts on the current CPU */
+
+       (void)s698pm_setup_irq(0, priv->irq, 0);
+
+      /* Enable the interrupt (RX and TX interrupts are still disabled
+       * in the USART
+       */
+
+       up_enable_irq(priv->irq);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: up_detach
+ *
+ * Description:
+ *   Detach UART interrupts.  This method is called when the serial port is
+ *   closed normally just before the shutdown method is called. The exception
+ *   is the serial console which is never shutdown.
+ *
+ ****************************************************************************/
+
+static void up_detach(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* Disable interrupts */
+
+  up_disableuartint(dev, NULL);
+
+  /* Detach from the interrupt */
+
+  irq_detach(priv->irq);
+}
+
+/****************************************************************************
+ * Name: up_interrupt
+ *
+ * Description:
+ *   This is the UART interrupt handler.  It will be invoked when an
+ *   interrupt received on the 'irq'  It should call uart_transmitchars or
+ *   uart_receivechar to perform the appropriate data transfers.  The
+ *   interrupt handling logic must be able to map the 'irq' number into the
+ *   approprite uart_dev_s structure in order to call these functions.
+ *
+ ****************************************************************************/
+
+static int up_interrupt(int irq, void *context, void *arg)
+{
+  struct uart_dev_s *dev = (struct uart_dev_s *)arg;
+  struct up_dev_s   *priv;
+  uint32_t           mis;
+  int                passes;
+  bool               handled;
+
+  DEBUGASSERT(dev != NULL && dev->priv != NULL);
+  priv = (struct up_dev_s *)dev->priv;
+
+  /* Loop until there are no characters to be transferred or,
+   * until we have been looping for a long time.
+   */
+
+  handled = true;
+  for (passes = 0; passes < 256 && handled; passes++)
+    {
+      handled = false;
+
+      /* Get the masked UART status and clear the pending interrupts. */
+
+       mis = up_serialin(priv, S698PM_UART_STATREG_OFFSET);
+
+      /* Handle incoming, receive bytes */
+
+      if ((mis & UART_STA_DR) != 0)
+        {
+      /* Rx buffer not empty ... process incoming bytes */
+
+           uart_recvchars(dev);
+           handled = true;
+        }
+
+      /* Handle outgoing, transmit bytes */
+
+      if ((mis & UART_STA_TF) != UART_STA_TF)
+        {
+      /* Tx FIFO not full ... process outgoing bytes */
+
+      /* if (dev->xmit.head != dev->xmit.tail)
+       * {
+       */
+
+           uart_xmitchars(dev);
+           handled = true;
+
+      /* } */

Review Comment:
   Please remove!



##########
arch/sparc/src/s698pm/s698pm-serial.c:
##########
@@ -0,0 +1,1037 @@
+/****************************************************************************
+ * arch/sparc/src/s698pm/s698pm-serial.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#ifdef CONFIG_SERIAL_TERMIOS
+#  include <termios.h>
+#endif
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/serial/serial.h>
+#include <nuttx/spinlock.h>
+#include <arch/board/board.h>
+
+#include "up_internal.h"
+#include "s698pm-config.h"
+#include "chip.h"
+#include "s698pm-uart.h"
+#include "s698pm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* If we are not using the serial driver for the console, then we still must
+ * provide some minimal implementation of up_putc.
+ */
+
+#ifdef USE_SERIALDRIVER
+
+/* Which UART with be tty0/console and which tty1?  The console will always
+ * be ttyS0.  If there is no console then will use the lowest numbered UART.
+ */
+
+/* First pick the console and ttys0.  This could be any of UART1-4 */
+
+#if defined(CONFIG_UART1_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart1port /* UART1 is console */
+#    define TTYS0_DEV           g_uart1port /* UART1 is ttyS0 */
+#    define UART1_ASSIGNED      1
+#elif defined(CONFIG_UART2_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart2port /* UART2 is console */
+#    define TTYS0_DEV           g_uart2port /* UART2 is ttyS0 */
+#    define UART2_ASSIGNED      1
+#elif defined(CONFIG_UART3_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart3port /* UART3 is console */
+#    define TTYS0_DEV           g_uart3port /* UART3 is ttyS0 */
+#    define UART3_ASSIGNED      1
+#elif defined(CONFIG_UART4_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart4port /* UART4 is console */
+#    define TTYS0_DEV           g_uart4port /* UART4 is ttyS0 */
+#    define UART4_ASSIGNED      1
+#else
+#  undef CONSOLE_DEV                        /* No console */
+#  if defined(CONFIG_S698PM_UART1)
+#    define TTYS0_DEV           g_uart1port /* UART1 is ttyS0 */
+#    define UART1_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART2)
+#    define TTYS0_DEV           g_uart2port /* UART2 is ttyS0 */
+#    define UART2_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART3)
+#    define TTYS0_DEV           g_uart3port /* UART3 is ttyS0 */
+#    define UART3_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART4)
+#    define TTYS0_DEV           g_uart4port /* UART4 is ttyS0 */
+#    define UART4_ASSIGNED      1
+#  endif
+#endif
+
+/* Pick ttys1.  This could be any of UART1-4 excluding the console UART. */
+
+#if defined(CONFIG_S698PM_UART1) && !defined(UART1_ASSIGNED)
+#  define TTYS1_DEV           g_uart1port /* UART1 is ttyS1 */
+#  define UART1_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART2) && !defined(UART2_ASSIGNED)
+#  define TTYS1_DEV           g_uart2port /* UART2 is ttyS1 */
+#  define UART2_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS1_DEV           g_uart3port /* UART3 is ttyS1 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS1_DEV           g_uart4port /* UART4 is ttyS1 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Pick ttys2.  This could be one of UART2-4. It can't be UART1 because that
+ * was either assigned as ttyS0 or ttys1.  One of UART 1-4 could also be the
+ * console.
+ */
+
+#if defined(CONFIG_S698PM_UART2) && !defined(UART2_ASSIGNED)
+#  define TTYS2_DEV           g_uart2port /* UART2 is ttyS2 */
+#  define UART2_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS2_DEV           g_uart3port /* UART3 is ttyS2 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS2_DEV           g_uart4port /* UART4 is ttyS2 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Pick ttys3. This could be one of UART3-4. It can't be UART1-2 because
+ * those have already been assigned to ttsyS0, 1, or 2.  One of
+ * UART 2-4 could also be the console.
+ */
+
+#if defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS3_DEV           g_uart3port /* UART3 is ttyS3 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS3_DEV           g_uart4port /* UART4 is ttyS3 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Common initialization logic will not not know that the all of the UARTs
+ * have been disabled.  So, as a result, we may still have to provide
+ * stub implementations of up_earlyserialinit(), up_serialinit(), and
+ * up_putc().
+ */
+
+#ifdef HAVE_UART_DEVICE
+
+/* These values describe the set of enabled interrupts */
+
+#define RX_ENABLED(im)    (((im) & MSK_UART_ENABLE_RX) != 0)
+#define TX_ENABLED(im)    (((im) & MSK_UART_ENABLE_TX) != 0)
+
+#define ENABLE_RX(im)     do { (im) |= MSK_UART_ENABLE_RX; } while (0)
+#define ENABLE_TX(im)     do { (im) |= MSK_UART_ENABLE_TX; } while (0)
+
+#define DISABLE_RX(im)    do { (im) &= ~MSK_UART_ENABLE_RX; } while (0)
+#define DISABLE_TX(im)    do { (im) &= ~MSK_UART_ENABLE_TX; } while (0)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct up_dev_s
+{
+  uintptr_t uartbase;  /* Base address of UART registers */
+  uint32_t  baud;      /* Configured baud */
+  uint8_t   irq;       /* IRQ associated with this UART (for attachment) */
+  uint8_t   im;        /* Interrupt mask state */
+  uint8_t   parity;    /* 0=none, 1=odd, 2=even */
+  uint8_t   bits;      /* Number of bits (5, 6, 7 or 8) */
+  bool      stopbits2; /* true: Configure with 2 stop bits instead of 1 */
+  spinlock_t lock;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Low-level helpers */
+
+static inline uint32_t up_serialin(struct up_dev_s *priv, int offset);
+static inline void up_serialout(struct up_dev_s *priv, int offset,
+                                uint32_t value);
+static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im);
+static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im);
+
+/* Serial driver methods */
+
+static int  up_setup(struct uart_dev_s *dev);
+static void up_shutdown(struct uart_dev_s *dev);
+static int  up_attach(struct uart_dev_s *dev);
+static void up_detach(struct uart_dev_s *dev);
+static int  up_interrupt(int irq, void *context, void *arg);
+static int  up_ioctl(struct file *filep, int cmd, unsigned long arg);
+static int  up_receive(struct uart_dev_s *dev, uint32_t *status);
+static void up_rxint(struct uart_dev_s *dev, bool enable);
+static bool up_rxavailable(struct uart_dev_s *dev);
+static void up_send(struct uart_dev_s *dev, int ch);
+static void up_txint(struct uart_dev_s *dev, bool enable);
+static bool up_txready(struct uart_dev_s *dev);
+static bool up_txempty(struct uart_dev_s *dev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct uart_ops_s g_uart_ops =
+{
+  .setup          = up_setup,
+  .shutdown       = up_shutdown,
+  .attach         = up_attach,
+  .detach         = up_detach,
+  .ioctl          = up_ioctl,
+  .receive        = up_receive,
+  .rxint          = up_rxint,
+  .rxavailable    = up_rxavailable,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  .rxflowcontrol  = NULL,
+#endif
+  .send           = up_send,
+  .txint          = up_txint,
+  .txready        = up_txready,
+  .txempty        = up_txempty,
+};
+
+/* I/O buffers */
+
+#ifdef CONFIG_S698PM_UART1
+static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE];
+static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART2
+static char g_uart2rxbuffer[CONFIG_UART2_RXBUFSIZE];
+static char g_uart2txbuffer[CONFIG_UART2_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART3
+static char g_uart3rxbuffer[CONFIG_UART3_RXBUFSIZE];
+static char g_uart3txbuffer[CONFIG_UART3_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART4
+static char g_uart3rxbuffer[CONFIG_UART4_RXBUFSIZE];
+static char g_uart3txbuffer[CONFIG_UART4_TXBUFSIZE];
+#endif
+
+/* This describes the state of the S698PM UART1 port. */
+
+#ifdef CONFIG_S698PM_UART1
+static struct up_dev_s g_uart1priv =
+{
+  .uartbase  = S698PM_UART1_BASE,
+  .baud      = CONFIG_UART1_BAUD,
+  .irq       = S698PM_IRQ_UART_1_RX_TX,
+  .parity    = CONFIG_UART1_PARITY,
+  .bits      = CONFIG_UART1_BITS,
+  .stopbits2 = CONFIG_UART1_2STOP,
+};
+
+static uart_dev_t g_uart1port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART1_RXBUFSIZE,
+    .buffer  = g_uart1rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART1_TXBUFSIZE,
+    .buffer  = g_uart1txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart1priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART2 port. */
+
+#ifdef CONFIG_S698PM_UART2
+static struct up_dev_s g_uart2priv =
+{
+  .uartbase  = S698PM_UART2_BASE,
+  .baud      = CONFIG_UART2_BAUD,
+  .irq       = S698PM_IRQ_UART_2_RX_TX,
+  .parity    = CONFIG_UART2_PARITY,
+  .bits      = CONFIG_UART2_BITS,
+  .stopbits2 = CONFIG_UART2_2STOP,
+};
+
+static uart_dev_t g_uart2port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART2_RXBUFSIZE,
+    .buffer  = g_uart2rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART2_TXBUFSIZE,
+    .buffer  = g_uart2txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart2priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART3 port. */
+
+#ifdef CONFIG_S698PM_UART3
+static struct up_dev_s g_uart3priv =
+{
+  .uartbase  = S698PM_UART3_BASE,
+  .baud      = CONFIG_UART3_BAUD,
+  .irq       = S698PM_IRQ_UART_3_RX_TX,
+  .parity    = CONFIG_UART3_PARITY,
+  .bits      = CONFIG_UART3_BITS,
+  .stopbits2 = CONFIG_UART3_2STOP,
+};
+
+static uart_dev_t g_uart3port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART3_RXBUFSIZE,
+    .buffer  = g_uart3rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART3_TXBUFSIZE,
+    .buffer  = g_uart3txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart3priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART4 port. */
+
+#ifdef CONFIG_S698PM_UART4
+static struct up_dev_s g_uart4priv =
+{
+  .uartbase  = S698PM_UART4_BASE,
+  .baud      = CONFIG_UART4_BAUD,
+  .irq       = S698PM_IRQ_UART_4_RX_TX,
+  .parity    = CONFIG_UART4_PARITY,
+  .bits      = CONFIG_UART4_BITS,
+  .stopbits2 = CONFIG_UART4_2STOP,
+};
+
+static uart_dev_t g_uart4port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART4_RXBUFSIZE,
+    .buffer  = g_uart4rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART4_TXBUFSIZE,
+    .buffer  = g_uart4txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart4priv,
+};
+#endif
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_serialin
+ ****************************************************************************/
+
+static inline uint32_t up_serialin(struct up_dev_s *priv, int offset)
+{
+  return getreg32(priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_serialout
+ ****************************************************************************/
+
+static inline void up_serialout(struct up_dev_s *priv, int offset,
+                                uint32_t value)
+{
+  putreg32(value, priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_setuartint
+ ****************************************************************************/
+
+static inline void up_setuartint(struct up_dev_s *priv)
+{
+  uint8_t regval;
+
+  regval   = up_serialin(priv, S698PM_UART_CTRLREG_OFFSET);
+  regval  &= ~MSK_UART_ALLINTS;
+  regval  |= priv->im;
+  up_serialout(priv, S698PM_UART_CTRLREG_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: up_restoreuartint
+ ****************************************************************************/
+
+static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  irqstate_t flags;
+
+  /* Re-enable/re-disable interrupts corresponding to the state of bits
+   * in im
+   */
+
+  flags = spin_lock_irqsave(&priv->lock);
+  priv->im  &= ~MSK_UART_ALLINTS;
+  priv->im  |= im;
+  up_setuartint(priv);
+  spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/****************************************************************************
+ * Name: up_disableuartint
+ ****************************************************************************/
+
+static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&priv->lock);
+  if (im)
+    {
+      *im = priv->im;
+    }
+
+  /* Disable all interrupts */
+
+  DISABLE_RX(priv->im);
+  DISABLE_TX(priv->im);
+  up_setuartint(priv);
+  spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/****************************************************************************
+ * 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;
+
+  /* Configure the UART as an RS-232 UART */
+
+  s698pm_uartconfigure(priv->uartbase, priv->baud, priv->parity,
+                        priv->bits, priv->stopbits2);
+#endif
+
+#ifdef CONFIG_ARCH_IRQPRIO
+  /* Set up the interrupt priority */
+
+  up_prioritize_irq(priv->irq, priv->irqprio);
+#endif
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: up_shutdown
+ *
+ * Description:
+ *   Disable the UART.  This method is called when the serial
+ *   port is closed
+ *
+ ****************************************************************************/
+
+static void up_shutdown(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* Disable interrupts */
+
+  up_disableuartint(dev, NULL);
+
+  /* Reset hardware and disable Rx and Tx */
+
+  s698pm_uartreset(priv->uartbase);
+}
+
+/****************************************************************************
+ * Name: up_attach
+ *
+ * Description:
+ *   Configure the UART to operation in interrupt driven mode. This method is
+ *   called when the serial port is opened.  Normally, this is just after the
+ *   the setup() method is called, however, the serial console may operate in
+ *   a non-interrupt driven mode during the boot phase.
+ *
+ *   RX and TX interrupts are not enabled by the attach method (unless the
+ *   hardware supports multiple levels of interrupt enabling).  The RX and TX
+ *   interrupts are not enabled until the txint() and rxint() methods are
+ *   called.
+ *
+ ****************************************************************************/
+
+static int up_attach(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  int ret;
+
+  /* Attach and enable the IRQ */
+
+  ret = irq_attach(priv->irq, up_interrupt, dev);
+  if (ret == OK)
+    {
+      /* Set up to uart interrupts on the current CPU */
+
+       (void)s698pm_setup_irq(0, priv->irq, 0);
+
+      /* Enable the interrupt (RX and TX interrupts are still disabled
+       * in the USART
+       */
+
+       up_enable_irq(priv->irq);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: up_detach
+ *
+ * Description:
+ *   Detach UART interrupts.  This method is called when the serial port is
+ *   closed normally just before the shutdown method is called. The exception
+ *   is the serial console which is never shutdown.
+ *
+ ****************************************************************************/
+
+static void up_detach(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* Disable interrupts */
+
+  up_disableuartint(dev, NULL);
+
+  /* Detach from the interrupt */
+
+  irq_detach(priv->irq);
+}
+
+/****************************************************************************
+ * Name: up_interrupt
+ *
+ * Description:
+ *   This is the UART interrupt handler.  It will be invoked when an
+ *   interrupt received on the 'irq'  It should call uart_transmitchars or
+ *   uart_receivechar to perform the appropriate data transfers.  The
+ *   interrupt handling logic must be able to map the 'irq' number into the
+ *   approprite uart_dev_s structure in order to call these functions.
+ *
+ ****************************************************************************/
+
+static int up_interrupt(int irq, void *context, void *arg)
+{
+  struct uart_dev_s *dev = (struct uart_dev_s *)arg;
+  struct up_dev_s   *priv;
+  uint32_t           mis;
+  int                passes;
+  bool               handled;
+
+  DEBUGASSERT(dev != NULL && dev->priv != NULL);
+  priv = (struct up_dev_s *)dev->priv;
+
+  /* Loop until there are no characters to be transferred or,
+   * until we have been looping for a long time.
+   */
+
+  handled = true;
+  for (passes = 0; passes < 256 && handled; passes++)
+    {
+      handled = false;
+
+      /* Get the masked UART status and clear the pending interrupts. */
+
+       mis = up_serialin(priv, S698PM_UART_STATREG_OFFSET);
+
+      /* Handle incoming, receive bytes */
+
+      if ((mis & UART_STA_DR) != 0)
+        {
+      /* Rx buffer not empty ... process incoming bytes */

Review Comment:
   Please align



##########
arch/sparc/src/s698pm/s698pm-irq.c:
##########
@@ -0,0 +1,533 @@
+/****************************************************************************
+ * arch/sparc/src/s698pm/s698pm-irq.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+
+#include <arch/irq.h>
+
+#include "up_internal.h"
+#include "s698pm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 7
+
+#if defined(CONFIG_SMP)
+#  define INTSTACK_ALLOC (CONFIG_SMP_NCPUS * INTSTACK_SIZE)
+#else
+#  define INTSTACK_ALLOC (INTSTACK_SIZE)
+#endif
+
+#endif
+
+/* IRQ to CPU and CPU interrupts mapping:
+ *
+ * Encoding: CCCIIIII
+ *  C: CPU that enabled the interrupt (0 ~ 3).
+ *  I: Associated CPU interrupt (0 ~ 31).
+ */
+
+#define IRQ_UNMAPPED      0xff
+#define IRQ_GETCPU(m)     (((m) & 0xe0) >> 0x05)
+#define IRQ_GETCPUINT(m)  ((m) & 0x1f)
+#define IRQ_MKMAP(c, i)   (((c) << 0x05) | (i))
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+static volatile uint8_t g_irqmap[NR_IRQS];
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 7
+/* In the SMP configuration, we will need custom interrupt stacks.
+ * These definitions provide the aligned stack allocations.
+ */
+
+static uint64_t g_intstack_alloc[INTSTACK_ALLOC >> 3];
+
+/* These definitions provide the "top" of the push-down stacks. */
+
+uintptr_t g_cpu_intstack_top[CONFIG_SMP_NCPUS] =
+{
+  (uintptr_t)g_intstack_alloc + INTSTACK_SIZE,
+#if defined(CONFIG_SMP)
+
+#if CONFIG_SMP_NCPUS > 1
+  (uintptr_t)g_intstack_alloc + (2 * INTSTACK_SIZE),
+#if CONFIG_SMP_NCPUS > 2
+  (uintptr_t)g_intstack_alloc + (3 * INTSTACK_SIZE),
+#if CONFIG_SMP_NCPUS > 3
+  (uintptr_t)g_intstack_alloc + (4 * INTSTACK_SIZE),
+#endif /* CONFIG_SMP_NCPUS > 3 */
+#endif /* CONFIG_SMP_NCPUS > 2 */
+#endif /* CONFIG_SMP_NCPUS > 1 */
+
+#endif /* defined(CONFIG_SMP) */
+};
+#endif /* if CONFIG_ARCH_INTERRUPTSTACK > 7 */
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#ifndef CONFIG_ARCH_IRQPRIO
+static int up_prioritize_irq(int irq, int priority);
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_irqinitialize
+ ****************************************************************************/
+
+void up_irqinitialize(void)
+{
+  int irq = 0;
+
+  for (irq = 0; irq < NR_IRQS; irq++)
+    {
+      g_irqmap[irq] = IRQ_UNMAPPED;
+    }
+
+  /* Initialize CPU interrupts */
+
+  s698pm_cpuint_initialize();
+
+  /* Set interrupts priority */
+
+  for (irq = 0x11; irq < 0x20; irq++)

Review Comment:
   ```suggestion
     for (irq = S698PM_IRQ_FIRST_INT; irq =< S698PM_IRQ_LAST_INT; irq++)
   ```



##########
arch/sparc/src/s698pm/s698pm-serial.c:
##########
@@ -0,0 +1,1037 @@
+/****************************************************************************
+ * arch/sparc/src/s698pm/s698pm-serial.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#ifdef CONFIG_SERIAL_TERMIOS
+#  include <termios.h>
+#endif
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/serial/serial.h>
+#include <nuttx/spinlock.h>
+#include <arch/board/board.h>
+
+#include "up_internal.h"
+#include "s698pm-config.h"
+#include "chip.h"
+#include "s698pm-uart.h"
+#include "s698pm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* If we are not using the serial driver for the console, then we still must
+ * provide some minimal implementation of up_putc.
+ */
+
+#ifdef USE_SERIALDRIVER
+
+/* Which UART with be tty0/console and which tty1?  The console will always
+ * be ttyS0.  If there is no console then will use the lowest numbered UART.
+ */
+
+/* First pick the console and ttys0.  This could be any of UART1-4 */
+
+#if defined(CONFIG_UART1_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart1port /* UART1 is console */
+#    define TTYS0_DEV           g_uart1port /* UART1 is ttyS0 */
+#    define UART1_ASSIGNED      1
+#elif defined(CONFIG_UART2_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart2port /* UART2 is console */
+#    define TTYS0_DEV           g_uart2port /* UART2 is ttyS0 */
+#    define UART2_ASSIGNED      1
+#elif defined(CONFIG_UART3_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart3port /* UART3 is console */
+#    define TTYS0_DEV           g_uart3port /* UART3 is ttyS0 */
+#    define UART3_ASSIGNED      1
+#elif defined(CONFIG_UART4_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart4port /* UART4 is console */
+#    define TTYS0_DEV           g_uart4port /* UART4 is ttyS0 */
+#    define UART4_ASSIGNED      1
+#else
+#  undef CONSOLE_DEV                        /* No console */
+#  if defined(CONFIG_S698PM_UART1)
+#    define TTYS0_DEV           g_uart1port /* UART1 is ttyS0 */
+#    define UART1_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART2)
+#    define TTYS0_DEV           g_uart2port /* UART2 is ttyS0 */
+#    define UART2_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART3)
+#    define TTYS0_DEV           g_uart3port /* UART3 is ttyS0 */
+#    define UART3_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART4)
+#    define TTYS0_DEV           g_uart4port /* UART4 is ttyS0 */
+#    define UART4_ASSIGNED      1
+#  endif
+#endif
+
+/* Pick ttys1.  This could be any of UART1-4 excluding the console UART. */
+
+#if defined(CONFIG_S698PM_UART1) && !defined(UART1_ASSIGNED)
+#  define TTYS1_DEV           g_uart1port /* UART1 is ttyS1 */
+#  define UART1_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART2) && !defined(UART2_ASSIGNED)
+#  define TTYS1_DEV           g_uart2port /* UART2 is ttyS1 */
+#  define UART2_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS1_DEV           g_uart3port /* UART3 is ttyS1 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS1_DEV           g_uart4port /* UART4 is ttyS1 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Pick ttys2.  This could be one of UART2-4. It can't be UART1 because that
+ * was either assigned as ttyS0 or ttys1.  One of UART 1-4 could also be the
+ * console.
+ */
+
+#if defined(CONFIG_S698PM_UART2) && !defined(UART2_ASSIGNED)
+#  define TTYS2_DEV           g_uart2port /* UART2 is ttyS2 */
+#  define UART2_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS2_DEV           g_uart3port /* UART3 is ttyS2 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS2_DEV           g_uart4port /* UART4 is ttyS2 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Pick ttys3. This could be one of UART3-4. It can't be UART1-2 because
+ * those have already been assigned to ttsyS0, 1, or 2.  One of
+ * UART 2-4 could also be the console.
+ */
+
+#if defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS3_DEV           g_uart3port /* UART3 is ttyS3 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS3_DEV           g_uart4port /* UART4 is ttyS3 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Common initialization logic will not not know that the all of the UARTs
+ * have been disabled.  So, as a result, we may still have to provide
+ * stub implementations of up_earlyserialinit(), up_serialinit(), and
+ * up_putc().
+ */
+
+#ifdef HAVE_UART_DEVICE
+
+/* These values describe the set of enabled interrupts */
+
+#define RX_ENABLED(im)    (((im) & MSK_UART_ENABLE_RX) != 0)
+#define TX_ENABLED(im)    (((im) & MSK_UART_ENABLE_TX) != 0)
+
+#define ENABLE_RX(im)     do { (im) |= MSK_UART_ENABLE_RX; } while (0)
+#define ENABLE_TX(im)     do { (im) |= MSK_UART_ENABLE_TX; } while (0)
+
+#define DISABLE_RX(im)    do { (im) &= ~MSK_UART_ENABLE_RX; } while (0)
+#define DISABLE_TX(im)    do { (im) &= ~MSK_UART_ENABLE_TX; } while (0)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct up_dev_s
+{
+  uintptr_t uartbase;  /* Base address of UART registers */
+  uint32_t  baud;      /* Configured baud */
+  uint8_t   irq;       /* IRQ associated with this UART (for attachment) */
+  uint8_t   im;        /* Interrupt mask state */
+  uint8_t   parity;    /* 0=none, 1=odd, 2=even */
+  uint8_t   bits;      /* Number of bits (5, 6, 7 or 8) */
+  bool      stopbits2; /* true: Configure with 2 stop bits instead of 1 */
+  spinlock_t lock;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Low-level helpers */
+
+static inline uint32_t up_serialin(struct up_dev_s *priv, int offset);
+static inline void up_serialout(struct up_dev_s *priv, int offset,
+                                uint32_t value);
+static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im);
+static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im);
+
+/* Serial driver methods */
+
+static int  up_setup(struct uart_dev_s *dev);
+static void up_shutdown(struct uart_dev_s *dev);
+static int  up_attach(struct uart_dev_s *dev);
+static void up_detach(struct uart_dev_s *dev);
+static int  up_interrupt(int irq, void *context, void *arg);
+static int  up_ioctl(struct file *filep, int cmd, unsigned long arg);
+static int  up_receive(struct uart_dev_s *dev, uint32_t *status);
+static void up_rxint(struct uart_dev_s *dev, bool enable);
+static bool up_rxavailable(struct uart_dev_s *dev);
+static void up_send(struct uart_dev_s *dev, int ch);
+static void up_txint(struct uart_dev_s *dev, bool enable);
+static bool up_txready(struct uart_dev_s *dev);
+static bool up_txempty(struct uart_dev_s *dev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct uart_ops_s g_uart_ops =
+{
+  .setup          = up_setup,
+  .shutdown       = up_shutdown,
+  .attach         = up_attach,
+  .detach         = up_detach,
+  .ioctl          = up_ioctl,
+  .receive        = up_receive,
+  .rxint          = up_rxint,
+  .rxavailable    = up_rxavailable,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  .rxflowcontrol  = NULL,
+#endif
+  .send           = up_send,
+  .txint          = up_txint,
+  .txready        = up_txready,
+  .txempty        = up_txempty,
+};
+
+/* I/O buffers */
+
+#ifdef CONFIG_S698PM_UART1
+static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE];
+static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART2
+static char g_uart2rxbuffer[CONFIG_UART2_RXBUFSIZE];
+static char g_uart2txbuffer[CONFIG_UART2_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART3
+static char g_uart3rxbuffer[CONFIG_UART3_RXBUFSIZE];
+static char g_uart3txbuffer[CONFIG_UART3_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART4
+static char g_uart3rxbuffer[CONFIG_UART4_RXBUFSIZE];
+static char g_uart3txbuffer[CONFIG_UART4_TXBUFSIZE];
+#endif
+
+/* This describes the state of the S698PM UART1 port. */
+
+#ifdef CONFIG_S698PM_UART1
+static struct up_dev_s g_uart1priv =
+{
+  .uartbase  = S698PM_UART1_BASE,
+  .baud      = CONFIG_UART1_BAUD,
+  .irq       = S698PM_IRQ_UART_1_RX_TX,
+  .parity    = CONFIG_UART1_PARITY,
+  .bits      = CONFIG_UART1_BITS,
+  .stopbits2 = CONFIG_UART1_2STOP,
+};
+
+static uart_dev_t g_uart1port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART1_RXBUFSIZE,
+    .buffer  = g_uart1rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART1_TXBUFSIZE,
+    .buffer  = g_uart1txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart1priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART2 port. */
+
+#ifdef CONFIG_S698PM_UART2
+static struct up_dev_s g_uart2priv =
+{
+  .uartbase  = S698PM_UART2_BASE,
+  .baud      = CONFIG_UART2_BAUD,
+  .irq       = S698PM_IRQ_UART_2_RX_TX,
+  .parity    = CONFIG_UART2_PARITY,
+  .bits      = CONFIG_UART2_BITS,
+  .stopbits2 = CONFIG_UART2_2STOP,
+};
+
+static uart_dev_t g_uart2port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART2_RXBUFSIZE,
+    .buffer  = g_uart2rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART2_TXBUFSIZE,
+    .buffer  = g_uart2txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart2priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART3 port. */
+
+#ifdef CONFIG_S698PM_UART3
+static struct up_dev_s g_uart3priv =
+{
+  .uartbase  = S698PM_UART3_BASE,
+  .baud      = CONFIG_UART3_BAUD,
+  .irq       = S698PM_IRQ_UART_3_RX_TX,
+  .parity    = CONFIG_UART3_PARITY,
+  .bits      = CONFIG_UART3_BITS,
+  .stopbits2 = CONFIG_UART3_2STOP,
+};
+
+static uart_dev_t g_uart3port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART3_RXBUFSIZE,
+    .buffer  = g_uart3rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART3_TXBUFSIZE,
+    .buffer  = g_uart3txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart3priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART4 port. */
+
+#ifdef CONFIG_S698PM_UART4
+static struct up_dev_s g_uart4priv =
+{
+  .uartbase  = S698PM_UART4_BASE,
+  .baud      = CONFIG_UART4_BAUD,
+  .irq       = S698PM_IRQ_UART_4_RX_TX,
+  .parity    = CONFIG_UART4_PARITY,
+  .bits      = CONFIG_UART4_BITS,
+  .stopbits2 = CONFIG_UART4_2STOP,
+};
+
+static uart_dev_t g_uart4port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART4_RXBUFSIZE,
+    .buffer  = g_uart4rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART4_TXBUFSIZE,
+    .buffer  = g_uart4txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart4priv,
+};
+#endif
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_serialin
+ ****************************************************************************/
+
+static inline uint32_t up_serialin(struct up_dev_s *priv, int offset)
+{
+  return getreg32(priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_serialout
+ ****************************************************************************/
+
+static inline void up_serialout(struct up_dev_s *priv, int offset,
+                                uint32_t value)
+{
+  putreg32(value, priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_setuartint
+ ****************************************************************************/
+
+static inline void up_setuartint(struct up_dev_s *priv)
+{
+  uint8_t regval;
+
+  regval   = up_serialin(priv, S698PM_UART_CTRLREG_OFFSET);
+  regval  &= ~MSK_UART_ALLINTS;
+  regval  |= priv->im;
+  up_serialout(priv, S698PM_UART_CTRLREG_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: up_restoreuartint
+ ****************************************************************************/
+
+static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  irqstate_t flags;
+
+  /* Re-enable/re-disable interrupts corresponding to the state of bits
+   * in im
+   */
+
+  flags = spin_lock_irqsave(&priv->lock);
+  priv->im  &= ~MSK_UART_ALLINTS;
+  priv->im  |= im;
+  up_setuartint(priv);
+  spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/****************************************************************************
+ * Name: up_disableuartint
+ ****************************************************************************/
+
+static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&priv->lock);
+  if (im)
+    {
+      *im = priv->im;
+    }
+
+  /* Disable all interrupts */
+
+  DISABLE_RX(priv->im);
+  DISABLE_TX(priv->im);
+  up_setuartint(priv);
+  spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/****************************************************************************
+ * 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;
+
+  /* Configure the UART as an RS-232 UART */
+
+  s698pm_uartconfigure(priv->uartbase, priv->baud, priv->parity,
+                        priv->bits, priv->stopbits2);
+#endif
+
+#ifdef CONFIG_ARCH_IRQPRIO
+  /* Set up the interrupt priority */
+
+  up_prioritize_irq(priv->irq, priv->irqprio);
+#endif
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: up_shutdown
+ *
+ * Description:
+ *   Disable the UART.  This method is called when the serial
+ *   port is closed
+ *
+ ****************************************************************************/
+
+static void up_shutdown(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* Disable interrupts */
+
+  up_disableuartint(dev, NULL);
+
+  /* Reset hardware and disable Rx and Tx */
+
+  s698pm_uartreset(priv->uartbase);
+}
+
+/****************************************************************************
+ * Name: up_attach
+ *
+ * Description:
+ *   Configure the UART to operation in interrupt driven mode. This method is
+ *   called when the serial port is opened.  Normally, this is just after the
+ *   the setup() method is called, however, the serial console may operate in
+ *   a non-interrupt driven mode during the boot phase.
+ *
+ *   RX and TX interrupts are not enabled by the attach method (unless the
+ *   hardware supports multiple levels of interrupt enabling).  The RX and TX
+ *   interrupts are not enabled until the txint() and rxint() methods are
+ *   called.
+ *
+ ****************************************************************************/
+
+static int up_attach(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  int ret;
+
+  /* Attach and enable the IRQ */
+
+  ret = irq_attach(priv->irq, up_interrupt, dev);
+  if (ret == OK)
+    {
+      /* Set up to uart interrupts on the current CPU */
+
+       (void)s698pm_setup_irq(0, priv->irq, 0);
+
+      /* Enable the interrupt (RX and TX interrupts are still disabled
+       * in the USART
+       */
+
+       up_enable_irq(priv->irq);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: up_detach
+ *
+ * Description:
+ *   Detach UART interrupts.  This method is called when the serial port is
+ *   closed normally just before the shutdown method is called. The exception
+ *   is the serial console which is never shutdown.
+ *
+ ****************************************************************************/
+
+static void up_detach(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* Disable interrupts */
+
+  up_disableuartint(dev, NULL);
+
+  /* Detach from the interrupt */
+
+  irq_detach(priv->irq);
+}
+
+/****************************************************************************
+ * Name: up_interrupt
+ *
+ * Description:
+ *   This is the UART interrupt handler.  It will be invoked when an
+ *   interrupt received on the 'irq'  It should call uart_transmitchars or
+ *   uart_receivechar to perform the appropriate data transfers.  The
+ *   interrupt handling logic must be able to map the 'irq' number into the
+ *   approprite uart_dev_s structure in order to call these functions.
+ *
+ ****************************************************************************/
+
+static int up_interrupt(int irq, void *context, void *arg)
+{
+  struct uart_dev_s *dev = (struct uart_dev_s *)arg;
+  struct up_dev_s   *priv;
+  uint32_t           mis;
+  int                passes;
+  bool               handled;
+
+  DEBUGASSERT(dev != NULL && dev->priv != NULL);
+  priv = (struct up_dev_s *)dev->priv;
+
+  /* Loop until there are no characters to be transferred or,
+   * until we have been looping for a long time.
+   */
+
+  handled = true;
+  for (passes = 0; passes < 256 && handled; passes++)
+    {
+      handled = false;
+
+      /* Get the masked UART status and clear the pending interrupts. */
+
+       mis = up_serialin(priv, S698PM_UART_STATREG_OFFSET);
+
+      /* Handle incoming, receive bytes */
+
+      if ((mis & UART_STA_DR) != 0)
+        {
+      /* Rx buffer not empty ... process incoming bytes */
+
+           uart_recvchars(dev);
+           handled = true;
+        }
+
+      /* Handle outgoing, transmit bytes */
+
+      if ((mis & UART_STA_TF) != UART_STA_TF)
+        {
+      /* Tx FIFO not full ... process outgoing bytes */
+
+      /* if (dev->xmit.head != dev->xmit.tail)
+       * {
+       */

Review Comment:
   Please remove!



##########
arch/sparc/src/s698pm/s698pm-serial.c:
##########
@@ -0,0 +1,1037 @@
+/****************************************************************************
+ * arch/sparc/src/s698pm/s698pm-serial.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#ifdef CONFIG_SERIAL_TERMIOS
+#  include <termios.h>
+#endif
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/serial/serial.h>
+#include <nuttx/spinlock.h>
+#include <arch/board/board.h>
+
+#include "up_internal.h"
+#include "s698pm-config.h"
+#include "chip.h"
+#include "s698pm-uart.h"
+#include "s698pm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* If we are not using the serial driver for the console, then we still must
+ * provide some minimal implementation of up_putc.
+ */
+
+#ifdef USE_SERIALDRIVER
+
+/* Which UART with be tty0/console and which tty1?  The console will always
+ * be ttyS0.  If there is no console then will use the lowest numbered UART.
+ */
+
+/* First pick the console and ttys0.  This could be any of UART1-4 */
+
+#if defined(CONFIG_UART1_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart1port /* UART1 is console */
+#    define TTYS0_DEV           g_uart1port /* UART1 is ttyS0 */
+#    define UART1_ASSIGNED      1
+#elif defined(CONFIG_UART2_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart2port /* UART2 is console */
+#    define TTYS0_DEV           g_uart2port /* UART2 is ttyS0 */
+#    define UART2_ASSIGNED      1
+#elif defined(CONFIG_UART3_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart3port /* UART3 is console */
+#    define TTYS0_DEV           g_uart3port /* UART3 is ttyS0 */
+#    define UART3_ASSIGNED      1
+#elif defined(CONFIG_UART4_SERIAL_CONSOLE)
+#    define CONSOLE_DEV         g_uart4port /* UART4 is console */
+#    define TTYS0_DEV           g_uart4port /* UART4 is ttyS0 */
+#    define UART4_ASSIGNED      1
+#else
+#  undef CONSOLE_DEV                        /* No console */
+#  if defined(CONFIG_S698PM_UART1)
+#    define TTYS0_DEV           g_uart1port /* UART1 is ttyS0 */
+#    define UART1_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART2)
+#    define TTYS0_DEV           g_uart2port /* UART2 is ttyS0 */
+#    define UART2_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART3)
+#    define TTYS0_DEV           g_uart3port /* UART3 is ttyS0 */
+#    define UART3_ASSIGNED      1
+#  elif defined(CONFIG_S698PM_UART4)
+#    define TTYS0_DEV           g_uart4port /* UART4 is ttyS0 */
+#    define UART4_ASSIGNED      1
+#  endif
+#endif
+
+/* Pick ttys1.  This could be any of UART1-4 excluding the console UART. */
+
+#if defined(CONFIG_S698PM_UART1) && !defined(UART1_ASSIGNED)
+#  define TTYS1_DEV           g_uart1port /* UART1 is ttyS1 */
+#  define UART1_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART2) && !defined(UART2_ASSIGNED)
+#  define TTYS1_DEV           g_uart2port /* UART2 is ttyS1 */
+#  define UART2_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS1_DEV           g_uart3port /* UART3 is ttyS1 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS1_DEV           g_uart4port /* UART4 is ttyS1 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Pick ttys2.  This could be one of UART2-4. It can't be UART1 because that
+ * was either assigned as ttyS0 or ttys1.  One of UART 1-4 could also be the
+ * console.
+ */
+
+#if defined(CONFIG_S698PM_UART2) && !defined(UART2_ASSIGNED)
+#  define TTYS2_DEV           g_uart2port /* UART2 is ttyS2 */
+#  define UART2_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS2_DEV           g_uart3port /* UART3 is ttyS2 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS2_DEV           g_uart4port /* UART4 is ttyS2 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Pick ttys3. This could be one of UART3-4. It can't be UART1-2 because
+ * those have already been assigned to ttsyS0, 1, or 2.  One of
+ * UART 2-4 could also be the console.
+ */
+
+#if defined(CONFIG_S698PM_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS3_DEV           g_uart3port /* UART3 is ttyS3 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_S698PM_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS3_DEV           g_uart4port /* UART4 is ttyS3 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Common initialization logic will not not know that the all of the UARTs
+ * have been disabled.  So, as a result, we may still have to provide
+ * stub implementations of up_earlyserialinit(), up_serialinit(), and
+ * up_putc().
+ */
+
+#ifdef HAVE_UART_DEVICE
+
+/* These values describe the set of enabled interrupts */
+
+#define RX_ENABLED(im)    (((im) & MSK_UART_ENABLE_RX) != 0)
+#define TX_ENABLED(im)    (((im) & MSK_UART_ENABLE_TX) != 0)
+
+#define ENABLE_RX(im)     do { (im) |= MSK_UART_ENABLE_RX; } while (0)
+#define ENABLE_TX(im)     do { (im) |= MSK_UART_ENABLE_TX; } while (0)
+
+#define DISABLE_RX(im)    do { (im) &= ~MSK_UART_ENABLE_RX; } while (0)
+#define DISABLE_TX(im)    do { (im) &= ~MSK_UART_ENABLE_TX; } while (0)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct up_dev_s
+{
+  uintptr_t uartbase;  /* Base address of UART registers */
+  uint32_t  baud;      /* Configured baud */
+  uint8_t   irq;       /* IRQ associated with this UART (for attachment) */
+  uint8_t   im;        /* Interrupt mask state */
+  uint8_t   parity;    /* 0=none, 1=odd, 2=even */
+  uint8_t   bits;      /* Number of bits (5, 6, 7 or 8) */
+  bool      stopbits2; /* true: Configure with 2 stop bits instead of 1 */
+  spinlock_t lock;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Low-level helpers */
+
+static inline uint32_t up_serialin(struct up_dev_s *priv, int offset);
+static inline void up_serialout(struct up_dev_s *priv, int offset,
+                                uint32_t value);
+static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im);
+static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im);
+
+/* Serial driver methods */
+
+static int  up_setup(struct uart_dev_s *dev);
+static void up_shutdown(struct uart_dev_s *dev);
+static int  up_attach(struct uart_dev_s *dev);
+static void up_detach(struct uart_dev_s *dev);
+static int  up_interrupt(int irq, void *context, void *arg);
+static int  up_ioctl(struct file *filep, int cmd, unsigned long arg);
+static int  up_receive(struct uart_dev_s *dev, uint32_t *status);
+static void up_rxint(struct uart_dev_s *dev, bool enable);
+static bool up_rxavailable(struct uart_dev_s *dev);
+static void up_send(struct uart_dev_s *dev, int ch);
+static void up_txint(struct uart_dev_s *dev, bool enable);
+static bool up_txready(struct uart_dev_s *dev);
+static bool up_txempty(struct uart_dev_s *dev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct uart_ops_s g_uart_ops =
+{
+  .setup          = up_setup,
+  .shutdown       = up_shutdown,
+  .attach         = up_attach,
+  .detach         = up_detach,
+  .ioctl          = up_ioctl,
+  .receive        = up_receive,
+  .rxint          = up_rxint,
+  .rxavailable    = up_rxavailable,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  .rxflowcontrol  = NULL,
+#endif
+  .send           = up_send,
+  .txint          = up_txint,
+  .txready        = up_txready,
+  .txempty        = up_txempty,
+};
+
+/* I/O buffers */
+
+#ifdef CONFIG_S698PM_UART1
+static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE];
+static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART2
+static char g_uart2rxbuffer[CONFIG_UART2_RXBUFSIZE];
+static char g_uart2txbuffer[CONFIG_UART2_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART3
+static char g_uart3rxbuffer[CONFIG_UART3_RXBUFSIZE];
+static char g_uart3txbuffer[CONFIG_UART3_TXBUFSIZE];
+#endif
+#ifdef CONFIG_S698PM_UART4
+static char g_uart3rxbuffer[CONFIG_UART4_RXBUFSIZE];
+static char g_uart3txbuffer[CONFIG_UART4_TXBUFSIZE];
+#endif
+
+/* This describes the state of the S698PM UART1 port. */
+
+#ifdef CONFIG_S698PM_UART1
+static struct up_dev_s g_uart1priv =
+{
+  .uartbase  = S698PM_UART1_BASE,
+  .baud      = CONFIG_UART1_BAUD,
+  .irq       = S698PM_IRQ_UART_1_RX_TX,
+  .parity    = CONFIG_UART1_PARITY,
+  .bits      = CONFIG_UART1_BITS,
+  .stopbits2 = CONFIG_UART1_2STOP,
+};
+
+static uart_dev_t g_uart1port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART1_RXBUFSIZE,
+    .buffer  = g_uart1rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART1_TXBUFSIZE,
+    .buffer  = g_uart1txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart1priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART2 port. */
+
+#ifdef CONFIG_S698PM_UART2
+static struct up_dev_s g_uart2priv =
+{
+  .uartbase  = S698PM_UART2_BASE,
+  .baud      = CONFIG_UART2_BAUD,
+  .irq       = S698PM_IRQ_UART_2_RX_TX,
+  .parity    = CONFIG_UART2_PARITY,
+  .bits      = CONFIG_UART2_BITS,
+  .stopbits2 = CONFIG_UART2_2STOP,
+};
+
+static uart_dev_t g_uart2port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART2_RXBUFSIZE,
+    .buffer  = g_uart2rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART2_TXBUFSIZE,
+    .buffer  = g_uart2txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart2priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART3 port. */
+
+#ifdef CONFIG_S698PM_UART3
+static struct up_dev_s g_uart3priv =
+{
+  .uartbase  = S698PM_UART3_BASE,
+  .baud      = CONFIG_UART3_BAUD,
+  .irq       = S698PM_IRQ_UART_3_RX_TX,
+  .parity    = CONFIG_UART3_PARITY,
+  .bits      = CONFIG_UART3_BITS,
+  .stopbits2 = CONFIG_UART3_2STOP,
+};
+
+static uart_dev_t g_uart3port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART3_RXBUFSIZE,
+    .buffer  = g_uart3rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART3_TXBUFSIZE,
+    .buffer  = g_uart3txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart3priv,
+};
+#endif
+
+/* This describes the state of the S698PM UART4 port. */
+
+#ifdef CONFIG_S698PM_UART4
+static struct up_dev_s g_uart4priv =
+{
+  .uartbase  = S698PM_UART4_BASE,
+  .baud      = CONFIG_UART4_BAUD,
+  .irq       = S698PM_IRQ_UART_4_RX_TX,
+  .parity    = CONFIG_UART4_PARITY,
+  .bits      = CONFIG_UART4_BITS,
+  .stopbits2 = CONFIG_UART4_2STOP,
+};
+
+static uart_dev_t g_uart4port =
+{
+  .recv      =
+  {
+    .size    = CONFIG_UART4_RXBUFSIZE,
+    .buffer  = g_uart4rxbuffer,
+  },
+  .xmit      =
+  {
+    .size    = CONFIG_UART4_TXBUFSIZE,
+    .buffer  = g_uart4txbuffer,
+  },
+  .ops       = &g_uart_ops,
+  .priv      = &g_uart4priv,
+};
+#endif
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_serialin
+ ****************************************************************************/
+
+static inline uint32_t up_serialin(struct up_dev_s *priv, int offset)
+{
+  return getreg32(priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_serialout
+ ****************************************************************************/
+
+static inline void up_serialout(struct up_dev_s *priv, int offset,
+                                uint32_t value)
+{
+  putreg32(value, priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_setuartint
+ ****************************************************************************/
+
+static inline void up_setuartint(struct up_dev_s *priv)
+{
+  uint8_t regval;
+
+  regval   = up_serialin(priv, S698PM_UART_CTRLREG_OFFSET);
+  regval  &= ~MSK_UART_ALLINTS;
+  regval  |= priv->im;
+  up_serialout(priv, S698PM_UART_CTRLREG_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: up_restoreuartint
+ ****************************************************************************/
+
+static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  irqstate_t flags;
+
+  /* Re-enable/re-disable interrupts corresponding to the state of bits
+   * in im
+   */
+
+  flags = spin_lock_irqsave(&priv->lock);
+  priv->im  &= ~MSK_UART_ALLINTS;
+  priv->im  |= im;
+  up_setuartint(priv);
+  spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/****************************************************************************
+ * Name: up_disableuartint
+ ****************************************************************************/
+
+static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&priv->lock);
+  if (im)
+    {
+      *im = priv->im;
+    }
+
+  /* Disable all interrupts */
+
+  DISABLE_RX(priv->im);
+  DISABLE_TX(priv->im);
+  up_setuartint(priv);
+  spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/****************************************************************************
+ * 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;
+
+  /* Configure the UART as an RS-232 UART */
+
+  s698pm_uartconfigure(priv->uartbase, priv->baud, priv->parity,
+                        priv->bits, priv->stopbits2);
+#endif
+
+#ifdef CONFIG_ARCH_IRQPRIO
+  /* Set up the interrupt priority */
+
+  up_prioritize_irq(priv->irq, priv->irqprio);
+#endif
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: up_shutdown
+ *
+ * Description:
+ *   Disable the UART.  This method is called when the serial
+ *   port is closed
+ *
+ ****************************************************************************/
+
+static void up_shutdown(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* Disable interrupts */
+
+  up_disableuartint(dev, NULL);
+
+  /* Reset hardware and disable Rx and Tx */
+
+  s698pm_uartreset(priv->uartbase);
+}
+
+/****************************************************************************
+ * Name: up_attach
+ *
+ * Description:
+ *   Configure the UART to operation in interrupt driven mode. This method is
+ *   called when the serial port is opened.  Normally, this is just after the
+ *   the setup() method is called, however, the serial console may operate in
+ *   a non-interrupt driven mode during the boot phase.
+ *
+ *   RX and TX interrupts are not enabled by the attach method (unless the
+ *   hardware supports multiple levels of interrupt enabling).  The RX and TX
+ *   interrupts are not enabled until the txint() and rxint() methods are
+ *   called.
+ *
+ ****************************************************************************/
+
+static int up_attach(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  int ret;
+
+  /* Attach and enable the IRQ */
+
+  ret = irq_attach(priv->irq, up_interrupt, dev);
+  if (ret == OK)
+    {
+      /* Set up to uart interrupts on the current CPU */
+
+       (void)s698pm_setup_irq(0, priv->irq, 0);
+
+      /* Enable the interrupt (RX and TX interrupts are still disabled
+       * in the USART
+       */
+
+       up_enable_irq(priv->irq);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: up_detach
+ *
+ * Description:
+ *   Detach UART interrupts.  This method is called when the serial port is
+ *   closed normally just before the shutdown method is called. The exception
+ *   is the serial console which is never shutdown.
+ *
+ ****************************************************************************/
+
+static void up_detach(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* Disable interrupts */
+
+  up_disableuartint(dev, NULL);
+
+  /* Detach from the interrupt */
+
+  irq_detach(priv->irq);
+}
+
+/****************************************************************************
+ * Name: up_interrupt
+ *
+ * Description:
+ *   This is the UART interrupt handler.  It will be invoked when an
+ *   interrupt received on the 'irq'  It should call uart_transmitchars or
+ *   uart_receivechar to perform the appropriate data transfers.  The
+ *   interrupt handling logic must be able to map the 'irq' number into the
+ *   approprite uart_dev_s structure in order to call these functions.
+ *
+ ****************************************************************************/
+
+static int up_interrupt(int irq, void *context, void *arg)
+{
+  struct uart_dev_s *dev = (struct uart_dev_s *)arg;
+  struct up_dev_s   *priv;
+  uint32_t           mis;
+  int                passes;
+  bool               handled;
+
+  DEBUGASSERT(dev != NULL && dev->priv != NULL);
+  priv = (struct up_dev_s *)dev->priv;
+
+  /* Loop until there are no characters to be transferred or,
+   * until we have been looping for a long time.
+   */
+
+  handled = true;
+  for (passes = 0; passes < 256 && handled; passes++)
+    {
+      handled = false;
+
+      /* Get the masked UART status and clear the pending interrupts. */
+
+       mis = up_serialin(priv, S698PM_UART_STATREG_OFFSET);
+
+      /* Handle incoming, receive bytes */
+
+      if ((mis & UART_STA_DR) != 0)
+        {
+      /* Rx buffer not empty ... process incoming bytes */
+
+           uart_recvchars(dev);
+           handled = true;
+        }
+
+      /* Handle outgoing, transmit bytes */
+
+      if ((mis & UART_STA_TF) != UART_STA_TF)
+        {
+      /* Tx FIFO not full ... process outgoing bytes */

Review Comment:
   Please align!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to