This is an automated email from the ASF dual-hosted git repository. jerpelea pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 1dd9f6428753def6a665ee109befd26b7817c364 Author: chao an <anc...@lixiang.com> AuthorDate: Thu Jan 11 14:15:45 2024 +0800 drivers/serial/pl011: add support of uart0/2/3 port Signed-off-by: chao an <anc...@lixiang.com> --- drivers/serial/Kconfig-pl011 | 58 +++--- drivers/serial/uart_pl011.c | 425 +++++++++++++++++++++++++++++++------------ 2 files changed, 341 insertions(+), 142 deletions(-) diff --git a/drivers/serial/Kconfig-pl011 b/drivers/serial/Kconfig-pl011 index 9d562761bc..c4c94ba221 100644 --- a/drivers/serial/Kconfig-pl011 +++ b/drivers/serial/Kconfig-pl011 @@ -10,51 +10,59 @@ config UART0_PL011 select UART0_SERIALDRIVER default n +if UART0_PL011 + +config UART0_BASE + hex "UART0 base address" + +config UART0_IRQ + int "PL011 UART0 IRQ number" + +endif # UART0_PL011 + config UART1_PL011 bool "UART1 PL011" select UART1_SERIALDRIVER default n +if UART1_PL011 + +config UART1_BASE + hex "UART1 base address" + +config UART1_IRQ + int "PL011 UART1 IRQ number" + +endif # UART1_PL011 + config UART2_PL011 bool "UART2 PL011" select UART2_SERIALDRIVER default n +if UART2_PL011 + +config UART2_BASE + hex "UART2 base address" + +config UART2_IRQ + int "PL011 UART2 IRQ number" + +endif # UART2_PL011 + config UART3_PL011 bool "UART3 PL011" select UART3_SERIALDRIVER default n -config UART0_BASE - hex "UART0 base address" - depends on UART0_PL011 - -config UART1_BASE - hex "UART1 base address" - depends on UART1_PL011 - -config UART2_BASE - hex "UART2 base address" - depends on UART2_PL011 +if UART3_PL011 config UART3_BASE hex "UART3 base address" - depends on UART3_PL011 - -config UART0_IRQ - int "PL011 UART0 IRQ number" - depends on UART0_PL011 - -config UART1_IRQ - int "PL011 UART1 IRQ number" - depends on UART1_PL011 - -config UART2_IRQ - int "PL011 UART2 IRQ number" - depends on UART2_PL011 config UART3_IRQ int "PL011 UART3 IRQ number" - depends on UART3_PL011 + +endif # UART3_PL011 endif # UART_PL011 diff --git a/drivers/serial/uart_pl011.c b/drivers/serial/uart_pl011.c index 222579a21f..da2aa2f684 100644 --- a/drivers/serial/uart_pl011.c +++ b/drivers/serial/uart_pl011.c @@ -59,10 +59,16 @@ /* First pick the console and ttys0. This could be any of UART1-5 */ -#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 +#if defined(CONFIG_UART0_SERIAL_CONSOLE) && defined(CONFIG_UART0_PL011) +# define HAVE_PL011_CONSOLE 1 +#elif defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(CONFIG_UART1_PL011) +# define HAVE_PL011_CONSOLE 1 +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) && defined(CONFIG_UART2_PL011) +# define HAVE_PL011_CONSOLE 1 +#elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_UART3_PL011) +# define HAVE_PL011_CONSOLE 1 +#else +# undef HAVE_PL011_CONSOLE 1 #endif #define PL011_BIT_MASK(x, y) (((2 << (x)) - 1) << (y)) @@ -220,9 +226,263 @@ struct pl011_uart_port_s struct pl011_data data; struct pl011_config config; unsigned int irq_num; - bool is_console; }; +static int pl011_setup(struct uart_dev_s *dev); +static void pl011_shutdown(struct uart_dev_s *dev); +static int pl011_attach(struct uart_dev_s *dev); +static void pl011_detach(struct uart_dev_s *dev); +static int pl011_ioctl(struct file *filep, int cmd, unsigned long arg); +static int pl011_receive(struct uart_dev_s *dev, unsigned int *status); +static void pl011_rxint(struct uart_dev_s *dev, bool enable); +static bool pl011_rxavailable(struct uart_dev_s *dev); +static void pl011_send(struct uart_dev_s *dev, int ch); +static void pl011_txint(struct uart_dev_s *dev, bool enable); +static bool pl011_txready(struct uart_dev_s *dev); +static bool pl011_txempty(struct uart_dev_s *dev); + +/*************************************************************************** + * Private Data + ***************************************************************************/ + +/* Serial driver UART operations */ + +static const struct uart_ops_s g_uart_ops = +{ + .setup = pl011_setup, + .shutdown = pl011_shutdown, + .attach = pl011_attach, + .detach = pl011_detach, + .ioctl = pl011_ioctl, + .receive = pl011_receive, + .rxint = pl011_rxint, + .rxavailable = pl011_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = pl011_send, + .txint = pl011_txint, + .txready = pl011_txready, + .txempty = pl011_txempty, +}; + +/* I/O buffers */ + +#ifdef CONFIG_UART0_PL011 +static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE]; +static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE]; +#endif +#ifdef CONFIG_UART1_PL011 +static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE]; +static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE]; +#endif +#ifdef CONFIG_UART2_PL011 +static char g_uart2rxbuffer[CONFIG_UART2_RXBUFSIZE]; +static char g_uart2txbuffer[CONFIG_UART2_TXBUFSIZE]; +#endif +#ifdef CONFIG_UART3_PL011 +static char g_uart3rxbuffer[CONFIG_UART3_RXBUFSIZE]; +static char g_uart3txbuffer[CONFIG_UART3_TXBUFSIZE]; +#endif + +/* This describes the state of the uart0 port. */ + +#ifdef CONFIG_UART0_PL011 + +static struct pl011_uart_port_s g_uart0priv = +{ + .data = + { + .baud_rate = CONFIG_UART0_BAUD, + .sbsa = false, + }, + + .config = + { + .uart = (volatile struct pl011_regs *)CONFIG_UART0_BASE, + .sys_clk_freq = 24000000, + }, + + .irq_num = CONFIG_UART0_IRQ, +}; + +/* I/O buffers */ + +static struct uart_dev_s g_uart0port = +{ + .recv = + { + .size = CONFIG_UART0_RXBUFSIZE, + .buffer = g_uart0rxbuffer, + }, + + .xmit = + { + .size = CONFIG_UART0_TXBUFSIZE, + .buffer = g_uart0txbuffer, + }, + + .ops = &g_uart_ops, + .priv = &g_uart0priv, +}; + +#endif /* CONFIG_UART0_PL011 */ + +/* This describes the state of the uart1 port. */ + +#ifdef CONFIG_UART1_PL011 + +static struct pl011_uart_port_s g_uart1priv = +{ + .data = + { + .baud_rate = CONFIG_UART1_BAUD, + .sbsa = false, + }, + + .config = + { + .uart = (volatile struct pl011_regs *)CONFIG_UART1_BASE, + .sys_clk_freq = 24000000, + }, + + .irq_num = CONFIG_UART1_IRQ, +}; + +/* I/O buffers */ + +static struct uart_dev_s 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 /* CONFIG_UART1_PL011 */ + +/* This describes the state of the uart2 port. */ + +#ifdef CONFIG_UART2_PL011 + +static struct pl011_uart_port_s g_uart2priv = +{ + .data = + { + .baud_rate = CONFIG_UART2_BAUD, + .sbsa = false, + }, + + .config = + { + .uart = (volatile struct pl011_regs *)CONFIG_UART2_BASE, + .sys_clk_freq = 24000000, + }, + + .irq_num = CONFIG_UART2_IRQ, +}; + +/* I/O buffers */ + +static struct uart_dev_s 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 /* CONFIG_UART2_PL011 */ + +/* This describes the state of the uart3 port. */ + +#ifdef CONFIG_UART3_PL011 + +static struct pl011_uart_port_s g_uart3priv = +{ + .data = + { + .baud_rate = CONFIG_UART3_BAUD, + .sbsa = false, + }, + + .config = + { + .uart = (volatile struct pl011_regs *)CONFIG_UART3_BASE, + .sys_clk_freq = 24000000, + }, + + .irq_num = CONFIG_UART3_IRQ, +}; + +/* I/O buffers */ + +static struct uart_dev_s 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 /* CONFIG_UART3_PL011 */ + +#if defined(CONFIG_UART0_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart0port /* UART0 is console */ +#elif defined(CONFIG_UART1_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart1port /* UART1 is console */ +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart2port /* UART2 is console */ +#elif defined(CONFIG_UART3_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart3port /* UART3 is console */ +#endif + +#ifdef CONFIG_UART0_PL011 +# define TTYS0_DEV g_uart0port +#endif + +#ifdef CONFIG_UART1_PL011 +# define TTYS1_DEV g_uart1port +#endif + +#ifdef CONFIG_UART2_PL011 +# define TTYS2_DEV g_uart2port +#endif + +#ifdef CONFIG_UART3_PL011 +# define TTYS3_DEV g_uart3port +#endif + /*************************************************************************** * Private Functions ***************************************************************************/ @@ -350,7 +610,7 @@ static int pl011_irq_rx_ready(const struct pl011_uart_port_s *sport) static bool pl011_txready(struct uart_dev_s *dev) { - struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + struct pl011_uart_port_s *sport = dev->priv; const struct pl011_config *config = &sport->config; struct pl011_data *data = &sport->data; @@ -373,7 +633,7 @@ static bool pl011_txready(struct uart_dev_s *dev) static bool pl011_txempty(struct uart_dev_s *dev) { - struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + struct pl011_uart_port_s *sport = dev->priv; return pl011_irq_tx_complete(sport); } @@ -388,7 +648,7 @@ static bool pl011_txempty(struct uart_dev_s *dev) static void pl011_send(struct uart_dev_s *dev, int ch) { - struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + struct pl011_uart_port_s *sport = dev->priv; const struct pl011_config *config = &sport->config; config->uart->dr = ch; @@ -404,7 +664,7 @@ static void pl011_send(struct uart_dev_s *dev, int ch) static bool pl011_rxavailable(struct uart_dev_s *dev) { - struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + struct pl011_uart_port_s *sport = dev->priv; const struct pl011_config *config = &sport->config; struct pl011_data *data = &sport->data; @@ -428,7 +688,7 @@ static bool pl011_rxavailable(struct uart_dev_s *dev) static void pl011_rxint(struct uart_dev_s *dev, bool enable) { - struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + struct pl011_uart_port_s *sport = dev->priv; if (enable) { @@ -450,7 +710,7 @@ static void pl011_rxint(struct uart_dev_s *dev, bool enable) static void pl011_txint(struct uart_dev_s *dev, bool enable) { - struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + struct pl011_uart_port_s *sport = dev->priv; irqstate_t flags; flags = enter_critical_section(); @@ -485,7 +745,7 @@ static void pl011_txint(struct uart_dev_s *dev, bool enable) static int pl011_receive(struct uart_dev_s *dev, unsigned int *status) { - struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + struct pl011_uart_port_s *sport = dev->priv; const struct pl011_config *config = &sport->config; unsigned int rx; @@ -537,13 +797,13 @@ static int pl011_ioctl(struct file *filep, int cmd, unsigned long arg) static int pl011_irq_handler(int irq, void *context, void *arg) { - struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct uart_dev_s *dev = arg; struct pl011_uart_port_s *sport; UNUSED(irq); UNUSED(context); DEBUGASSERT(dev != NULL && dev->priv != NULL); - sport = (struct pl011_uart_port_s *)dev->priv; + sport = dev->priv; if (pl011_irq_rx_ready(sport)) { @@ -570,7 +830,7 @@ static int pl011_irq_handler(int irq, void *context, void *arg) static void pl011_detach(struct uart_dev_s *dev) { - struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + struct pl011_uart_port_s *sport = dev->priv; up_disable_irq(sport->irq_num); irq_detach(sport->irq_num); @@ -599,7 +859,7 @@ static int pl011_attach(struct uart_dev_s *dev) struct pl011_data *data; int ret; - sport = (struct pl011_uart_port_s *)dev->priv; + sport = dev->priv; data = &sport->data; ret = irq_attach(sport->irq_num, pl011_irq_handler, dev); @@ -638,7 +898,7 @@ static void pl011_shutdown(struct uart_dev_s *dev) static int pl011_setup(struct uart_dev_s *dev) { - struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + struct pl011_uart_port_s *sport = dev->priv; const struct pl011_config *config = &sport->config; struct pl011_data *data = &sport->data; int ret; @@ -698,74 +958,6 @@ static int pl011_setup(struct uart_dev_s *dev) return 0; } -/*************************************************************************** - * Private Data - ***************************************************************************/ - -/* Serial driver UART operations */ - -static const struct uart_ops_s g_uart_ops = -{ - .setup = pl011_setup, - .shutdown = pl011_shutdown, - .attach = pl011_attach, - .detach = pl011_detach, - .ioctl = pl011_ioctl, - .receive = pl011_receive, - .rxint = pl011_rxint, - .rxavailable = pl011_rxavailable, -#ifdef CONFIG_SERIAL_IFLOWCONTROL - .rxflowcontrol = NULL, -#endif - .send = pl011_send, - .txint = pl011_txint, - .txready = pl011_txready, - .txempty = pl011_txempty, -}; - -/* This describes the state of the uart1 port. */ - -static struct pl011_uart_port_s g_uart1priv = -{ - .data = - { - .baud_rate = CONFIG_UART1_BAUD, - .sbsa = false, - }, - - .config = - { - .uart = (volatile struct pl011_regs *)CONFIG_UART1_BASE, - .sys_clk_freq = 24000000, - }, - - .irq_num = CONFIG_UART1_IRQ, - .is_console = 1, -}; - -/* I/O buffers */ - -static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE]; -static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE]; - -static struct uart_dev_s 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, -}; - /*************************************************************************** * Public Functions ***************************************************************************/ @@ -789,18 +981,45 @@ void pl011_earlyserialinit(void) #endif } +/*************************************************************************** + * Name: pl011_serialinit + * + * Description: + * Register serial console and serial ports. This assumes that + * pl011_earlyserialinit was called previously. + * + ***************************************************************************/ + +void pl011_serialinit(void) +{ +#ifdef CONSOLE_DEV + uart_register("/dev/console", &CONSOLE_DEV); +#endif +#ifdef TTYS0_DEV + uart_register("/dev/ttyS0", &TTYS0_DEV); +#endif +#ifdef TTYS1_DEV + uart_register("/dev/ttyS1", &TTYS1_DEV); +#endif +#ifdef TTYS2_DEV + uart_register("/dev/ttyS2", &TTYS2_DEV); +#endif +#ifdef TTYS3_DEV + uart_register("/dev/ttyS3", &TTYS3_DEV); +#endif +} + /*************************************************************************** * Name: up_putc * * Description: - * Provide priority, low-level access to support OS debug - * writes + * Provide priority, low-level access to support OS debug writes * ***************************************************************************/ +#ifdef HAVE_PL011_CONSOLE int up_putc(int ch) { -#ifdef CONSOLE_DEV struct uart_dev_s *dev = &CONSOLE_DEV; /* Check for LF */ @@ -813,37 +1032,9 @@ int up_putc(int ch) } pl011_send(dev, ch); -#endif return ch; } - -/*************************************************************************** - * Name: pl011_serialinit - * - * Description: - * see nuttx/serial/uart_pl011.h - * - ***************************************************************************/ - -void pl011_serialinit(void) -{ -#ifdef CONSOLE_DEV - int ret; - - ret = uart_register("/dev/console", &CONSOLE_DEV); - if (ret < 0) - { - sinfo("error at register dev/console, ret =%d\n", ret); - } - - ret = uart_register("/dev/ttyS0", &TTYS0_DEV); - - if (ret < 0) - { - sinfo("error at register dev/ttyS0, ret =%d\n", ret); - } #endif -} -#endif /* USE_SERIALDRIVER */ +#endif /* CONFIG_UART_PL011 */