123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365 |
- /****************************************************************************
- * drivers/serial/uart_16550.c
- * Serial driver for 16550 UART
- *
- * Copyright (C) 2011, 2013, 2017-2018 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gnutt@nuttx.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************/
- /****************************************************************************
- * 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 <debug.h>
- #include <nuttx/irq.h>
- #include <nuttx/arch.h>
- #include <nuttx/serial/serial.h>
- #include <nuttx/fs/ioctl.h>
- #include <nuttx/serial/uart_16550.h>
- #include <arch/board/board.h>
- #ifdef CONFIG_16550_UART
- /****************************************************************************
- * Pre-processor definitions
- ****************************************************************************/
- /****************************************************************************
- * Private Types
- ****************************************************************************/
- struct u16550_s
- {
- uart_addrwidth_t uartbase; /* Base address of UART registers */
- #ifndef CONFIG_16550_SUPRESS_CONFIG
- uint32_t baud; /* Configured baud */
- uint32_t uartclk; /* UART clock frequency */
- #endif
- uart_datawidth_t ier; /* Saved IER value */
- uint8_t irq; /* IRQ associated with this UART */
- #ifndef CONFIG_16550_SUPRESS_CONFIG
- uint8_t parity; /* 0=none, 1=odd, 2=even */
- uint8_t bits; /* Number of bits (7 or 8) */
- bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */
- #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
- bool flow; /* flow control (RTS/CTS) enabled */
- #endif
- #endif
- };
- /****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
- static int u16550_setup(FAR struct uart_dev_s *dev);
- static void u16550_shutdown(FAR struct uart_dev_s *dev);
- static int u16550_attach(FAR struct uart_dev_s *dev);
- static void u16550_detach(FAR struct uart_dev_s *dev);
- static int u16550_interrupt(int irq, FAR void *context, FAR void *arg);
- static int u16550_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
- static int u16550_receive(FAR struct uart_dev_s *dev, uint32_t *status);
- static void u16550_rxint(FAR struct uart_dev_s *dev, bool enable);
- static bool u16550_rxavailable(FAR struct uart_dev_s *dev);
- #ifdef CONFIG_SERIAL_IFLOWCONTROL
- static bool u16550_rxflowcontrol(struct uart_dev_s *dev, unsigned int nbuffered,
- bool upper);
- #endif
- #ifdef CONFIG_SERIAL_DMA
- static void u16550_dmasend(FAR struct uart_dev_s *dev);
- static void u16550_dmareceive(FAR struct uart_dev_s *dev);
- static void u16550_dmarxfree(FAR struct uart_dev_s *dev);
- static void u16550_dmatxavail(FAR struct uart_dev_s *dev);
- #endif
- static void u16550_send(FAR struct uart_dev_s *dev, int ch);
- static void u16550_txint(FAR struct uart_dev_s *dev, bool enable);
- static bool u16550_txready(FAR struct uart_dev_s *dev);
- static bool u16550_txempty(FAR struct uart_dev_s *dev);
- /****************************************************************************
- * Private Data
- ****************************************************************************/
- static const struct uart_ops_s g_uart_ops =
- {
- .setup = u16550_setup,
- .shutdown = u16550_shutdown,
- .attach = u16550_attach,
- .detach = u16550_detach,
- .ioctl = u16550_ioctl,
- .receive = u16550_receive,
- .rxint = u16550_rxint,
- .rxavailable = u16550_rxavailable,
- #ifdef CONFIG_SERIAL_IFLOWCONTROL
- .rxflowcontrol = u16550_rxflowcontrol,
- #endif
- #ifdef CONFIG_SERIAL_DMA
- .dmasend = u16550_dmasend,
- .dmareceive = u16550_dmareceive,
- .dmarxfree = u16550_dmarxfree,
- .dmatxavail = u16550_dmatxavail,
- #endif
- .send = u16550_send,
- .txint = u16550_txint,
- .txready = u16550_txready,
- .txempty = u16550_txempty,
- };
- /* I/O buffers */
- #ifdef CONFIG_16550_UART0
- static char g_uart0rxbuffer[CONFIG_16550_UART0_RXBUFSIZE];
- static char g_uart0txbuffer[CONFIG_16550_UART0_TXBUFSIZE];
- #endif
- #ifdef CONFIG_16550_UART1
- static char g_uart1rxbuffer[CONFIG_16550_UART1_RXBUFSIZE];
- static char g_uart1txbuffer[CONFIG_16550_UART1_TXBUFSIZE];
- #endif
- #ifdef CONFIG_16550_UART2
- static char g_uart2rxbuffer[CONFIG_16550_UART2_RXBUFSIZE];
- static char g_uart2txbuffer[CONFIG_16550_UART2_TXBUFSIZE];
- #endif
- #ifdef CONFIG_16550_UART3
- static char g_uart3rxbuffer[CONFIG_16550_UART3_RXBUFSIZE];
- static char g_uart3txbuffer[CONFIG_16550_UART3_TXBUFSIZE];
- #endif
- /* This describes the state of the 16550 uart0 port. */
- #ifdef CONFIG_16550_UART0
- static struct u16550_s g_uart0priv =
- {
- .uartbase = CONFIG_16550_UART0_BASE,
- #ifndef CONFIG_16550_SUPRESS_CONFIG
- .baud = CONFIG_16550_UART0_BAUD,
- .uartclk = CONFIG_16550_UART0_CLOCK,
- #endif
- .irq = CONFIG_16550_UART0_IRQ,
- #ifndef CONFIG_16550_SUPRESS_CONFIG
- .parity = CONFIG_16550_UART0_PARITY,
- .bits = CONFIG_16550_UART0_BITS,
- .stopbits2 = CONFIG_16550_UART0_2STOP,
- #if defined(CONFIG_16550_UART0_IFLOWCONTROL) || defined(CONFIG_16550_UART0_OFLOWCONTROL)
- .flow = true,
- #endif
- #endif
- };
- static uart_dev_t g_uart0port =
- {
- .recv =
- {
- .size = CONFIG_16550_UART0_RXBUFSIZE,
- .buffer = g_uart0rxbuffer,
- },
- .xmit =
- {
- .size = CONFIG_16550_UART0_TXBUFSIZE,
- .buffer = g_uart0txbuffer,
- },
- .ops = &g_uart_ops,
- .priv = &g_uart0priv,
- };
- #endif
- /* This describes the state of the 16550 uart1 port. */
- #ifdef CONFIG_16550_UART1
- static struct u16550_s g_uart1priv =
- {
- .uartbase = CONFIG_16550_UART1_BASE,
- #ifndef CONFIG_16550_SUPRESS_CONFIG
- .baud = CONFIG_16550_UART1_BAUD,
- .uartclk = CONFIG_16550_UART1_CLOCK,
- #endif
- .irq = CONFIG_16550_UART1_IRQ,
- #ifndef CONFIG_16550_SUPRESS_CONFIG
- .parity = CONFIG_16550_UART1_PARITY,
- .bits = CONFIG_16550_UART1_BITS,
- .stopbits2 = CONFIG_16550_UART1_2STOP,
- #if defined(CONFIG_16550_UART1_IFLOWCONTROL) || defined(CONFIG_16551_UART1_OFLOWCONTROL)
- .flow = true,
- #endif
- #endif
- };
- static uart_dev_t g_uart1port =
- {
- .recv =
- {
- .size = CONFIG_16550_UART1_RXBUFSIZE,
- .buffer = g_uart1rxbuffer,
- },
- .xmit =
- {
- .size = CONFIG_16550_UART1_TXBUFSIZE,
- .buffer = g_uart1txbuffer,
- },
- .ops = &g_uart_ops,
- .priv = &g_uart1priv,
- };
- #endif
- /* This describes the state of the 16550 uart1 port. */
- #ifdef CONFIG_16550_UART2
- static struct u16550_s g_uart2priv =
- {
- .uartbase = CONFIG_16550_UART2_BASE,
- #ifndef CONFIG_16550_SUPRESS_CONFIG
- .baud = CONFIG_16550_UART2_BAUD,
- .uartclk = CONFIG_16550_UART2_CLOCK,
- #endif
- .irq = CONFIG_16550_UART2_IRQ,
- #ifndef CONFIG_16550_SUPRESS_CONFIG
- .parity = CONFIG_16550_UART2_PARITY,
- .bits = CONFIG_16550_UART2_BITS,
- .stopbits2 = CONFIG_16550_UART2_2STOP,
- #if defined(CONFIG_16550_UART2_IFLOWCONTROL) || defined(CONFIG_16550_UART2_OFLOWCONTROL)
- .flow = true,
- #endif
- #endif
- };
- static uart_dev_t g_uart2port =
- {
- .recv =
- {
- .size = CONFIG_16550_UART2_RXBUFSIZE,
- .buffer = g_uart2rxbuffer,
- },
- .xmit =
- {
- .size = CONFIG_16550_UART2_TXBUFSIZE,
- .buffer = g_uart2txbuffer,
- },
- .ops = &g_uart_ops,
- .priv = &g_uart2priv,
- };
- #endif
- /* This describes the state of the 16550 uart1 port. */
- #ifdef CONFIG_16550_UART3
- static struct u16550_s g_uart3priv =
- {
- .uartbase = CONFIG_16550_UART3_BASE,
- #ifndef CONFIG_16550_SUPRESS_CONFIG
- .baud = CONFIG_16550_UART3_BAUD,
- .uartclk = CONFIG_16550_UART3_CLOCK,
- #endif
- .irq = CONFIG_16550_UART3_IRQ,
- #ifndef CONFIG_16550_SUPRESS_CONFIG
- .parity = CONFIG_16550_UART3_PARITY,
- .bits = CONFIG_16550_UART3_BITS,
- .stopbits2 = CONFIG_16550_UART3_2STOP,
- #if defined(CONFIG_16550_UART3_IFLOWCONTROL) || defined(CONFIG_16550_UART3_OFLOWCONTROL)
- .flow = true,
- #endif
- #endif
- };
- static uart_dev_t g_uart3port =
- {
- .recv =
- {
- .size = CONFIG_16550_UART3_RXBUFSIZE,
- .buffer = g_uart3rxbuffer,
- },
- .xmit =
- {
- .size = CONFIG_16550_UART3_TXBUFSIZE,
- .buffer = g_uart3txbuffer,
- },
- .ops = &g_uart_ops,
- .priv = &g_uart3priv,
- };
- #endif
- /* Which UART with be tty0/console and which tty1? tty2? tty3? */
- #ifdef CONFIG_16550_SERIAL_DISABLE_REORDERING
- # if defined(CONFIG_16550_UART0_SERIAL_CONSOLE)
- # define CONSOLE_DEV g_uart0port /* UART0=console */
- # elif defined(CONFIG_16550_UART1_SERIAL_CONSOLE)
- # define CONSOLE_DEV g_uart1port /* UART1=console */
- # elif defined(CONFIG_16550_UART2_SERIAL_CONSOLE)
- # define CONSOLE_DEV g_uart2port /* UART2=console */
- # elif defined(CONFIG_16550_UART3_SERIAL_CONSOLE)
- # define CONSOLE_DEV g_uart3port /* UART3=console */
- # endif
- # ifdef CONFIG_16550_UART0
- # define TTYS0_DEV g_uart0port
- # endif
- # ifdef CONFIG_16550_UART1
- # define TTYS1_DEV g_uart1port
- # endif
- # ifdef CONFIG_16550_UART2
- # define TTYS2_DEV g_uart2port
- # endif
- # ifdef CONFIG_16550_UART3
- # define TTYS3_DEV g_uart3port
- # endif
- #else /* CONFIG_16550_SERIAL_DISABLE_REORDERING */
- /* Which UART with be tty0/console and which tty1? tty2? tty3? */
- # if defined(CONFIG_16550_UART0_SERIAL_CONSOLE)
- # define CONSOLE_DEV g_uart0port /* UART0=console */
- # define TTYS0_DEV g_uart0port /* UART0=ttyS0 */
- # ifdef CONFIG_16550_UART1
- # define TTYS1_DEV g_uart1port /* UART0=ttyS0;UART1=ttyS1 */
- # ifdef CONFIG_16550_UART2
- # define TTYS2_DEV g_uart2port /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS2 */
- # ifdef CONFIG_16550_UART3
- # define TTYS3_DEV g_uart3port /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS2;UART3=ttyS3 */
- # else
- # undef TTYS3_DEV /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS;No ttyS3 */
- # endif
- # else
- # ifdef CONFIG_16550_UART3
- # define TTYS2_DEV g_uart3port /* UART0=ttyS0;UART1=ttyS1;UART3=ttys2;No ttyS3 */
- # else
- # undef TTYS2_DEV /* UART0=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS3_DEV /* No ttyS3 */
- # endif
- # else
- # ifdef CONFIG_16550_UART2
- # define TTYS1_DEV g_uart2port /* UART0=ttyS0;UART2=ttyS1;No ttyS3 */
- # ifdef CONFIG_16550_UART3
- # define TTYS2_DEV g_uart3port /* UART0=ttyS0;UART2=ttyS1;UART3=ttyS2;No ttyS3 */
- # else
- # undef TTYS2_DEV /* UART0=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS3_DEV /* No ttyS3 */
- # else
- # ifdef CONFIG_16550_UART3
- # define TTYS1_DEV g_uart3port /* UART0=ttyS0;UART3=ttyS1;No ttyS2;No ttyS3 */
- # else
- # undef TTYS1_DEV /* UART0=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS2_DEV /* No ttyS2 */
- # undef TTYS3_DEV /* No ttyS3 */
- # endif
- # endif
- # elif defined(CONFIG_16550_UART1_SERIAL_CONSOLE)
- # define CONSOLE_DEV g_uart1port /* UART1=console */
- # define TTYS0_DEV g_uart1port /* UART1=ttyS0 */
- # ifdef CONFIG_16550_UART
- # define TTYS1_DEV g_uart0port /* UART1=ttyS0;UART0=ttyS1 */
- # ifdef CONFIG_16550_UART2
- # define TTYS2_DEV g_uart2port /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS2 */
- # ifdef CONFIG_16550_UART3
- # define TTYS3_DEV g_uart3port /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS2;UART3=ttyS3 */
- # else
- # undef TTYS3_DEV /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS;No ttyS3 */
- # endif
- # else
- # ifdef CONFIG_16550_UART3
- # define TTYS2_DEV g_uart3port /* UART1=ttyS0;UART0=ttyS1;UART3=ttys2;No ttyS3 */
- # else
- # undef TTYS2_DEV /* UART1=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS3_DEV /* No ttyS3 */
- # endif
- # else
- # ifdef CONFIG_16550_UART2
- # define TTYS1_DEV g_uart2port /* UART1=ttyS0;UART2=ttyS1 */
- # ifdef CONFIG_16550_UART3
- # define TTYS2_DEV g_uart3port /* UART1=ttyS0;UART2=ttyS1;UART3=ttyS2;No ttyS3 */
- # else
- # undef TTYS2_DEV /* UART1=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS3_DEV /* No ttyS3 */
- # else
- # ifdef CONFIG_16550_UART3
- # define TTYS1_DEV g_uart3port /* UART1=ttyS0;UART3=ttyS1;No ttyS2;No ttyS3 */
- # else
- # undef TTYS1_DEV /* UART1=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS2_DEV /* No ttyS2 */
- # undef TTYS3_DEV /* No ttyS3 */
- # endif
- # endif
- # elif defined(CONFIG_16550_UART2_SERIAL_CONSOLE)
- # define CONSOLE_DEV g_uart2port /* UART2=console */
- # define TTYS0_DEV g_uart2port /* UART2=ttyS0 */
- # ifdef CONFIG_16550_UART
- # define TTYS1_DEV g_uart0port /* UART2=ttyS0;UART0=ttyS1 */
- # ifdef CONFIG_16550_UART1
- # define TTYS2_DEV g_uart1port /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS2 */
- # ifdef CONFIG_16550_UART3
- # define TTYS3_DEV g_uart3port /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS2;UART3=ttyS3 */
- # else
- # undef TTYS3_DEV /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS;No ttyS3 */
- # endif
- # else
- # ifdef CONFIG_16550_UART3
- # define TTYS2_DEV g_uart3port /* UART2=ttyS0;UART0=ttyS1;UART3=ttys2;No ttyS3 */
- # else
- # undef TTYS2_DEV /* UART2=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS3_DEV /* No ttyS3 */
- # endif
- # else
- # ifdef CONFIG_16550_UART1
- # define TTYS1_DEV g_uart1port /* UART2=ttyS0;UART1=ttyS1 */
- # ifdef CONFIG_16550_UART3
- # define TTYS2_DEV g_uart3port /* UART2=ttyS0;UART1=ttyS1;UART3=ttyS2 */
- # else
- # undef TTYS2_DEV /* UART2=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS3_DEV /* No ttyS3 */
- # else
- # ifdef CONFIG_16550_UART3
- # define TTYS1_DEV g_uart3port /* UART2=ttyS0;UART3=ttyS1;No ttyS3 */
- # else
- # undef TTYS1_DEV /* UART2=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS2_DEV /* No ttyS2 */
- # undef TTYS3_DEV /* No ttyS3 */
- # endif
- # endif
- # elif defined(CONFIG_16550_UART3_SERIAL_CONSOLE)
- # define CONSOLE_DEV g_uart3port /* UART3=console */
- # define TTYS0_DEV g_uart3port /* UART3=ttyS0 */
- # ifdef CONFIG_16550_UART
- # define TTYS1_DEV g_uart0port /* UART3=ttyS0;UART0=ttyS1 */
- # ifdef CONFIG_16550_UART1
- # define TTYS2_DEV g_uart1port /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS2 */
- # ifdef CONFIG_16550_UART2
- # define TTYS3_DEV g_uart2port /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS2;UART2=ttyS3 */
- # else
- # undef TTYS3_DEV /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS;No ttyS3 */
- # endif
- # else
- # ifdef CONFIG_16550_UART2
- # define TTYS2_DEV g_uart2port /* UART3=ttyS0;UART0=ttyS1;UART2=ttys2;No ttyS3 */
- # else
- # undef TTYS2_DEV /* UART3=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS3_DEV /* No ttyS3 */
- # endif
- # else
- # ifdef CONFIG_16550_UART1
- # define TTYS1_DEV g_uart1port /* UART3=ttyS0;UART1=ttyS1 */
- # ifdef CONFIG_16550_UART2
- # define TTYS2_DEV g_uart2port /* UART3=ttyS0;UART1=ttyS1;UART2=ttyS2;No ttyS3 */
- # else
- # undef TTYS2_DEV /* UART3=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS3_DEV /* No ttyS3 */
- # else
- # ifdef CONFIG_16550_UART2
- # define TTYS1_DEV g_uart2port /* UART3=ttyS0;UART2=ttyS1;No ttyS3;No ttyS3 */
- # undef TTYS3_DEV /* UART3=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */
- # else
- # undef TTYS1_DEV /* UART3=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
- # endif
- # undef TTYS2_DEV /* No ttyS2 */
- # undef TTYS3_DEV /* No ttyS3 */
- # endif
- # endif
- # endif
- #endif /* CONFIG_16550_SERIAL_DISABLE_REORDERING */
- /****************************************************************************
- * Private Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: u16550_serialin
- ****************************************************************************/
- static inline uart_datawidth_t u16550_serialin(FAR struct u16550_s *priv, int offset)
- {
- #ifdef CONFIG_SERIAL_UART_ARCH_MMIO
- return *((FAR volatile uart_addrwidth_t *)priv->uartbase + offset);
- #else
- return uart_getreg(priv->uartbase, offset);
- #endif
- }
- /****************************************************************************
- * Name: u16550_serialout
- ****************************************************************************/
- static inline void u16550_serialout(FAR struct u16550_s *priv, int offset,
- uart_datawidth_t value)
- {
- #ifdef CONFIG_SERIAL_UART_ARCH_MMIO
- *((FAR volatile uart_addrwidth_t *)priv->uartbase + offset) = value;
- #else
- uart_putreg(priv->uartbase, offset, value);
- #endif
- }
- /****************************************************************************
- * Name: u16550_disableuartint
- ****************************************************************************/
- static inline void u16550_disableuartint(FAR struct u16550_s *priv,
- FAR uart_datawidth_t *ier)
- {
- if (ier)
- {
- *ier = priv->ier & UART_IER_ALLIE;
- }
- priv->ier &= ~UART_IER_ALLIE;
- u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
- }
- /****************************************************************************
- * Name: u16550_restoreuartint
- ****************************************************************************/
- static inline void u16550_restoreuartint(FAR struct u16550_s *priv,
- uint32_t ier)
- {
- priv->ier |= ier & UART_IER_ALLIE;
- u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
- }
- /****************************************************************************
- * Name: u16550_enablebreaks
- ****************************************************************************/
- static inline void u16550_enablebreaks(FAR struct u16550_s *priv,
- bool enable)
- {
- uint32_t lcr = u16550_serialin(priv, UART_LCR_OFFSET);
- if (enable)
- {
- lcr |= UART_LCR_BRK;
- }
- else
- {
- lcr &= ~UART_LCR_BRK;
- }
- u16550_serialout(priv, UART_LCR_OFFSET, lcr);
- }
- /****************************************************************************
- * Name: u16550_divisor
- *
- * Description:
- * Select a divider to produce the BAUD from the UART_CLK.
- *
- * BAUD = UART_CLK / (16 * DL), or
- * DIV = UART_CLK / BAUD / 16
- *
- * Ignoring the fractional divider for now.
- *
- ****************************************************************************/
- #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);
- }
- #endif
- /****************************************************************************
- * Name: u16550_setup
- *
- * Description:
- * Configure the UART baud, bits, parity, fifos, etc. This
- * method is called the first time that the serial port is
- * opened.
- *
- ****************************************************************************/
- 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 lcr;
- #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
- uint32_t mcr;
- #endif
- /* Clear fifos */
- u16550_serialout(priv, UART_FCR_OFFSET,
- (UART_FCR_RXRST | UART_FCR_TXRST));
- /* Set trigger */
- u16550_serialout(priv, UART_FCR_OFFSET,
- (UART_FCR_FIFOEN | UART_FCR_RXTRIGGER_8));
- /* Set up the IER */
- priv->ier = u16550_serialin(priv, UART_IER_OFFSET);
- /* Set up the LCR */
- lcr = 0;
- switch (priv->bits)
- {
- case 5 :
- lcr |= UART_LCR_WLS_5BIT;
- break;
- case 6 :
- lcr |= UART_LCR_WLS_6BIT;
- break;
- case 7 :
- lcr |= UART_LCR_WLS_7BIT;
- break;
- default:
- case 8 :
- lcr |= UART_LCR_WLS_8BIT;
- break;
- }
- if (priv->stopbits2)
- {
- lcr |= UART_LCR_STB;
- }
- if (priv->parity == 1)
- {
- lcr |= UART_LCR_PEN;
- }
- else if (priv->parity == 2)
- {
- lcr |= (UART_LCR_PEN | UART_LCR_EPS);
- }
- /* Enter DLAB=1 */
- u16550_serialout(priv, UART_LCR_OFFSET, (lcr | UART_LCR_DLAB));
- /* Set the BAUD divisor */
- div = u16550_divisor(priv);
- u16550_serialout(priv, UART_DLM_OFFSET, div >> 8);
- u16550_serialout(priv, UART_DLL_OFFSET, div & 0xff);
- /* Clear DLAB */
- u16550_serialout(priv, UART_LCR_OFFSET, lcr);
- /* Configure the FIFOs */
- u16550_serialout(priv, UART_FCR_OFFSET,
- (UART_FCR_RXTRIGGER_8 | UART_FCR_TXRST | UART_FCR_RXRST |
- UART_FCR_FIFOEN));
- /* Set up the auto flow control */
- #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
- mcr = u16550_serialin(priv, UART_MCR_OFFSET);
- if (priv->flow)
- {
- mcr |= UART_MCR_AFCE;
- }
- else
- {
- mcr &= ~UART_MCR_AFCE;
- }
- mcr |= UART_MCR_RTS;
- u16550_serialout(priv, UART_MCR_OFFSET, mcr);
- #endif /* defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL) */
- #endif
- return OK;
- }
- /****************************************************************************
- * Name: u16550_shutdown
- *
- * Description:
- * Disable the UART. This method is called when the serial
- * port is closed
- *
- ****************************************************************************/
- static void u16550_shutdown(struct uart_dev_s *dev)
- {
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- u16550_disableuartint(priv, NULL);
- }
- /****************************************************************************
- * Name: u16550_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 when 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 u16550_attach(struct uart_dev_s *dev)
- {
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- int ret;
- /* Attach and enable the IRQ */
- ret = irq_attach(priv->irq, u16550_interrupt, dev);
- #ifndef CONFIG_ARCH_NOINTC
- if (ret == OK)
- {
- /* Enable the interrupt (RX and TX interrupts are still disabled
- * in the UART
- */
- up_enable_irq(priv->irq);
- }
- #endif
- return ret;
- }
- /****************************************************************************
- * Name: u16550_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 u16550_detach(FAR struct uart_dev_s *dev)
- {
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- up_disable_irq(priv->irq);
- irq_detach(priv->irq);
- }
- /****************************************************************************
- * Name: u16550_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
- * appropriate u16550_s structure in order to call these functions.
- *
- ****************************************************************************/
- static int u16550_interrupt(int irq, FAR void *context, FAR void *arg)
- {
- FAR struct uart_dev_s *dev = (struct uart_dev_s *)arg;
- FAR struct u16550_s *priv;
- uint32_t status;
- int passes;
- DEBUGASSERT(dev != NULL && dev->priv != NULL);
- priv = (FAR struct u16550_s *)dev->priv;
- /* Loop until there are no characters to be transferred or,
- * until we have been looping for a long time.
- */
- for (passes = 0; passes < 256; passes++)
- {
- /* Get the current UART status and check for loop
- * termination conditions
- */
- status = u16550_serialin(priv, UART_IIR_OFFSET);
- /* The UART_IIR_INTSTATUS bit should be zero if there are pending
- * interrupts
- */
- if ((status & UART_IIR_INTSTATUS) != 0)
- {
- /* Break out of the loop when there is no longer a
- * pending interrupt
- */
- break;
- }
- /* Handle the interrupt by its interrupt ID field */
- switch (status & UART_IIR_INTID_MASK)
- {
- /* Handle incoming, receive bytes (with or without timeout) */
- case UART_IIR_INTID_RDA:
- case UART_IIR_INTID_CTI:
- {
- uart_recvchars(dev);
- break;
- }
- /* Handle outgoing, transmit bytes */
- case UART_IIR_INTID_THRE:
- {
- uart_xmitchars(dev);
- break;
- }
- /* Just clear modem status interrupts (UART1 only) */
- case UART_IIR_INTID_MSI:
- {
- /* Read the modem status register (MSR) to clear */
- status = u16550_serialin(priv, UART_MSR_OFFSET);
- sinfo("MSR: %02x\n", status);
- break;
- }
- /* Just clear any line status interrupts */
- case UART_IIR_INTID_RLS:
- {
- /* Read the line status register (LSR) to clear */
- status = u16550_serialin(priv, UART_LSR_OFFSET);
- sinfo("LSR: %02x\n", status);
- break;
- }
- /* There should be no other values */
- default:
- {
- serr("ERROR: Unexpected IIR: %02x\n", status);
- break;
- }
- }
- }
- return OK;
- }
- /****************************************************************************
- * Name: u16550_ioctl
- *
- * Description:
- * All ioctl calls will be routed through this method
- *
- ****************************************************************************/
- static int u16550_ioctl(struct file *filep, int cmd, unsigned long arg)
- {
- FAR struct inode *inode = filep->f_inode;
- FAR struct uart_dev_s *dev = inode->i_private;
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- int ret;
- #ifdef CONFIG_SERIAL_UART_ARCH_IOCTL
- ret = uart_ioctl(filep, cmd, arg);
- if (ret != -ENOTTY)
- {
- return ret;
- }
- #else
- ret = OK;
- #endif
- switch (cmd)
- {
- #ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
- case TIOCSERGSTRUCT:
- {
- FAR struct u16550_s *user = (FAR struct u16550_s *)arg;
- if (!user)
- {
- ret = -EINVAL;
- }
- else
- {
- memcpy(user, dev, sizeof(struct u16550_s));
- }
- }
- break;
- #endif
- case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
- {
- irqstate_t flags = enter_critical_section();
- u16550_enablebreaks(priv, true);
- leave_critical_section(flags);
- }
- break;
- case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */
- {
- irqstate_t flags;
- flags = enter_critical_section();
- u16550_enablebreaks(priv, false);
- leave_critical_section(flags);
- }
- break;
- #if defined(CONFIG_SERIAL_TERMIOS) && !defined(CONFIG_16550_SUPRESS_CONFIG)
- case TCGETS:
- {
- FAR struct termios *termiosp = (FAR struct termios *)arg;
- irqstate_t flags;
- if (!termiosp)
- {
- ret = -EINVAL;
- break;
- }
- flags = enter_critical_section();
- cfsetispeed(termiosp, priv->baud);
- termiosp->c_cflag = ((priv->parity != 0) ? PARENB : 0) |
- ((priv->parity == 1) ? PARODD : 0);
- termiosp->c_cflag |= (priv->stopbits2) ? CSTOPB : 0;
- #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
- termiosp->c_cflag |= priv->flow ? CRTSCTS : 0;
- #endif
- switch (priv->bits)
- {
- case 5:
- termiosp->c_cflag |= CS5;
- break;
- case 6:
- termiosp->c_cflag |= CS6;
- break;
- case 7:
- termiosp->c_cflag |= CS7;
- break;
- case 8:
- default:
- termiosp->c_cflag |= CS8;
- break;
- }
- leave_critical_section(flags);
- }
- break;
- case TCSETS:
- {
- FAR struct termios *termiosp = (FAR struct termios *)arg;
- irqstate_t flags;
- if (!termiosp)
- {
- ret = -EINVAL;
- break;
- }
- flags = enter_critical_section();
- switch (termiosp->c_cflag & CSIZE)
- {
- case CS5:
- priv->bits = 5;
- break;
- case CS6:
- priv->bits = 6;
- break;
- case CS7:
- priv->bits = 7;
- break;
- case CS8:
- default:
- priv->bits = 8;
- break;
- }
- if ((termiosp->c_cflag & PARENB) != 0)
- {
- priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2;
- }
- else
- {
- priv->parity = 0;
- }
- priv->baud = cfgetispeed(termiosp);
- priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0;
- #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
- priv->flow = (termiosp->c_cflag & CRTSCTS) != 0;
- #endif
- u16550_setup(dev);
- leave_critical_section(flags);
- }
- break;
- #endif
- default:
- ret = -ENOTTY;
- break;
- }
- return ret;
- }
- /****************************************************************************
- * Name: u16550_receive
- *
- * Description:
- * Called (usually) from the interrupt level to receive one
- * character from the UART. Error bits associated with the
- * receipt are provided in the return 'status'.
- *
- ****************************************************************************/
- static int u16550_receive(struct uart_dev_s *dev, uint32_t *status)
- {
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- uint32_t rbr;
- *status = u16550_serialin(priv, UART_LSR_OFFSET);
- rbr = u16550_serialin(priv, UART_RBR_OFFSET);
- return rbr;
- }
- /****************************************************************************
- * Name: u16550_rxint
- *
- * Description:
- * Call to enable or disable RX interrupts
- *
- ****************************************************************************/
- static void u16550_rxint(struct uart_dev_s *dev, bool enable)
- {
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- if (enable)
- {
- priv->ier |= UART_IER_ERBFI;
- }
- else
- {
- priv->ier &= ~UART_IER_ERBFI;
- }
- u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
- }
- /****************************************************************************
- * Name: u16550_rxavailable
- *
- * Description:
- * Return true if the receive fifo is not empty
- *
- ****************************************************************************/
- static bool u16550_rxavailable(struct uart_dev_s *dev)
- {
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- return ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_DR) != 0);
- }
- /****************************************************************************
- * Name: u16550_dma*
- *
- * Description:
- * Stubbed out DMA-related methods
- *
- ****************************************************************************/
- #ifdef CONFIG_SERIAL_IFLOWCONTROL
- static bool u16550_rxflowcontrol(struct uart_dev_s *dev, unsigned int nbuffered,
- bool upper)
- {
- #ifndef CONFIG_16550_SUPRESS_CONFIG
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- if (priv->flow)
- {
- /* Disable Rx interrupt to prevent more data being from
- * peripheral if the RX buffer is near full. When hardware
- * RTS is enabled, this will prevent more data from coming
- * in. Otherwise, enable Rx interrupt to make sure that more
- * input is received.
- */
- u16550_rxint(dev, !upper);
- return true;
- }
- #endif
- return false;
- }
- #endif
- /****************************************************************************
- * Name: u16550_dma*
- *
- * Description:
- * Stub functions used when serial DMA is enabled.
- *
- ****************************************************************************/
- #ifdef CONFIG_SERIAL_DMA
- static void u16550_dmasend(FAR struct uart_dev_s *dev)
- {
- }
- static void u16550_dmareceive(FAR struct uart_dev_s *dev)
- {
- }
- static void u16550_dmarxfree(FAR struct uart_dev_s *dev)
- {
- }
- static void u16550_dmatxavail(FAR struct uart_dev_s *dev)
- {
- }
- #endif
- /****************************************************************************
- * Name: u16550_send
- *
- * Description:
- * This method will send one byte on the UART
- *
- ****************************************************************************/
- static void u16550_send(struct uart_dev_s *dev, int ch)
- {
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- u16550_serialout(priv, UART_THR_OFFSET, (uart_datawidth_t)ch);
- }
- /****************************************************************************
- * Name: u16550_txint
- *
- * Description:
- * Call to enable or disable TX interrupts
- *
- ****************************************************************************/
- static void u16550_txint(struct uart_dev_s *dev, bool enable)
- {
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- irqstate_t flags;
- flags = enter_critical_section();
- if (enable)
- {
- priv->ier |= UART_IER_ETBEI;
- u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
- /* Fake a TX interrupt here by just calling uart_xmitchars() with
- * interrupts disabled (note this may recurse).
- */
- uart_xmitchars(dev);
- }
- else
- {
- priv->ier &= ~UART_IER_ETBEI;
- u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
- }
- leave_critical_section(flags);
- }
- /****************************************************************************
- * Name: u16550_txready
- *
- * Description:
- * Return true if the tranmsit fifo is not full
- *
- ****************************************************************************/
- static bool u16550_txready(struct uart_dev_s *dev)
- {
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- return ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_THRE) != 0);
- }
- /****************************************************************************
- * Name: u16550_txempty
- *
- * Description:
- * Return true if the transmit fifo is empty
- *
- ****************************************************************************/
- static bool u16550_txempty(struct uart_dev_s *dev)
- {
- FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
- return ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_TEMT) != 0);
- }
- /****************************************************************************
- * Name: u16550_putc
- *
- * Description:
- * Write one character to the UART (polled)
- *
- ****************************************************************************/
- #ifdef HAVE_16550_CONSOLE
- static void u16550_putc(FAR struct u16550_s *priv, int ch)
- {
- while ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_THRE) == 0);
- u16550_serialout(priv, UART_THR_OFFSET, (uart_datawidth_t)ch);
- }
- #endif
- /****************************************************************************
- * Public Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: up_earlyserialinit
- *
- * Description:
- * Performs the low level UART initialization early in debug so that the
- * serial console will be available during bootup. This must be called
- * before uart_serialinit.
- *
- * NOTE: Configuration of the CONSOLE UART was performed by uart_lowsetup()
- * very early in the boot sequence.
- *
- ****************************************************************************/
- void up_earlyserialinit(void)
- {
- /* Configuration whichever one is the console */
- #ifdef CONSOLE_DEV
- CONSOLE_DEV.isconsole = true;
- #ifndef CONFIG_16550_SUPRESS_INITIAL_CONFIG
- u16550_setup(&CONSOLE_DEV);
- #endif
- #endif
- }
- /****************************************************************************
- * Name: up_serialinit
- *
- * Description:
- * Register serial console and serial ports. This assumes that
- * up_earlyserialinit was called previously.
- *
- ****************************************************************************/
- void up_serialinit(void)
- {
- #ifdef CONSOLE_DEV
- (void)uart_register("/dev/console", &CONSOLE_DEV);
- #endif
- #ifdef TTYS0_DEV
- (void)uart_register("/dev/ttyS0", &TTYS0_DEV);
- #endif
- #ifdef TTYS1_DEV
- (void)uart_register("/dev/ttyS1", &TTYS1_DEV);
- #endif
- #ifdef TTYS2_DEV
- (void)uart_register("/dev/ttyS2", &TTYS2_DEV);
- #endif
- #ifdef TTYS3_DEV
- (void)uart_register("/dev/ttyS3", &TTYS3_DEV);
- #endif
- }
- /****************************************************************************
- * Name: up_putc
- *
- * Description:
- * Provide priority, low-level access to support OS debug writes
- *
- ****************************************************************************/
- #ifdef HAVE_16550_CONSOLE
- int up_putc(int ch)
- {
- FAR struct u16550_s *priv = (FAR struct u16550_s *)CONSOLE_DEV.priv;
- uart_datawidth_t ier;
- u16550_disableuartint(priv, &ier);
- /* Check for LF */
- if (ch == '\n')
- {
- /* Add CR */
- u16550_putc(priv, '\r');
- }
- u16550_putc(priv, ch);
- u16550_restoreuartint(priv, ier);
- return ch;
- }
- #endif
- #endif /* CONFIG_16550_UART */
|