This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit ee306d47fd977134909b53af6a53e73f48cd1bd3
Author: sunjikun <[email protected]>
AuthorDate: Wed Oct 25 17:20:51 2023 +0800

    drivers/serial: Add 16550_DLF_SIZE option for DesignWare UART.
    
    Signed-off-by: sunjikun <[email protected]>
---
 drivers/serial/Kconfig-16550      |  7 +++++++
 drivers/serial/uart_16550.c       | 18 +++++++++++++---
 include/nuttx/serial/uart_16550.h | 43 ++++++++++++++++++++++++++-------------
 3 files changed, 51 insertions(+), 17 deletions(-)

diff --git a/drivers/serial/Kconfig-16550 b/drivers/serial/Kconfig-16550
index aeb19cd6c5..03732bf72f 100644
--- a/drivers/serial/Kconfig-16550
+++ b/drivers/serial/Kconfig-16550
@@ -554,4 +554,11 @@ config 16550_SET_MCR_OUT2
        ---help---
                Some platforms require OUT2 of MCR being set for interrupt to 
be triggered
 
+config 16550_DLF_SIZE
+       int "DLF(Divisor Latch Fraction) size of DesignWare APB UART"
+       default 0
+       ---help---
+               The bit width of DLF register for DesignWare APB UART.
+               DLF_SIZE=0 means no support. Default: 0
+
 endif # 16550_UART
