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 *************************************************/