diff --git a/drivers/serial/uart_16550.c b/drivers/serial/uart_16550.c
index 58dc514e89..89d2cfa776 100644
--- a/drivers/serial/uart_16550.c
+++ b/drivers/serial/uart_16550.c
@@ -760,7 +760,16 @@ static inline void u16550_enablebreaks(FAR struct u16550_s 
*priv,
 #ifndef CONFIG_16550_SUPRESS_CONFIG
 static inline uint32_t u16550_divisor(FAR struct u16550_s *priv)
 {
-  return (priv->uartclk + (priv->baud << 3)) / (priv->baud << 4);
+  uint32_t base = 16 * priv->baud;
+  uint32_t quot = priv->uartclk / base;
+  uint32_t rem  = priv->uartclk % base;
+  uint32_t frac = ((rem << CONFIG_16550_DLF_SIZE) + base / 2) / base;
+
+#if CONFIG_16550_DLF_SIZE != 0
+  return quot | (frac << 16);
+#else
+  return quot + frac;
+#endif
 }
 #endif
 
@@ -778,7 +787,7 @@ static int u16550_setup(FAR struct uart_dev_s *dev)
 {
 #ifndef CONFIG_16550_SUPRESS_CONFIG
   FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
-  uint16_t div;
+  uint32_t div;
   uint32_t lcr;
 #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL) 
|| \
     defined(CONFIG_16550_SET_MCR_OUT2)
@@ -855,7 +864,10 @@ static int u16550_setup(FAR struct uart_dev_s *dev)
   /* Set the BAUD divisor */
 
   div = u16550_divisor(priv);
-  u16550_serialout(priv, UART_DLM_OFFSET, div >> 8);
+#if CONFIG_16550_DLF_SIZE != 0
+  u16550_serialout(priv, UART_DLF_OFFSET, (div >> 16) & 0xff);
+#endif
+  u16550_serialout(priv, UART_DLM_OFFSET, (div >>  8) & 0xff);
   u16550_serialout(priv, UART_DLL_OFFSET, div & 0xff);
 
 #ifdef CONFIG_16550_WAIT_LCR
diff --git a/include/nuttx/serial/uart_16550.h 
b/include/nuttx/serial/uart_16550.h
index ad77ca391b..ff8f44fdb3 100644
--- a/include/nuttx/serial/uart_16550.h
+++ b/include/nuttx/serial/uart_16550.h
@@ -173,20 +173,35 @@
 
 /* Register offsets *********************************************************/
 
-#define UART_RBR_OFFSET        0  /* (DLAB =0) Receiver Buffer Register */
-#define UART_THR_OFFSET        0  /* (DLAB =0) Transmit Holding Register */
-#define UART_DLL_OFFSET        0  /* (DLAB =1) Divisor Latch LSB */
-#define UART_DLM_OFFSET        1  /* (DLAB =1) Divisor Latch MSB */
-#define UART_IER_OFFSET        1  /* (DLAB =0) Interrupt Enable Register */
-#define UART_IIR_OFFSET        2  /* Interrupt ID Register */
-#define UART_FCR_OFFSET        2  /* FIFO Control Register */
-#define UART_LCR_OFFSET        3  /* Line Control Register */
-#define UART_MCR_OFFSET        4  /* Modem Control Register */
-#define UART_LSR_OFFSET        5  /* Line Status Register */
-#define UART_MSR_OFFSET        6  /* Modem Status Register */
-#define UART_SCR_OFFSET        7  /* Scratch Pad Register */
-#define UART_USR_OFFSET        31 /* UART Status Register */
-#define UART_DLF_OFFSET        48 /* Divisor Latch Fraction Register */
+#define UART_RBR_INCR          0  /* (DLAB =0) Receiver Buffer Register */
+#define UART_THR_INCR          0  /* (DLAB =0) Transmit Holding Register */
+#define UART_DLL_INCR          0  /* (DLAB =1) Divisor Latch LSB */
+#define UART_DLM_INCR          1  /* (DLAB =1) Divisor Latch MSB */
+#define UART_IER_INCR          1  /* (DLAB =0) Interrupt Enable Register */
+#define UART_IIR_INCR          2  /* Interrupt ID Register */
+#define UART_FCR_INCR          2  /* FIFO Control Register */
+#define UART_LCR_INCR          3  /* Line Control Register */
+#define UART_MCR_INCR          4  /* Modem Control Register */
+#define UART_LSR_INCR          5  /* Line Status Register */
+#define UART_MSR_INCR          6  /* Modem Status Register */
+#define UART_SCR_INCR          7  /* Scratch Pad Register */
+#define UART_USR_INCR          31 /* UART Status Register */
+#define UART_DLF_INCR          48 /* Divisor Latch Fraction Register */
+
+#define UART_RBR_OFFSET        (CONFIG_16550_REGINCR*UART_RBR_INCR)
+#define UART_THR_OFFSET        (CONFIG_16550_REGINCR*UART_THR_INCR)
+#define UART_DLL_OFFSET        (CONFIG_16550_REGINCR*UART_DLL_INCR)
+#define UART_DLM_OFFSET        (CONFIG_16550_REGINCR*UART_DLM_INCR)
+#define UART_IER_OFFSET        (CONFIG_16550_REGINCR*UART_IER_INCR)
+#define UART_IIR_OFFSET        (CONFIG_16550_REGINCR*UART_IIR_INCR)
+#define UART_FCR_OFFSET        (CONFIG_16550_REGINCR*UART_FCR_INCR)
+#define UART_LCR_OFFSET        (CONFIG_16550_REGINCR*UART_LCR_INCR)
+#define UART_MCR_OFFSET        (CONFIG_16550_REGINCR*UART_MCR_INCR)
+#define UART_LSR_OFFSET        (CONFIG_16550_REGINCR*UART_LSR_INCR)
+#define UART_MSR_OFFSET        (CONFIG_16550_REGINCR*UART_MSR_INCR)
+#define UART_SCR_OFFSET        (CONFIG_16550_REGINCR*UART_SCR_INCR)
+#define UART_USR_OFFSET        (CONFIG_16550_REGINCR*UART_USR_INCR)
+#define UART_DLF_OFFSET        (CONFIG_16550_REGINCR*UART_DLF_INCR)
 
 /* Register bit definitions *************************************************/
 

Reply via email to