LCOV - code coverage report
Current view: top level - proj/xhdsswstaff1/ajaneeli/LocalBuilds/ZephyrProj/zephyr/drivers/serial - uart_ns16550.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 178 242 73.6 %
Date: 2025-01-01 10:14:44 Functions: 24 28 85.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 21 39 53.8 %

           Branch data     Line data    Source code
       1                 :            : /* ns16550.c - NS16550D serial driver */
       2                 :            : 
       3                 :            : #define DT_DRV_COMPAT ns16550
       4                 :            : 
       5                 :            : /*
       6                 :            :  * Copyright (c) 2010, 2012-2015 Wind River Systems, Inc.
       7                 :            :  * Copyright (c) 2020-2023 Intel Corp.
       8                 :            :  *
       9                 :            :  * SPDX-License-Identifier: Apache-2.0
      10                 :            :  */
      11                 :            : 
      12                 :            : /**
      13                 :            :  * @brief NS16550 Serial Driver
      14                 :            :  *
      15                 :            :  * This is the driver for the Intel NS16550 UART Chip used on the PC 386.
      16                 :            :  * It uses the SCCs in asynchronous mode only.
      17                 :            :  *
      18                 :            :  * Before individual UART port can be used, uart_ns16550_port_init() has to be
      19                 :            :  * called to setup the port.
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <errno.h>
      23                 :            : #include <zephyr/kernel.h>
      24                 :            : #include <zephyr/arch/cpu.h>
      25                 :            : #include <zephyr/types.h>
      26                 :            : 
      27                 :            : #include <zephyr/init.h>
      28                 :            : #include <zephyr/toolchain.h>
      29                 :            : #include <zephyr/linker/sections.h>
      30                 :            : #include <zephyr/drivers/uart.h>
      31                 :            : #include <zephyr/drivers/clock_control.h>
      32                 :            : #include <zephyr/pm/policy.h>
      33                 :            : #include <zephyr/sys/sys_io.h>
      34                 :            : #include <zephyr/spinlock.h>
      35                 :            : #include <zephyr/irq.h>
      36                 :            : 
      37                 :            : #if defined(CONFIG_PINCTRL)
      38                 :            : #include <zephyr/drivers/pinctrl.h>
      39                 :            : #endif
      40                 :            : 
      41                 :            : #include <zephyr/drivers/serial/uart_ns16550.h>
      42                 :            : #include <zephyr/logging/log.h>
      43                 :            : 
      44                 :            : LOG_MODULE_REGISTER(uart_ns16550, CONFIG_UART_LOG_LEVEL);
      45                 :            : 
      46                 :            : #define UART_NS16550_PCP_ENABLED DT_ANY_INST_HAS_PROP_STATUS_OKAY(pcp)
      47                 :            : #define UART_NS16550_DLF_ENABLED DT_ANY_INST_HAS_PROP_STATUS_OKAY(dlf)
      48                 :            : #define UART_NS16550_DMAS_ENABLED DT_ANY_INST_HAS_PROP_STATUS_OKAY(dmas)
      49                 :            : 
      50                 :            : #if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie)
      51                 :            : BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE");
      52                 :            : #include <zephyr/drivers/pcie/pcie.h>
      53                 :            : #endif
      54                 :            : 
      55                 :            : /* Is UART module 'resets' line property defined */
      56                 :            : #define UART_NS16550_RESET_ENABLED DT_ANY_INST_HAS_PROP_STATUS_OKAY(resets)
      57                 :            : 
      58                 :            : #if UART_NS16550_RESET_ENABLED
      59                 :            : #include <zephyr/drivers/reset.h>
      60                 :            : #endif
      61                 :            : 
      62                 :            : #if defined(CONFIG_UART_ASYNC_API)
      63                 :            : #include <zephyr/drivers/dma.h>
      64                 :            : #include <assert.h>
      65                 :            : 
      66                 :            : #if defined(CONFIG_UART_NS16550_INTEL_LPSS_DMA)
      67                 :            : #include <zephyr/drivers/dma/dma_intel_lpss.h>
      68                 :            : #endif
      69                 :            : 
      70                 :            : #endif
      71                 :            : 
      72                 :            : /* If any node has property io-mapped set, we need to support IO port
      73                 :            :  * access in the code and device config struct.
      74                 :            :  *
      75                 :            :  * Note that DT_ANY_INST_HAS_PROP_STATUS_OKAY() always returns true
      76                 :            :  * as io-mapped property is considered always exists and present,
      77                 :            :  * even if its value is zero. Therefore we cannot use it, and has to
      78                 :            :  * resort to the follow helper to see if any okay nodes have io-mapped
      79                 :            :  * as 1.
      80                 :            :  */
      81                 :            : #define UART_NS16550_DT_PROP_IOMAPPED_HELPER(inst, prop, def) \
      82                 :            :         DT_INST_PROP_OR(inst, prop, def) ||
      83                 :            : 
      84                 :            : #define UART_NS16550_IOPORT_ENABLED \
      85                 :            :         (DT_INST_FOREACH_STATUS_OKAY_VARGS(UART_NS16550_DT_PROP_IOMAPPED_HELPER, io_mapped, 0) 0)
      86                 :            : 
      87                 :            : /* register definitions */
      88                 :            : 
      89                 :            : #define REG_THR 0x00  /* Transmitter holding reg.       */
      90                 :            : #define REG_RDR 0x00  /* Receiver data reg.             */
      91                 :            : #define REG_BRDL 0x00 /* Baud rate divisor (LSB)        */
      92                 :            : #define REG_BRDH 0x01 /* Baud rate divisor (MSB)        */
      93                 :            : #define REG_IER 0x01  /* Interrupt enable reg.          */
      94                 :            : #define REG_IIR 0x02  /* Interrupt ID reg.              */
      95                 :            : #define REG_FCR 0x02  /* FIFO control reg.              */
      96                 :            : #define REG_LCR 0x03  /* Line control reg.              */
      97                 :            : #define REG_MDC 0x04  /* Modem control reg.             */
      98                 :            : #define REG_LSR 0x05  /* Line status reg.               */
      99                 :            : #define REG_MSR 0x06  /* Modem status reg.              */
     100                 :            : #define REG_DLF 0xC0  /* Divisor Latch Fraction         */
     101                 :            : #define REG_PCP 0x200 /* PRV_CLOCK_PARAMS (Apollo Lake) */
     102                 :            : #define REG_MDR1 0x08 /* Mode control reg. (TI_K3) */
     103                 :            : 
     104                 :            : #if defined(CONFIG_UART_NS16550_INTEL_LPSS_DMA)
     105                 :            : #define REG_LPSS_SRC_TRAN 0xAF8 /* SRC Transfer LPSS DMA */
     106                 :            : #define REG_LPSS_CLR_SRC_TRAN 0xB48 /* Clear SRC Tran LPSS DMA */
     107                 :            : #define REG_LPSS_MST 0xB20 /* Mask SRC Transfer LPSS DMA */
     108                 :            : #endif
     109                 :            : 
     110                 :            : /* equates for interrupt enable register */
     111                 :            : 
     112                 :            : #define IER_RXRDY 0x01 /* receiver data ready */
     113                 :            : #define IER_TBE 0x02   /* transmit bit enable */
     114                 :            : #define IER_LSR 0x04   /* line status interrupts */
     115                 :            : #define IER_MSI 0x08   /* modem status interrupts */
     116                 :            : 
     117                 :            : /* equates for interrupt identification register */
     118                 :            : 
     119                 :            : #define IIR_MSTAT 0x00 /* modem status interrupt  */
     120                 :            : #define IIR_NIP   0x01 /* no interrupt pending    */
     121                 :            : #define IIR_THRE  0x02 /* transmit holding register empty interrupt */
     122                 :            : #define IIR_RBRF  0x04 /* receiver buffer register full interrupt */
     123                 :            : #define IIR_LS    0x06 /* receiver line status interrupt */
     124                 :            : #define IIR_MASK  0x07 /* interrupt id bits mask  */
     125                 :            : #define IIR_ID    0x06 /* interrupt ID mask without NIP */
     126                 :            : #define IIR_FE    0xC0 /* FIFO mode enabled */
     127                 :            : #define IIR_CH    0x0C /* Character timeout*/
     128                 :            : 
     129                 :            : /* equates for FIFO control register */
     130                 :            : 
     131                 :            : #define FCR_FIFO 0x01    /* enable XMIT and RCVR FIFO */
     132                 :            : #define FCR_RCVRCLR 0x02 /* clear RCVR FIFO */
     133                 :            : #define FCR_XMITCLR 0x04 /* clear XMIT FIFO */
     134                 :            : 
     135                 :            : /* equates for Apollo Lake clock control register (PRV_CLOCK_PARAMS) */
     136                 :            : 
     137                 :            : #define PCP_UPDATE 0x80000000 /* update clock */
     138                 :            : #define PCP_EN 0x00000001     /* enable clock output */
     139                 :            : 
     140                 :            : /* Fields for TI K3 UART module */
     141                 :            : 
     142                 :            : #define MDR1_MODE_SELECT_FIELD_MASK             BIT_MASK(3)
     143                 :            : #define MDR1_MODE_SELECT_FIELD_SHIFT            BIT_MASK(0)
     144                 :            : 
     145                 :            : /* Modes available for TI K3 UART module */
     146                 :            : 
     147                 :            : #define MDR1_STD_MODE                                   (0)
     148                 :            : #define MDR1_SIR_MODE                                   (1)
     149                 :            : #define MDR1_UART_16X                                   (2)
     150                 :            : #define MDR1_UART_13X                                   (3)
     151                 :            : #define MDR1_MIR_MODE                                   (4)
     152                 :            : #define MDR1_FIR_MODE                                   (5)
     153                 :            : #define MDR1_CIR_MODE                                   (6)
     154                 :            : #define MDR1_DISABLE                                    (7)
     155                 :            : 
     156                 :            : /*
     157                 :            :  * Per PC16550D (Literature Number: SNLS378B):
     158                 :            :  *
     159                 :            :  * RXRDY, Mode 0: When in the 16450 Mode (FCR0 = 0) or in
     160                 :            :  * the FIFO Mode (FCR0 = 1, FCR3 = 0) and there is at least 1
     161                 :            :  * character in the RCVR FIFO or RCVR holding register, the
     162                 :            :  * RXRDY pin (29) will be low active. Once it is activated the
     163                 :            :  * RXRDY pin will go inactive when there are no more charac-
     164                 :            :  * ters in the FIFO or holding register.
     165                 :            :  *
     166                 :            :  * RXRDY, Mode 1: In the FIFO Mode (FCR0 = 1) when the
     167                 :            :  * FCR3 = 1 and the trigger level or the timeout has been
     168                 :            :  * reached, the RXRDY pin will go low active. Once it is acti-
     169                 :            :  * vated it will go inactive when there are no more characters
     170                 :            :  * in the FIFO or holding register.
     171                 :            :  *
     172                 :            :  * TXRDY, Mode 0: In the 16450 Mode (FCR0 = 0) or in the
     173                 :            :  * FIFO Mode (FCR0 = 1, FCR3 = 0) and there are no charac-
     174                 :            :  * ters in the XMIT FIFO or XMIT holding register, the TXRDY
     175                 :            :  * pin (24) will be low active. Once it is activated the TXRDY
     176                 :            :  * pin will go inactive after the first character is loaded into the
     177                 :            :  * XMIT FIFO or holding register.
     178                 :            :  *
     179                 :            :  * TXRDY, Mode 1: In the FIFO Mode (FCR0 = 1) when
     180                 :            :  * FCR3 = 1 and there are no characters in the XMIT FIFO, the
     181                 :            :  * TXRDY pin will go low active. This pin will become inactive
     182                 :            :  * when the XMIT FIFO is completely full.
     183                 :            :  */
     184                 :            : #define FCR_MODE0 0x00 /* set receiver in mode 0 */
     185                 :            : #define FCR_MODE1 0x08 /* set receiver in mode 1 */
     186                 :            : 
     187                 :            : /* RCVR FIFO interrupt levels: trigger interrupt with this bytes in FIFO */
     188                 :            : #define FCR_FIFO_1 0x00  /* 1 byte in RCVR FIFO */
     189                 :            : #define FCR_FIFO_4 0x40  /* 4 bytes in RCVR FIFO */
     190                 :            : #define FCR_FIFO_8 0x80  /* 8 bytes in RCVR FIFO */
     191                 :            : #define FCR_FIFO_14 0xC0 /* 14 bytes in RCVR FIFO */
     192                 :            : 
     193                 :            : /*
     194                 :            :  * UART NS16750 supports 64 bytes FIFO, which can be enabled
     195                 :            :  * via the FCR register
     196                 :            :  */
     197                 :            : #define FCR_FIFO_64 0x20 /* Enable 64 bytes FIFO */
     198                 :            : 
     199                 :            : /* constants for line control register */
     200                 :            : 
     201                 :            : #define LCR_CS5 0x00   /* 5 bits data size */
     202                 :            : #define LCR_CS6 0x01   /* 6 bits data size */
     203                 :            : #define LCR_CS7 0x02   /* 7 bits data size */
     204                 :            : #define LCR_CS8 0x03   /* 8 bits data size */
     205                 :            : #define LCR_2_STB 0x04 /* 2 stop bits */
     206                 :            : #define LCR_1_STB 0x00 /* 1 stop bit */
     207                 :            : #define LCR_PEN 0x08   /* parity enable */
     208                 :            : #define LCR_PDIS 0x00  /* parity disable */
     209                 :            : #define LCR_EPS 0x10   /* even parity select */
     210                 :            : #define LCR_SP 0x20    /* stick parity select */
     211                 :            : #define LCR_SBRK 0x40  /* break control bit */
     212                 :            : #define LCR_DLAB 0x80  /* divisor latch access enable */
     213                 :            : 
     214                 :            : /* constants for the modem control register */
     215                 :            : 
     216                 :            : #define MCR_DTR 0x01  /* dtr output */
     217                 :            : #define MCR_RTS 0x02  /* rts output */
     218                 :            : #define MCR_OUT1 0x04 /* output #1 */
     219                 :            : #define MCR_OUT2 0x08 /* output #2 */
     220                 :            : #define MCR_LOOP 0x10 /* loop back */
     221                 :            : #define MCR_AFCE 0x20 /* auto flow control enable */
     222                 :            : 
     223                 :            : /* constants for line status register */
     224                 :            : 
     225                 :            : #define LSR_RXRDY 0x01 /* receiver data available */
     226                 :            : #define LSR_OE 0x02    /* overrun error */
     227                 :            : #define LSR_PE 0x04    /* parity error */
     228                 :            : #define LSR_FE 0x08    /* framing error */
     229                 :            : #define LSR_BI 0x10    /* break interrupt */
     230                 :            : #define LSR_EOB_MASK 0x1E /* Error or Break mask */
     231                 :            : #define LSR_THRE 0x20  /* transmit holding register empty */
     232                 :            : #define LSR_TEMT 0x40  /* transmitter empty */
     233                 :            : 
     234                 :            : /* constants for modem status register */
     235                 :            : 
     236                 :            : #define MSR_DCTS 0x01 /* cts change */
     237                 :            : #define MSR_DDSR 0x02 /* dsr change */
     238                 :            : #define MSR_DRI 0x04  /* ring change */
     239                 :            : #define MSR_DDCD 0x08 /* data carrier change */
     240                 :            : #define MSR_CTS 0x10  /* complement of cts */
     241                 :            : #define MSR_DSR 0x20  /* complement of dsr */
     242                 :            : #define MSR_RI 0x40   /* complement of ring signal */
     243                 :            : #define MSR_DCD 0x80  /* complement of dcd */
     244                 :            : 
     245                 :            : #define THR(dev) (get_port(dev) + (REG_THR * reg_interval(dev)))
     246                 :            : #define RDR(dev) (get_port(dev) + (REG_RDR * reg_interval(dev)))
     247                 :            : #define BRDL(dev) (get_port(dev) + (REG_BRDL * reg_interval(dev)))
     248                 :            : #define BRDH(dev) (get_port(dev) + (REG_BRDH * reg_interval(dev)))
     249                 :            : #define IER(dev) (get_port(dev) + (REG_IER * reg_interval(dev)))
     250                 :            : #define IIR(dev) (get_port(dev) + (REG_IIR * reg_interval(dev)))
     251                 :            : #define FCR(dev) (get_port(dev) + (REG_FCR * reg_interval(dev)))
     252                 :            : #define LCR(dev) (get_port(dev) + (REG_LCR * reg_interval(dev)))
     253                 :            : #define MDC(dev) (get_port(dev) + (REG_MDC * reg_interval(dev)))
     254                 :            : #define LSR(dev) (get_port(dev) + (REG_LSR * reg_interval(dev)))
     255                 :            : #define MSR(dev) (get_port(dev) + (REG_MSR * reg_interval(dev)))
     256                 :            : #define MDR1(dev) (get_port(dev) + (REG_MDR1 * reg_interval(dev)))
     257                 :            : #define DLF(dev) (get_port(dev) + REG_DLF)
     258                 :            : #define PCP(dev) (get_port(dev) + REG_PCP)
     259                 :            : 
     260                 :            : #if defined(CONFIG_UART_NS16550_INTEL_LPSS_DMA)
     261                 :            : #define SRC_TRAN(dev) (get_port(dev) + REG_LPSS_SRC_TRAN)
     262                 :            : #define CLR_SRC_TRAN(dev) (get_port(dev) + REG_LPSS_CLR_SRC_TRAN)
     263                 :            : #define MST(dev) (get_port(dev) + REG_LPSS_MST)
     264                 :            : 
     265                 :            : #define UNMASK_LPSS_INT(chan) (BIT(chan) | (BIT(8) << chan)) /* unmask LPSS DMA Interrupt */
     266                 :            : #endif
     267                 :            : 
     268                 :            : #define IIRC(dev) (((struct uart_ns16550_dev_data *)(dev)->data)->iir_cache)
     269                 :            : 
     270                 :            : #ifdef CONFIG_UART_NS16550_ITE_HIGH_SPEED_BUADRATE
     271                 :            : /* Register definitions (ITE_IT8XXX2) */
     272                 :            : #define REG_ECSPMR 0x08 /* EC Serial port mode reg */
     273                 :            : 
     274                 :            : /* Fields for ITE IT8XXX2 UART module */
     275                 :            : #define ECSPMR_ECHS 0x02  /* EC high speed select */
     276                 :            : 
     277                 :            : /* IT8XXX2 UART high speed baud rate settings */
     278                 :            : #define UART_BAUDRATE_115200 115200
     279                 :            : #define UART_BAUDRATE_230400 230400
     280                 :            : #define UART_BAUDRATE_460800 460800
     281                 :            : #define IT8XXX2_230400_DIVISOR 32770
     282                 :            : #define IT8XXX2_460800_DIVISOR 32769
     283                 :            : 
     284                 :            : #define ECSPMR(dev) (get_port(dev) + REG_ECSPMR * reg_interval(dev))
     285                 :            : #endif
     286                 :            : 
     287                 :            : #if defined(CONFIG_UART_ASYNC_API)
     288                 :            : struct uart_ns16550_rx_dma_params {
     289                 :            :         const struct device *dma_dev;
     290                 :            :         uint8_t dma_channel;
     291                 :            :         struct dma_config dma_cfg;
     292                 :            :         struct dma_block_config active_dma_block;
     293                 :            :         uint8_t *buf;
     294                 :            :         size_t buf_len;
     295                 :            :         size_t offset;
     296                 :            :         size_t counter;
     297                 :            :         struct k_work_delayable timeout_work;
     298                 :            :         size_t timeout_us;
     299                 :            : };
     300                 :            : 
     301                 :            : struct uart_ns16550_tx_dma_params {
     302                 :            :         const struct device *dma_dev;
     303                 :            :         uint8_t dma_channel;
     304                 :            :         struct dma_config dma_cfg;
     305                 :            :         struct dma_block_config active_dma_block;
     306                 :            :         const uint8_t *buf;
     307                 :            :         size_t buf_len;
     308                 :            :         struct k_work_delayable timeout_work;
     309                 :            :         size_t timeout_us;
     310                 :            : };
     311                 :            : 
     312                 :            : struct uart_ns16550_async_data {
     313                 :            :         const struct device *uart_dev;
     314                 :            :         struct uart_ns16550_tx_dma_params tx_dma_params;
     315                 :            :         struct uart_ns16550_rx_dma_params rx_dma_params;
     316                 :            :         uint8_t *next_rx_buffer;
     317                 :            :         size_t next_rx_buffer_len;
     318                 :            :         uart_callback_t user_callback;
     319                 :            :         void *user_data;
     320                 :            : };
     321                 :            : 
     322                 :            : static void uart_ns16550_async_rx_timeout(struct k_work *work);
     323                 :            : static void uart_ns16550_async_tx_timeout(struct k_work *work);
     324                 :            : #endif
     325                 :            : 
     326                 :            : /* device config */
     327                 :            : struct uart_ns16550_device_config {
     328                 :            :         union {
     329                 :            :                 DEVICE_MMIO_ROM;
     330                 :            :                 uint32_t port;
     331                 :            :         };
     332                 :            :         uint32_t sys_clk_freq;
     333                 :            :         const struct device *clock_dev;
     334                 :            :         clock_control_subsys_t clock_subsys;
     335                 :            : #if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API)
     336                 :            :         uart_irq_config_func_t  irq_config_func;
     337                 :            : #endif
     338                 :            : #if UART_NS16550_PCP_ENABLED
     339                 :            :         uint32_t pcp;
     340                 :            : #endif
     341                 :            :         uint8_t reg_interval;
     342                 :            : #if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie)
     343                 :            :         struct pcie_dev *pcie;
     344                 :            : #endif
     345                 :            : #if defined(CONFIG_PINCTRL)
     346                 :            :         const struct pinctrl_dev_config *pincfg;
     347                 :            : #endif
     348                 :            : #if UART_NS16550_IOPORT_ENABLED
     349                 :            :         bool io_map;
     350                 :            : #endif
     351                 :            : #if UART_NS16550_RESET_ENABLED
     352                 :            :         struct reset_dt_spec reset_spec;
     353                 :            : #endif
     354                 :            : };
     355                 :            : 
     356                 :            : /** Device data structure */
     357                 :            : struct uart_ns16550_dev_data {
     358                 :            :         DEVICE_MMIO_RAM;
     359                 :            :         struct uart_config uart_config;
     360                 :            :         struct k_spinlock lock;
     361                 :            :         uint8_t fifo_size;
     362                 :            : 
     363                 :            : #ifdef CONFIG_UART_INTERRUPT_DRIVEN
     364                 :            :         uint8_t iir_cache;      /**< cache of IIR since it clears when read */
     365                 :            :         uart_irq_callback_user_data_t cb;  /**< Callback function pointer */
     366                 :            :         void *cb_data;  /**< Callback function arg */
     367                 :            : #endif
     368                 :            : 
     369                 :            : #if UART_NS16550_DLF_ENABLED
     370                 :            :         uint8_t dlf;            /**< DLF value */
     371                 :            : #endif
     372                 :            : 
     373                 :            : #if defined(CONFIG_UART_INTERRUPT_DRIVEN) && defined(CONFIG_PM)
     374                 :            :         bool tx_stream_on;
     375                 :            : #endif
     376                 :            : 
     377                 :            : #if defined(CONFIG_UART_ASYNC_API)
     378                 :            :         uint64_t phys_addr;
     379                 :            :         struct uart_ns16550_async_data async;
     380                 :            : #endif
     381                 :            : };
     382                 :            : 
     383                 :      91012 : static void ns16550_outbyte(const struct uart_ns16550_device_config *cfg,
     384                 :            :                             uintptr_t port, uint8_t val)
     385                 :            : {
     386                 :            : #if UART_NS16550_IOPORT_ENABLED
     387                 :            :         if (cfg->io_map) {
     388                 :            :                 if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) {
     389                 :            :                         sys_out32(val, port);
     390                 :            :                 } else {
     391                 :            :                         sys_out8(val, port);
     392                 :            :                 }
     393                 :            :         } else {
     394                 :            : #else
     395                 :            :         {
     396                 :            : #endif
     397                 :            :                 /* MMIO mapped */
     398                 :            :                 if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) {
     399                 :            :                         sys_write32(val, port);
     400                 :            :                 } else {
     401                 :      91012 :                         sys_write8(val, port);
     402                 :            :                 }
     403                 :            :         }
     404                 :      91012 : }
     405                 :            : 
     406                 :    1023608 : static uint8_t ns16550_inbyte(const struct uart_ns16550_device_config *cfg,
     407                 :            :                               uintptr_t port)
     408                 :            : {
     409                 :            : #if UART_NS16550_IOPORT_ENABLED
     410                 :            :         if (cfg->io_map) {
     411                 :            :                 if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) {
     412                 :            :                         return sys_in32(port);
     413                 :            :                 } else {
     414                 :            :                         return sys_in8(port);
     415                 :            :                 }
     416                 :            :         } else {
     417                 :            : #else
     418                 :            :         {
     419                 :            : #endif
     420                 :            :                 /* MMIO mapped */
     421                 :            :                 if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) {
     422                 :            :                         return sys_read32(port);
     423                 :            :                 } else {
     424                 :    1023608 :                         return sys_read8(port);
     425                 :            :                 }
     426                 :            :         }
     427                 :            :         return 0;
     428                 :            : }
     429                 :            : 
     430                 :            : #if (defined(CONFIG_UART_NS16550_INTEL_LPSS_DMA) & (defined(CONFIG_UART_ASYNC_API)))\
     431                 :            :         | UART_NS16550_PCP_ENABLED
     432                 :            : static void ns16550_outword(const struct uart_ns16550_device_config *cfg,
     433                 :            :                             uintptr_t port, uint32_t val)
     434                 :            : {
     435                 :            : #if UART_NS16550_IOPORT_ENABLED
     436                 :            :         if (cfg->io_map) {
     437                 :            :                 sys_out32(val, port);
     438                 :            :         } else {
     439                 :            : #else
     440                 :            :         {
     441                 :            : #endif
     442                 :            :                 /* MMIO mapped */
     443                 :            :                 sys_write32(val, port);
     444                 :            :         }
     445                 :            : }
     446                 :            : 
     447                 :            : static uint32_t ns16550_inword(const struct uart_ns16550_device_config *cfg,
     448                 :            :                               uintptr_t port)
     449                 :            : {
     450                 :            : #if UART_NS16550_IOPORT_ENABLED
     451                 :            :         if (cfg->io_map) {
     452                 :            :                 return sys_in32(port);
     453                 :            :         }
     454                 :            : #endif
     455                 :            :         /* MMIO mapped */
     456                 :            :         return sys_read32(port);
     457                 :            : }
     458                 :            : #endif
     459                 :            : 
     460                 :    1114620 : static inline uint8_t reg_interval(const struct device *dev)
     461                 :            : {
     462                 :    1114620 :         const struct uart_ns16550_device_config *config = dev->config;
     463                 :            : 
     464                 :    1114620 :         return config->reg_interval;
     465                 :            : }
     466                 :            : 
     467                 :    1114620 : static inline uintptr_t get_port(const struct device *dev)
     468                 :            : {
     469                 :            :         uintptr_t port;
     470                 :            : #if UART_NS16550_IOPORT_ENABLED
     471                 :            :         const struct uart_ns16550_device_config *config = dev->config;
     472                 :            : 
     473                 :            :         if (config->io_map) {
     474                 :            :                 port = config->port;
     475                 :            :         } else {
     476                 :            : #else
     477                 :            :         {
     478                 :            : #endif
     479                 :    1114620 :                 port = DEVICE_MMIO_GET(dev);
     480                 :            :         }
     481                 :            : 
     482                 :    1114620 :         return port;
     483                 :            : }
     484                 :            : 
     485                 :          4 : static uint32_t get_uart_burdrate_divisor(const struct device *dev,
     486                 :            :                                           uint32_t baud_rate,
     487                 :            :                                           uint32_t pclk)
     488                 :            : {
     489                 :            :         ARG_UNUSED(dev);
     490                 :            :         /*
     491                 :            :          * calculate baud rate divisor. a variant of
     492                 :            :          * (uint32_t)(pclk / (16.0 * baud_rate) + 0.5)
     493                 :            :          */
     494                 :          4 :         return ((pclk + (baud_rate << 3)) / baud_rate) >> 4;
     495                 :            : }
     496                 :            : 
     497                 :            : #ifdef CONFIG_UART_NS16550_ITE_HIGH_SPEED_BUADRATE
     498                 :            : static uint32_t get_ite_uart_burdrate_divisor(const struct device *dev,
     499                 :            :                                               uint32_t baud_rate,
     500                 :            :                                               uint32_t pclk)
     501                 :            : {
     502                 :            :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
     503                 :            :         uint32_t divisor = 0;
     504                 :            : 
     505                 :            :         if (baud_rate > UART_BAUDRATE_115200) {
     506                 :            :                 /* Baud rate divisor for high speed */
     507                 :            :                 if (baud_rate == UART_BAUDRATE_230400) {
     508                 :            :                         divisor = IT8XXX2_230400_DIVISOR;
     509                 :            :                 } else if (baud_rate == UART_BAUDRATE_460800) {
     510                 :            :                         divisor = IT8XXX2_460800_DIVISOR;
     511                 :            :                 }
     512                 :            :                 /*
     513                 :            :                  * This bit indicates that the supported baud rate of
     514                 :            :                  * UART1/UART2 can be up to 230.4k and 460.8k.
     515                 :            :                  * Other bits are reserved and have no setting, so we
     516                 :            :                  * directly write the ECSPMR register.
     517                 :            :                  */
     518                 :            :                 ns16550_outbyte(dev_cfg, ECSPMR(dev), ECSPMR_ECHS);
     519                 :            :         } else {
     520                 :            :                 divisor = get_uart_burdrate_divisor(dev, baud_rate, pclk);
     521                 :            :                 /* Set ECSPMR register as default */
     522                 :            :                 ns16550_outbyte(dev_cfg, ECSPMR(dev), 0);
     523                 :            :         }
     524                 :            : 
     525                 :            :         return divisor;
     526                 :            : }
     527                 :            : #endif
     528                 :            : 
     529                 :          4 : static void set_baud_rate(const struct device *dev, uint32_t baud_rate, uint32_t pclk)
     530                 :            : {
     531                 :          4 :         struct uart_ns16550_dev_data * const dev_data = dev->data;
     532                 :          4 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
     533                 :            :         uint32_t divisor; /* baud rate divisor */
     534                 :            :         uint8_t lcr_cache;
     535                 :            : 
     536   [ +  -  +  - ]:          4 :         if ((baud_rate != 0U) && (pclk != 0U)) {
     537                 :            : #ifdef CONFIG_UART_NS16550_ITE_HIGH_SPEED_BUADRATE
     538                 :            :                 divisor = get_ite_uart_burdrate_divisor(dev, baud_rate, pclk);
     539                 :            : #else
     540                 :          4 :                 divisor = get_uart_burdrate_divisor(dev, baud_rate, pclk);
     541                 :            : #endif
     542                 :            :                 /* set the DLAB to access the baud rate divisor registers */
     543                 :          4 :                 lcr_cache = ns16550_inbyte(dev_cfg, LCR(dev));
     544                 :          4 :                 ns16550_outbyte(dev_cfg, LCR(dev), LCR_DLAB | lcr_cache);
     545                 :          4 :                 ns16550_outbyte(dev_cfg, BRDL(dev), (unsigned char)(divisor & 0xff));
     546                 :          4 :                 ns16550_outbyte(dev_cfg, BRDH(dev), (unsigned char)((divisor >> 8) & 0xff));
     547                 :            : 
     548                 :            :                 /* restore the DLAB to access the baud rate divisor registers */
     549                 :          4 :                 ns16550_outbyte(dev_cfg, LCR(dev), lcr_cache);
     550                 :            : 
     551                 :          4 :                 dev_data->uart_config.baudrate = baud_rate;
     552                 :            :         }
     553                 :          4 : }
     554                 :            : 
     555                 :          4 : static int uart_ns16550_configure(const struct device *dev,
     556                 :            :                                   const struct uart_config *cfg)
     557                 :            : {
     558                 :          4 :         struct uart_ns16550_dev_data * const dev_data = dev->data;
     559                 :          4 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
     560                 :          4 :         uint8_t mdc = 0U;
     561                 :          4 :         uint32_t pclk = 0U;
     562                 :            : 
     563                 :            :         /* temp for return value if error occurs in this locked region */
     564                 :          4 :         int ret = 0;
     565                 :            : 
     566                 :          4 :         k_spinlock_key_t key = k_spin_lock(&dev_data->lock);
     567                 :            : 
     568                 :            : #if defined(CONFIG_PINCTRL)
     569                 :            :         if (dev_cfg->pincfg != NULL) {
     570                 :            :                 pinctrl_apply_state(dev_cfg->pincfg, PINCTRL_STATE_DEFAULT);
     571                 :            :         }
     572                 :            : #endif
     573                 :            : 
     574                 :            : #ifdef CONFIG_UART_INTERRUPT_DRIVEN
     575                 :          3 :         dev_data->iir_cache = 0U;
     576                 :            : #endif
     577                 :            : 
     578                 :            : #if UART_NS16550_DLF_ENABLED
     579                 :            :         ns16550_outbyte(dev_cfg, DLF(dev), dev_data->dlf);
     580                 :            : #endif
     581                 :            : 
     582                 :            : #if UART_NS16550_PCP_ENABLED
     583                 :            :         uint32_t pcp = dev_cfg->pcp;
     584                 :            : 
     585                 :            :         if (pcp) {
     586                 :            :                 pcp |= PCP_EN;
     587                 :            :                 ns16550_outbyte(dev_cfg, PCP(dev), pcp & ~PCP_UPDATE);
     588                 :            :                 ns16550_outbyte(dev_cfg, PCP(dev), pcp | PCP_UPDATE);
     589                 :            :         }
     590                 :            : #endif
     591                 :            : 
     592                 :            : #ifdef CONFIG_UART_NS16550_TI_K3
     593                 :            :         uint32_t mdr = ns16550_inbyte(dev_cfg, MDR1(dev));
     594                 :            : 
     595                 :            :         mdr = ((mdr & ~MDR1_MODE_SELECT_FIELD_MASK) | ((((MDR1_STD_MODE) <<
     596                 :            :                 MDR1_MODE_SELECT_FIELD_SHIFT)) & MDR1_MODE_SELECT_FIELD_MASK));
     597                 :            :         ns16550_outbyte(dev_cfg, MDR1(dev), mdr);
     598                 :            : #endif
     599                 :            :         /*
     600                 :            :          * set clock frequency from clock_frequency property if valid,
     601                 :            :          * otherwise, get clock frequency from clock manager
     602                 :            :          */
     603         [ +  - ]:          4 :         if (dev_cfg->sys_clk_freq != 0U) {
     604                 :          4 :                 pclk = dev_cfg->sys_clk_freq;
     605                 :            :         } else {
     606         [ #  # ]:          0 :                 if (!device_is_ready(dev_cfg->clock_dev)) {
     607                 :          0 :                         ret = -EINVAL;
     608                 :          0 :                         goto out;
     609                 :            :                 }
     610                 :            : 
     611         [ #  # ]:          0 :                 if (clock_control_get_rate(dev_cfg->clock_dev,
     612                 :          0 :                                            dev_cfg->clock_subsys,
     613                 :            :                                            &pclk) != 0) {
     614                 :          0 :                         ret = -EINVAL;
     615                 :          0 :                         goto out;
     616                 :            :                 }
     617                 :            :         }
     618                 :            : 
     619                 :          4 :         set_baud_rate(dev, cfg->baudrate, pclk);
     620                 :            : 
     621                 :            :         /* Local structure to hold temporary values to pass to ns16550_outbyte() */
     622                 :            :         struct uart_config uart_cfg;
     623                 :            : 
     624   [ -  -  -  +  :          4 :         switch (cfg->data_bits) {
                      - ]
     625                 :          0 :         case UART_CFG_DATA_BITS_5:
     626                 :          0 :                 uart_cfg.data_bits = LCR_CS5;
     627                 :          0 :                 break;
     628                 :          0 :         case UART_CFG_DATA_BITS_6:
     629                 :          0 :                 uart_cfg.data_bits = LCR_CS6;
     630                 :          0 :                 break;
     631                 :          0 :         case UART_CFG_DATA_BITS_7:
     632                 :          0 :                 uart_cfg.data_bits = LCR_CS7;
     633                 :          0 :                 break;
     634                 :          4 :         case UART_CFG_DATA_BITS_8:
     635                 :          4 :                 uart_cfg.data_bits = LCR_CS8;
     636                 :          4 :                 break;
     637                 :          0 :         default:
     638                 :          0 :                 ret = -ENOTSUP;
     639                 :          0 :                 goto out;
     640                 :            :         }
     641                 :            : 
     642      [ +  -  - ]:          4 :         switch (cfg->stop_bits) {
     643                 :          4 :         case UART_CFG_STOP_BITS_1:
     644                 :          4 :                 uart_cfg.stop_bits = LCR_1_STB;
     645                 :          4 :                 break;
     646                 :          0 :         case UART_CFG_STOP_BITS_2:
     647                 :          0 :                 uart_cfg.stop_bits = LCR_2_STB;
     648                 :          0 :                 break;
     649                 :          0 :         default:
     650                 :          0 :                 ret = -ENOTSUP;
     651                 :          0 :                 goto out;
     652                 :            :         }
     653                 :            : 
     654      [ +  -  - ]:          4 :         switch (cfg->parity) {
     655                 :          4 :         case UART_CFG_PARITY_NONE:
     656                 :          4 :                 uart_cfg.parity = LCR_PDIS;
     657                 :          4 :                 break;
     658                 :          0 :         case UART_CFG_PARITY_EVEN:
     659                 :          0 :                 uart_cfg.parity = LCR_EPS;
     660                 :          0 :                 break;
     661                 :          0 :         default:
     662                 :          0 :                 ret = -ENOTSUP;
     663                 :          0 :                 goto out;
     664                 :            :         }
     665                 :            : 
     666                 :          4 :         dev_data->uart_config = *cfg;
     667                 :            : 
     668                 :            :         /* data bits, stop bits, parity, clear DLAB */
     669                 :          4 :         ns16550_outbyte(dev_cfg, LCR(dev),
     670                 :          4 :                         uart_cfg.data_bits | uart_cfg.stop_bits | uart_cfg.parity);
     671                 :            : 
     672                 :          4 :         mdc = MCR_OUT2 | MCR_RTS | MCR_DTR;
     673                 :            : #if defined(CONFIG_UART_NS16550_VARIANT_NS16750) || \
     674                 :            :         defined(CONFIG_UART_NS16550_VARIANT_NS16950)
     675                 :            :         if (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS) {
     676                 :            :                 mdc |= MCR_AFCE;
     677                 :            :         }
     678                 :            : #endif
     679                 :            : 
     680                 :          4 :         ns16550_outbyte(dev_cfg, MDC(dev), mdc);
     681                 :            : 
     682                 :            :         /*
     683                 :            :          * Program FIFO: enabled, mode 0 (set for compatibility with quark),
     684                 :            :          * generate the interrupt at 8th byte
     685                 :            :          * Clear TX and RX FIFO
     686                 :            :          */
     687                 :          4 :         ns16550_outbyte(dev_cfg, FCR(dev),
     688                 :            :                         FCR_FIFO | FCR_MODE0 | FCR_FIFO_8 | FCR_RCVRCLR | FCR_XMITCLR
     689                 :            : #ifdef CONFIG_UART_NS16550_VARIANT_NS16750
     690                 :            :                         | FCR_FIFO_64
     691                 :            : #endif
     692                 :            :                         );
     693                 :            : 
     694         [ +  - ]:          4 :         if ((ns16550_inbyte(dev_cfg, IIR(dev)) & IIR_FE) == IIR_FE) {
     695                 :            : #ifdef CONFIG_UART_NS16550_VARIANT_NS16750
     696                 :            :                 dev_data->fifo_size = 64;
     697                 :            : #elif defined(CONFIG_UART_NS16550_VARIANT_NS16950)
     698                 :            :                 dev_data->fifo_size = 128;
     699                 :            : #else
     700                 :          4 :                 dev_data->fifo_size = 16;
     701                 :            : #endif
     702                 :            :         } else {
     703                 :          0 :                 dev_data->fifo_size = 1;
     704                 :            :         }
     705                 :            : 
     706                 :            :         /* clear the port */
     707                 :          4 :         ns16550_inbyte(dev_cfg, RDR(dev));
     708                 :            : 
     709                 :            :         /* disable interrupts  */
     710                 :          4 :         ns16550_outbyte(dev_cfg, IER(dev), 0x00);
     711                 :            : 
     712                 :          4 : out:
     713                 :          4 :         k_spin_unlock(&dev_data->lock, key);
     714                 :          4 :         return ret;
     715                 :            : };
     716                 :            : 
     717                 :            : #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
     718                 :          1 : static int uart_ns16550_config_get(const struct device *dev,
     719                 :            :                                    struct uart_config *cfg)
     720                 :            : {
     721                 :          1 :         struct uart_ns16550_dev_data *data = dev->data;
     722                 :            : 
     723                 :          1 :         cfg->baudrate = data->uart_config.baudrate;
     724                 :          1 :         cfg->parity = data->uart_config.parity;
     725                 :          1 :         cfg->stop_bits = data->uart_config.stop_bits;
     726                 :          1 :         cfg->data_bits = data->uart_config.data_bits;
     727                 :          1 :         cfg->flow_ctrl = data->uart_config.flow_ctrl;
     728                 :            : 
     729                 :          1 :         return 0;
     730                 :            : }
     731                 :            : #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
     732                 :            : 
     733                 :            : #if UART_NS16550_RESET_ENABLED
     734                 :            : /**
     735                 :            :  * @brief Toggle the reset UART line
     736                 :            :  *
     737                 :            :  * This routine is called to bring UART IP out of reset state.
     738                 :            :  *
     739                 :            :  * @param reset_spec Reset controller device configuration struct
     740                 :            :  *
     741                 :            :  * @return 0 if successful, failed otherwise
     742                 :            :  */
     743                 :            : static int uart_reset_config(const struct reset_dt_spec *reset_spec)
     744                 :            : {
     745                 :            :         int ret;
     746                 :            : 
     747                 :            :         if (!device_is_ready(reset_spec->dev)) {
     748                 :            :                 LOG_ERR("Reset controller device is not ready");
     749                 :            :                 return -ENODEV;
     750                 :            :         }
     751                 :            : 
     752                 :            :         ret = reset_line_toggle(reset_spec->dev, reset_spec->id);
     753                 :            :         if (ret != 0) {
     754                 :            :                 LOG_ERR("UART toggle reset line failed");
     755                 :            :                 return ret;
     756                 :            :         }
     757                 :            : 
     758                 :            :         return 0;
     759                 :            : }
     760                 :            : #endif /* UART_NS16550_RESET_ENABLED */
     761                 :            : 
     762                 :            : #if (IS_ENABLED(CONFIG_UART_ASYNC_API))
     763                 :            : static inline void async_timer_start(struct k_work_delayable *work, size_t timeout_us)
     764                 :            : {
     765                 :            :         if ((timeout_us != SYS_FOREVER_US) && (timeout_us != 0)) {
     766                 :            :                 k_work_reschedule(work, K_USEC(timeout_us));
     767                 :            :         }
     768                 :            : }
     769                 :            : 
     770                 :            : #endif
     771                 :            : 
     772                 :            : /**
     773                 :            :  * @brief Initialize individual UART port
     774                 :            :  *
     775                 :            :  * This routine is called to reset the chip in a quiescent state.
     776                 :            :  *
     777                 :            :  * @param dev UART device struct
     778                 :            :  *
     779                 :            :  * @return 0 if successful, failed otherwise
     780                 :            :  */
     781                 :          2 : static int uart_ns16550_init(const struct device *dev)
     782                 :            : {
     783                 :          2 :         struct uart_ns16550_dev_data *data = dev->data;
     784                 :          2 :         const struct uart_ns16550_device_config *dev_cfg = dev->config;
     785                 :            :         int ret;
     786                 :            : 
     787                 :            :         ARG_UNUSED(dev_cfg);
     788                 :            : 
     789                 :            : #if UART_NS16550_RESET_ENABLED
     790                 :            :         /* Assert the UART reset line if it is defined. */
     791                 :            :         if (dev_cfg->reset_spec.dev != NULL) {
     792                 :            :                 ret = uart_reset_config(&(dev_cfg->reset_spec));
     793                 :            :                 if (ret != 0) {
     794                 :            :                         return ret;
     795                 :            :                 }
     796                 :            :         }
     797                 :            : #endif
     798                 :            : 
     799                 :            : #if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie)
     800                 :            :         if (dev_cfg->pcie) {
     801                 :            :                 struct pcie_bar mbar;
     802                 :            : 
     803                 :            :                 if (dev_cfg->pcie->bdf == PCIE_BDF_NONE) {
     804                 :            :                         return -EINVAL;
     805                 :            :                 }
     806                 :            : 
     807                 :            :                 pcie_probe_mbar(dev_cfg->pcie->bdf, 0, &mbar);
     808                 :            :                 pcie_set_cmd(dev_cfg->pcie->bdf, PCIE_CONF_CMDSTAT_MEM, true);
     809                 :            : 
     810                 :            :                 device_map(DEVICE_MMIO_RAM_PTR(dev), mbar.phys_addr, mbar.size,
     811                 :            :                            K_MEM_CACHE_NONE);
     812                 :            : #if defined(CONFIG_UART_ASYNC_API)
     813                 :            :                 if (data->async.tx_dma_params.dma_dev != NULL) {
     814                 :            :                         pcie_set_cmd(dev_cfg->pcie->bdf, PCIE_CONF_CMDSTAT_MASTER, true);
     815                 :            :                         data->phys_addr = mbar.phys_addr;
     816                 :            :                 }
     817                 :            : #endif
     818                 :            :         } else
     819                 :            : #endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) */
     820                 :            :         {
     821                 :            : #if UART_NS16550_IOPORT_ENABLED
     822                 :            :                 /* Map directly from DTS */
     823                 :            :                 if (!dev_cfg->io_map) {
     824                 :            : #else
     825                 :            :                 {
     826                 :            : #endif
     827                 :            :                         DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
     828                 :            :                 }
     829                 :            :         }
     830                 :            : #if defined(CONFIG_UART_ASYNC_API)
     831                 :            :         if (data->async.tx_dma_params.dma_dev != NULL) {
     832                 :            :                 data->async.next_rx_buffer = NULL;
     833                 :            :                 data->async.next_rx_buffer_len = 0;
     834                 :            :                 data->async.uart_dev = dev;
     835                 :            :                 k_work_init_delayable(&data->async.rx_dma_params.timeout_work,
     836                 :            :                                       uart_ns16550_async_rx_timeout);
     837                 :            :                 k_work_init_delayable(&data->async.tx_dma_params.timeout_work,
     838                 :            :                                       uart_ns16550_async_tx_timeout);
     839                 :            :                 data->async.rx_dma_params.dma_cfg.head_block =
     840                 :            :                         &data->async.rx_dma_params.active_dma_block;
     841                 :            :                 data->async.tx_dma_params.dma_cfg.head_block =
     842                 :            :                         &data->async.tx_dma_params.active_dma_block;
     843                 :            : #if defined(CONFIG_UART_NS16550_INTEL_LPSS_DMA)
     844                 :            : #if UART_NS16550_IOPORT_ENABLED
     845                 :            :                 if (!dev_cfg->io_map)
     846                 :            : #endif
     847                 :            :                 {
     848                 :            :                         uintptr_t base;
     849                 :            : 
     850                 :            :                         base = DEVICE_MMIO_GET(dev) + DMA_INTEL_LPSS_OFFSET;
     851                 :            :                         dma_intel_lpss_set_base(data->async.tx_dma_params.dma_dev, base);
     852                 :            :                         dma_intel_lpss_setup(data->async.tx_dma_params.dma_dev);
     853                 :            :                         sys_write32((uint32_t)data->phys_addr,
     854                 :            :                                     DEVICE_MMIO_GET(dev) + DMA_INTEL_LPSS_REMAP_LOW);
     855                 :            :                         sys_write32((uint32_t)(data->phys_addr >> DMA_INTEL_LPSS_ADDR_RIGHT_SHIFT),
     856                 :            :                                     DEVICE_MMIO_GET(dev) + DMA_INTEL_LPSS_REMAP_HI);
     857                 :            :                 }
     858                 :            : #endif
     859                 :            :         }
     860                 :            : #endif
     861                 :          2 :         ret = uart_ns16550_configure(dev, &data->uart_config);
     862         [ -  + ]:          2 :         if (ret != 0) {
     863                 :          0 :                 return ret;
     864                 :            :         }
     865                 :            : 
     866                 :            : #ifdef CONFIG_UART_INTERRUPT_DRIVEN
     867                 :          1 :         dev_cfg->irq_config_func(dev);
     868                 :            : #endif
     869                 :            : 
     870                 :          2 :         return 0;
     871                 :            : }
     872                 :            : 
     873                 :            : /**
     874                 :            :  * @brief Poll the device for input.
     875                 :            :  *
     876                 :            :  * @param dev UART device struct
     877                 :            :  * @param c Pointer to character
     878                 :            :  *
     879                 :            :  * @return 0 if a character arrived, -1 if the input buffer if empty.
     880                 :            :  */
     881                 :      44147 : static int uart_ns16550_poll_in(const struct device *dev, unsigned char *c)
     882                 :            : {
     883                 :      44147 :         struct uart_ns16550_dev_data *data = dev->data;
     884                 :      44147 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
     885                 :      44147 :         int ret = -1;
     886                 :      44147 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
     887                 :            : 
     888         [ +  + ]:      44147 :         if ((ns16550_inbyte(dev_cfg, LSR(dev)) & LSR_RXRDY) != 0) {
     889                 :            :                 /* got a character */
     890                 :         10 :                 *c = ns16550_inbyte(dev_cfg, RDR(dev));
     891                 :         10 :                 ret = 0;
     892                 :            :         }
     893                 :            : 
     894                 :      44147 :         k_spin_unlock(&data->lock, key);
     895                 :            : 
     896                 :      44147 :         return ret;
     897                 :            : }
     898                 :            : 
     899                 :            : /**
     900                 :            :  * @brief Output a character in polled mode.
     901                 :            :  *
     902                 :            :  * Checks if the transmitter is empty. If empty, a character is written to
     903                 :            :  * the data register.
     904                 :            :  *
     905                 :            :  * If the hardware flow control is enabled then the handshake signal CTS has to
     906                 :            :  * be asserted in order to send a character.
     907                 :            :  *
     908                 :            :  * @param dev UART device struct
     909                 :            :  * @param c Character to send
     910                 :            :  */
     911                 :      90951 : static void uart_ns16550_poll_out(const struct device *dev,
     912                 :            :                                            unsigned char c)
     913                 :            : {
     914                 :      90951 :         struct uart_ns16550_dev_data *data = dev->data;
     915                 :      90951 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
     916                 :      90951 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
     917                 :            : 
     918         [ +  + ]:     979356 :         while ((ns16550_inbyte(dev_cfg, LSR(dev)) & LSR_THRE) == 0) {
     919                 :            :         }
     920                 :            : 
     921                 :      90951 :         ns16550_outbyte(dev_cfg, THR(dev), c);
     922                 :            : 
     923                 :      90951 :         k_spin_unlock(&data->lock, key);
     924                 :      90951 : }
     925                 :            : 
     926                 :            : /**
     927                 :            :  * @brief Check if an error was received
     928                 :            :  *
     929                 :            :  * @param dev UART device struct
     930                 :            :  *
     931                 :            :  * @return one of UART_ERROR_OVERRUN, UART_ERROR_PARITY, UART_ERROR_FRAMING,
     932                 :            :  * UART_BREAK if an error was detected, 0 otherwise.
     933                 :            :  */
     934                 :          0 : static int uart_ns16550_err_check(const struct device *dev)
     935                 :            : {
     936                 :          0 :         struct uart_ns16550_dev_data *data = dev->data;
     937                 :          0 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
     938                 :          0 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
     939                 :          0 :         int check = (ns16550_inbyte(dev_cfg, LSR(dev)) & LSR_EOB_MASK);
     940                 :            : 
     941                 :          0 :         k_spin_unlock(&data->lock, key);
     942                 :            : 
     943                 :          0 :         return check >> 1;
     944                 :            : }
     945                 :            : 
     946                 :            : #if CONFIG_UART_INTERRUPT_DRIVEN
     947                 :            : 
     948                 :            : /**
     949                 :            :  * @brief Fill FIFO with data
     950                 :            :  *
     951                 :            :  * @param dev UART device struct
     952                 :            :  * @param tx_data Data to transmit
     953                 :            :  * @param size Number of bytes to send
     954                 :            :  *
     955                 :            :  * @return Number of bytes sent
     956                 :            :  */
     957                 :          2 : static int uart_ns16550_fifo_fill(const struct device *dev,
     958                 :            :                                   const uint8_t *tx_data,
     959                 :            :                                   int size)
     960                 :            : {
     961                 :          2 :         struct uart_ns16550_dev_data *data = dev->data;
     962                 :          2 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
     963                 :            :         int i;
     964                 :          2 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
     965                 :            : 
     966   [ +  +  +  + ]:         24 :         for (i = 0; (i < size) && (i < data->fifo_size); i++) {
     967                 :         22 :                 ns16550_outbyte(dev_cfg, THR(dev), tx_data[i]);
     968                 :            :         }
     969                 :            : 
     970                 :          2 :         k_spin_unlock(&data->lock, key);
     971                 :            : 
     972                 :          2 :         return i;
     973                 :            : }
     974                 :            : 
     975                 :            : /**
     976                 :            :  * @brief Read data from FIFO
     977                 :            :  *
     978                 :            :  * @param dev UART device struct
     979                 :            :  * @param rxData Data container
     980                 :            :  * @param size Container size
     981                 :            :  *
     982                 :            :  * @return Number of bytes read
     983                 :            :  */
     984                 :         25 : static int uart_ns16550_fifo_read(const struct device *dev, uint8_t *rx_data,
     985                 :            :                                   const int size)
     986                 :            : {
     987                 :         25 :         struct uart_ns16550_dev_data *data = dev->data;
     988                 :         25 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
     989                 :            :         int i;
     990                 :         25 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
     991                 :            : 
     992   [ +  +  +  + ]:         49 :         for (i = 0; (i < size) && (ns16550_inbyte(dev_cfg, LSR(dev)) & LSR_RXRDY) != 0; i++) {
     993                 :         24 :                 rx_data[i] = ns16550_inbyte(dev_cfg, RDR(dev));
     994                 :            :         }
     995                 :            : 
     996                 :         25 :         k_spin_unlock(&data->lock, key);
     997                 :            : 
     998                 :         25 :         return i;
     999                 :            : }
    1000                 :            : 
    1001                 :            : /**
    1002                 :            :  * @brief Enable TX interrupt in IER
    1003                 :            :  *
    1004                 :            :  * @param dev UART device struct
    1005                 :            :  */
    1006                 :          1 : static void uart_ns16550_irq_tx_enable(const struct device *dev)
    1007                 :            : {
    1008                 :          1 :         struct uart_ns16550_dev_data *data = dev->data;
    1009                 :          1 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
    1010                 :          1 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1011                 :            : 
    1012                 :            : #if defined(CONFIG_UART_INTERRUPT_DRIVEN) && defined(CONFIG_PM)
    1013                 :            :         struct uart_ns16550_dev_data *const dev_data = dev->data;
    1014                 :            : 
    1015                 :            :         if (!dev_data->tx_stream_on) {
    1016                 :            :                 dev_data->tx_stream_on = true;
    1017                 :            :                 uint8_t num_cpu_states;
    1018                 :            :                 const struct pm_state_info *cpu_states;
    1019                 :            : 
    1020                 :            :                 num_cpu_states = pm_state_cpu_get_all(0U, &cpu_states);
    1021                 :            : 
    1022                 :            :                 /*
    1023                 :            :                  * Power state to be disabled. Some platforms have multiple
    1024                 :            :                  * states and need to be given a constraint set according to
    1025                 :            :                  * different states.
    1026                 :            :                  */
    1027                 :            :                 for (uint8_t i = 0U; i < num_cpu_states; i++) {
    1028                 :            :                         pm_policy_state_lock_get(cpu_states[i].state, PM_ALL_SUBSTATES);
    1029                 :            :                 }
    1030                 :            :         }
    1031                 :            : #endif
    1032                 :          1 :         ns16550_outbyte(dev_cfg, IER(dev), ns16550_inbyte(dev_cfg, IER(dev)) | IER_TBE);
    1033                 :            : 
    1034                 :          1 :         k_spin_unlock(&data->lock, key);
    1035                 :          1 : }
    1036                 :            : 
    1037                 :            : /**
    1038                 :            :  * @brief Disable TX interrupt in IER
    1039                 :            :  *
    1040                 :            :  * @param dev UART device struct
    1041                 :            :  */
    1042                 :          3 : static void uart_ns16550_irq_tx_disable(const struct device *dev)
    1043                 :            : {
    1044                 :          3 :         struct uart_ns16550_dev_data *data = dev->data;
    1045                 :          3 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
    1046                 :          3 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1047                 :            : 
    1048                 :          6 :         ns16550_outbyte(dev_cfg, IER(dev),
    1049                 :          3 :                         ns16550_inbyte(dev_cfg, IER(dev)) & (~IER_TBE));
    1050                 :            : 
    1051                 :            : #if defined(CONFIG_UART_INTERRUPT_DRIVEN) && defined(CONFIG_PM)
    1052                 :            :         struct uart_ns16550_dev_data *const dev_data = dev->data;
    1053                 :            : 
    1054                 :            :         if (dev_data->tx_stream_on) {
    1055                 :            :                 dev_data->tx_stream_on = false;
    1056                 :            :                 uint8_t num_cpu_states;
    1057                 :            :                 const struct pm_state_info *cpu_states;
    1058                 :            : 
    1059                 :            :                 num_cpu_states = pm_state_cpu_get_all(0U, &cpu_states);
    1060                 :            : 
    1061                 :            :                 /*
    1062                 :            :                  * Power state to be enabled. Some platforms have multiple
    1063                 :            :                  * states and need to be given a constraint release according
    1064                 :            :                  * to different states.
    1065                 :            :                  */
    1066                 :            :                 for (uint8_t i = 0U; i < num_cpu_states; i++) {
    1067                 :            :                         pm_policy_state_lock_put(cpu_states[i].state, PM_ALL_SUBSTATES);
    1068                 :            :                 }
    1069                 :            :         }
    1070                 :            : #endif
    1071                 :          3 :         k_spin_unlock(&data->lock, key);
    1072                 :          3 : }
    1073                 :            : 
    1074                 :            : /**
    1075                 :            :  * @brief Check if Tx IRQ has been raised
    1076                 :            :  *
    1077                 :            :  * @param dev UART device struct
    1078                 :            :  *
    1079                 :            :  * @return 1 if an IRQ is ready, 0 otherwise
    1080                 :            :  */
    1081                 :         25 : static int uart_ns16550_irq_tx_ready(const struct device *dev)
    1082                 :            : {
    1083                 :         25 :         struct uart_ns16550_dev_data *data = dev->data;
    1084                 :         25 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1085                 :            : 
    1086                 :         25 :         int ret = ((IIRC(dev) & IIR_ID) == IIR_THRE) ? 1 : 0;
    1087                 :            : 
    1088                 :         25 :         k_spin_unlock(&data->lock, key);
    1089                 :            : 
    1090                 :         25 :         return ret;
    1091                 :            : }
    1092                 :            : 
    1093                 :            : /**
    1094                 :            :  * @brief Check if nothing remains to be transmitted
    1095                 :            :  *
    1096                 :            :  * @param dev UART device struct
    1097                 :            :  *
    1098                 :            :  * @return 1 if nothing remains to be transmitted, 0 otherwise
    1099                 :            :  */
    1100                 :          0 : static int uart_ns16550_irq_tx_complete(const struct device *dev)
    1101                 :            : {
    1102                 :          0 :         struct uart_ns16550_dev_data *data = dev->data;
    1103                 :          0 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
    1104                 :          0 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1105                 :            : 
    1106                 :          0 :         int ret = ((ns16550_inbyte(dev_cfg, LSR(dev)) & (LSR_TEMT | LSR_THRE))
    1107                 :          0 :                                 == (LSR_TEMT | LSR_THRE)) ? 1 : 0;
    1108                 :            : 
    1109                 :          0 :         k_spin_unlock(&data->lock, key);
    1110                 :            : 
    1111                 :          0 :         return ret;
    1112                 :            : }
    1113                 :            : 
    1114                 :            : /**
    1115                 :            :  * @brief Enable RX interrupt in IER
    1116                 :            :  *
    1117                 :            :  * @param dev UART device struct
    1118                 :            :  */
    1119                 :          2 : static void uart_ns16550_irq_rx_enable(const struct device *dev)
    1120                 :            : {
    1121                 :          2 :         struct uart_ns16550_dev_data *data = dev->data;
    1122                 :          2 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
    1123                 :          2 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1124                 :            : 
    1125                 :          2 :         ns16550_outbyte(dev_cfg, IER(dev), ns16550_inbyte(dev_cfg, IER(dev)) | IER_RXRDY);
    1126                 :            : 
    1127                 :          2 :         k_spin_unlock(&data->lock, key);
    1128                 :          2 : }
    1129                 :            : 
    1130                 :            : /**
    1131                 :            :  * @brief Disable RX interrupt in IER
    1132                 :            :  *
    1133                 :            :  * @param dev UART device struct
    1134                 :            :  */
    1135                 :          1 : static void uart_ns16550_irq_rx_disable(const struct device *dev)
    1136                 :            : {
    1137                 :          1 :         struct uart_ns16550_dev_data *data = dev->data;
    1138                 :          1 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
    1139                 :          1 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1140                 :            : 
    1141                 :          2 :         ns16550_outbyte(dev_cfg, IER(dev),
    1142                 :          1 :                         ns16550_inbyte(dev_cfg, IER(dev)) & (~IER_RXRDY));
    1143                 :            : 
    1144                 :          1 :         k_spin_unlock(&data->lock, key);
    1145                 :          1 : }
    1146                 :            : 
    1147                 :            : /**
    1148                 :            :  * @brief Check if Rx IRQ has been raised
    1149                 :            :  *
    1150                 :            :  * @param dev UART device struct
    1151                 :            :  *
    1152                 :            :  * @return 1 if an IRQ is ready, 0 otherwise
    1153                 :            :  */
    1154                 :         26 : static int uart_ns16550_irq_rx_ready(const struct device *dev)
    1155                 :            : {
    1156                 :         26 :         struct uart_ns16550_dev_data *data = dev->data;
    1157                 :         26 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1158                 :            : 
    1159                 :         26 :         int ret = ((IIRC(dev) & IIR_ID) == IIR_RBRF) ? 1 : 0;
    1160                 :            : 
    1161                 :         26 :         k_spin_unlock(&data->lock, key);
    1162                 :            : 
    1163                 :         26 :         return ret;
    1164                 :            : }
    1165                 :            : 
    1166                 :            : /**
    1167                 :            :  * @brief Enable error interrupt in IER
    1168                 :            :  *
    1169                 :            :  * @param dev UART device struct
    1170                 :            :  */
    1171                 :          0 : static void uart_ns16550_irq_err_enable(const struct device *dev)
    1172                 :            : {
    1173                 :          0 :         struct uart_ns16550_dev_data *data = dev->data;
    1174                 :          0 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
    1175                 :          0 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1176                 :            : 
    1177                 :          0 :         ns16550_outbyte(dev_cfg, IER(dev),
    1178                 :          0 :                         ns16550_inbyte(dev_cfg, IER(dev)) | IER_LSR);
    1179                 :            : 
    1180                 :          0 :         k_spin_unlock(&data->lock, key);
    1181                 :          0 : }
    1182                 :            : 
    1183                 :            : /**
    1184                 :            :  * @brief Disable error interrupt in IER
    1185                 :            :  *
    1186                 :            :  * @param dev UART device struct
    1187                 :            :  *
    1188                 :            :  * @return 1 if an IRQ is ready, 0 otherwise
    1189                 :            :  */
    1190                 :          0 : static void uart_ns16550_irq_err_disable(const struct device *dev)
    1191                 :            : {
    1192                 :          0 :         struct uart_ns16550_dev_data *data = dev->data;
    1193                 :          0 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
    1194                 :          0 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1195                 :            : 
    1196                 :          0 :         ns16550_outbyte(dev_cfg, IER(dev),
    1197                 :          0 :                         ns16550_inbyte(dev_cfg, IER(dev)) & (~IER_LSR));
    1198                 :            : 
    1199                 :          0 :         k_spin_unlock(&data->lock, key);
    1200                 :          0 : }
    1201                 :            : 
    1202                 :            : /**
    1203                 :            :  * @brief Check if any IRQ is pending
    1204                 :            :  *
    1205                 :            :  * @param dev UART device struct
    1206                 :            :  *
    1207                 :            :  * @return 1 if an IRQ is pending, 0 otherwise
    1208                 :            :  */
    1209                 :          2 : static int uart_ns16550_irq_is_pending(const struct device *dev)
    1210                 :            : {
    1211                 :          2 :         struct uart_ns16550_dev_data *data = dev->data;
    1212                 :          2 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1213                 :            : 
    1214                 :          2 :         int ret = (!(IIRC(dev) & IIR_NIP)) ? 1 : 0;
    1215                 :            : 
    1216                 :          2 :         k_spin_unlock(&data->lock, key);
    1217                 :            : 
    1218                 :          2 :         return ret;
    1219                 :            : }
    1220                 :            : 
    1221                 :            : /**
    1222                 :            :  * @brief Update cached contents of IIR
    1223                 :            :  *
    1224                 :            :  * @param dev UART device struct
    1225                 :            :  *
    1226                 :            :  * @return Always 1
    1227                 :            :  */
    1228                 :         27 : static int uart_ns16550_irq_update(const struct device *dev)
    1229                 :            : {
    1230                 :         27 :         struct uart_ns16550_dev_data *data = dev->data;
    1231                 :         27 :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
    1232                 :         27 :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1233                 :            : 
    1234                 :         27 :         IIRC(dev) = ns16550_inbyte(dev_cfg, IIR(dev));
    1235                 :            : 
    1236                 :         27 :         k_spin_unlock(&data->lock, key);
    1237                 :            : 
    1238                 :         27 :         return 1;
    1239                 :            : }
    1240                 :            : 
    1241                 :            : /**
    1242                 :            :  * @brief Set the callback function pointer for IRQ.
    1243                 :            :  *
    1244                 :            :  * @param dev UART device struct
    1245                 :            :  * @param cb Callback function pointer.
    1246                 :            :  */
    1247                 :          3 : static void uart_ns16550_irq_callback_set(const struct device *dev,
    1248                 :            :                                           uart_irq_callback_user_data_t cb,
    1249                 :            :                                           void *cb_data)
    1250                 :            : {
    1251                 :          3 :         struct uart_ns16550_dev_data * const dev_data = dev->data;
    1252                 :          3 :         k_spinlock_key_t key = k_spin_lock(&dev_data->lock);
    1253                 :            : 
    1254                 :          3 :         dev_data->cb = cb;
    1255                 :          3 :         dev_data->cb_data = cb_data;
    1256                 :            : 
    1257                 :          3 :         k_spin_unlock(&dev_data->lock, key);
    1258                 :          3 : }
    1259                 :            : 
    1260                 :            : /**
    1261                 :            :  * @brief Interrupt service routine.
    1262                 :            :  *
    1263                 :            :  * This simply calls the callback function, if one exists.
    1264                 :            :  *
    1265                 :            :  * @param arg Argument to ISR.
    1266                 :            :  */
    1267                 :         26 : static void uart_ns16550_isr(const struct device *dev)
    1268                 :            : {
    1269                 :         26 :         struct uart_ns16550_dev_data * const dev_data = dev->data;
    1270                 :            : 
    1271         [ +  - ]:         26 :         if (dev_data->cb) {
    1272                 :         26 :                 dev_data->cb(dev, dev_data->cb_data);
    1273                 :            :         }
    1274                 :            : #if (IS_ENABLED(CONFIG_UART_ASYNC_API))
    1275                 :            :         if (dev_data->async.tx_dma_params.dma_dev != NULL) {
    1276                 :            :                 const struct uart_ns16550_device_config * const config = dev->config;
    1277                 :            :                 uint8_t IIR_status = ns16550_inbyte(config, IIR(dev));
    1278                 :            : #if (IS_ENABLED(CONFIG_UART_NS16550_INTEL_LPSS_DMA))
    1279                 :            :                 uint32_t dma_status = ns16550_inword(config, SRC_TRAN(dev));
    1280                 :            : 
    1281                 :            :                 if (dma_status & BIT(dev_data->async.rx_dma_params.dma_channel)) {
    1282                 :            :                         async_timer_start(&dev_data->async.rx_dma_params.timeout_work,
    1283                 :            :                                           dev_data->async.rx_dma_params.timeout_us);
    1284                 :            :                         ns16550_outword(config, CLR_SRC_TRAN(dev),
    1285                 :            :                                         BIT(dev_data->async.rx_dma_params.dma_channel));
    1286                 :            :                         return;
    1287                 :            :                 }
    1288                 :            :                 dma_intel_lpss_isr(dev_data->async.rx_dma_params.dma_dev);
    1289                 :            : #endif
    1290                 :            :                 if (IIR_status & IIR_RBRF) {
    1291                 :            :                         async_timer_start(&dev_data->async.rx_dma_params.timeout_work,
    1292                 :            :                                           dev_data->async.rx_dma_params.timeout_us);
    1293                 :            :                         return;
    1294                 :            :                 }
    1295                 :            :         }
    1296                 :            : #endif
    1297                 :            : 
    1298                 :            : #ifdef CONFIG_UART_NS16550_WA_ISR_REENABLE_INTERRUPT
    1299                 :            :         const struct uart_ns16550_device_config * const dev_cfg = dev->config;
    1300                 :            :         uint8_t cached_ier = ns16550_inbyte(dev_cfg, IER(dev));
    1301                 :            : 
    1302                 :            :         ns16550_outbyte(dev_cfg, IER(dev), 0U);
    1303                 :            :         ns16550_outbyte(dev_cfg, IER(dev), cached_ier);
    1304                 :            : #endif
    1305                 :         26 : }
    1306                 :            : 
    1307                 :            : #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
    1308                 :            : 
    1309                 :            : #ifdef CONFIG_UART_NS16550_LINE_CTRL
    1310                 :            : 
    1311                 :            : /**
    1312                 :            :  * @brief Manipulate line control for UART.
    1313                 :            :  *
    1314                 :            :  * @param dev UART device struct
    1315                 :            :  * @param ctrl The line control to be manipulated
    1316                 :            :  * @param val Value to set the line control
    1317                 :            :  *
    1318                 :            :  * @return 0 if successful, failed otherwise
    1319                 :            :  */
    1320                 :            : static int uart_ns16550_line_ctrl_set(const struct device *dev,
    1321                 :            :                                       uint32_t ctrl, uint32_t val)
    1322                 :            : {
    1323                 :            :         struct uart_ns16550_dev_data *data = dev->data;
    1324                 :            :         const struct uart_ns16550_device_config *const dev_cfg = dev->config;
    1325                 :            :         uint32_t mdc, chg, pclk = 0U;
    1326                 :            :         k_spinlock_key_t key;
    1327                 :            : 
    1328                 :            :         if (dev_cfg->sys_clk_freq != 0U) {
    1329                 :            :                 pclk = dev_cfg->sys_clk_freq;
    1330                 :            :         } else {
    1331                 :            :                 if (device_is_ready(dev_cfg->clock_dev)) {
    1332                 :            :                         clock_control_get_rate(dev_cfg->clock_dev, dev_cfg->clock_subsys, &pclk);
    1333                 :            :                 }
    1334                 :            :         }
    1335                 :            : 
    1336                 :            :         switch (ctrl) {
    1337                 :            :         case UART_LINE_CTRL_BAUD_RATE:
    1338                 :            :                 set_baud_rate(dev, val, pclk);
    1339                 :            :                 return 0;
    1340                 :            : 
    1341                 :            :         case UART_LINE_CTRL_RTS:
    1342                 :            :         case UART_LINE_CTRL_DTR:
    1343                 :            :                 key = k_spin_lock(&data->lock);
    1344                 :            :                 mdc = ns16550_inbyte(dev_cfg, MDC(dev));
    1345                 :            : 
    1346                 :            :                 if (ctrl == UART_LINE_CTRL_RTS) {
    1347                 :            :                         chg = MCR_RTS;
    1348                 :            :                 } else {
    1349                 :            :                         chg = MCR_DTR;
    1350                 :            :                 }
    1351                 :            : 
    1352                 :            :                 if (val) {
    1353                 :            :                         mdc |= chg;
    1354                 :            :                 } else {
    1355                 :            :                         mdc &= ~(chg);
    1356                 :            :                 }
    1357                 :            :                 ns16550_outbyte(dev_cfg, MDC(dev), mdc);
    1358                 :            :                 k_spin_unlock(&data->lock, key);
    1359                 :            :                 return 0;
    1360                 :            :         }
    1361                 :            : 
    1362                 :            :         return -ENOTSUP;
    1363                 :            : }
    1364                 :            : 
    1365                 :            : #endif /* CONFIG_UART_NS16550_LINE_CTRL */
    1366                 :            : 
    1367                 :            : #ifdef CONFIG_UART_NS16550_DRV_CMD
    1368                 :            : 
    1369                 :            : /**
    1370                 :            :  * @brief Send extra command to driver
    1371                 :            :  *
    1372                 :            :  * @param dev UART device struct
    1373                 :            :  * @param cmd Command to driver
    1374                 :            :  * @param p Parameter to the command
    1375                 :            :  *
    1376                 :            :  * @return 0 if successful, failed otherwise
    1377                 :            :  */
    1378                 :            : static int uart_ns16550_drv_cmd(const struct device *dev, uint32_t cmd,
    1379                 :            :                                 uint32_t p)
    1380                 :            : {
    1381                 :            : #if UART_NS16550_DLF_ENABLED
    1382                 :            :         if (cmd == CMD_SET_DLF) {
    1383                 :            :                 struct uart_ns16550_dev_data * const dev_data = dev->data;
    1384                 :            :                 const struct uart_ns16550_device_config * const dev_cfg = dev->config;
    1385                 :            :                 k_spinlock_key_t key = k_spin_lock(&dev_data->lock);
    1386                 :            : 
    1387                 :            :                 dev_data->dlf = p;
    1388                 :            :                 ns16550_outbyte(dev_cfg, DLF(dev), dev_data->dlf);
    1389                 :            :                 k_spin_unlock(&dev_data->lock, key);
    1390                 :            :                 return 0;
    1391                 :            :         }
    1392                 :            : #endif
    1393                 :            : 
    1394                 :            :         return -ENOTSUP;
    1395                 :            : }
    1396                 :            : 
    1397                 :            : #endif /* CONFIG_UART_NS16550_DRV_CMD */
    1398                 :            : 
    1399                 :            : #if (IS_ENABLED(CONFIG_UART_ASYNC_API))
    1400                 :            : static void async_user_callback(const struct device *dev, struct uart_event *evt)
    1401                 :            : {
    1402                 :            :         const struct uart_ns16550_dev_data *data = dev->data;
    1403                 :            : 
    1404                 :            :         if (data->async.user_callback) {
    1405                 :            :                 data->async.user_callback(dev, evt, data->async.user_data);
    1406                 :            :         }
    1407                 :            : }
    1408                 :            : 
    1409                 :            : #if UART_NS16550_DMAS_ENABLED
    1410                 :            : static void async_evt_tx_done(struct device *dev)
    1411                 :            : {
    1412                 :            :         struct uart_ns16550_dev_data *data = dev->data;
    1413                 :            :         struct uart_ns16550_tx_dma_params *tx_params = &data->async.tx_dma_params;
    1414                 :            : 
    1415                 :            :         (void)k_work_cancel_delayable(&data->async.tx_dma_params.timeout_work);
    1416                 :            : 
    1417                 :            :         struct uart_event event = {
    1418                 :            :                 .type = UART_TX_DONE,
    1419                 :            :                 .data.tx.buf = tx_params->buf,
    1420                 :            :                 .data.tx.len = tx_params->buf_len
    1421                 :            :         };
    1422                 :            : 
    1423                 :            :         tx_params->buf = NULL;
    1424                 :            :         tx_params->buf_len = 0U;
    1425                 :            : 
    1426                 :            :         async_user_callback(dev, &event);
    1427                 :            : }
    1428                 :            : #endif
    1429                 :            : 
    1430                 :            : static void async_evt_rx_rdy(const struct device *dev)
    1431                 :            : {
    1432                 :            :         struct uart_ns16550_dev_data *data = dev->data;
    1433                 :            :         struct uart_ns16550_rx_dma_params *dma_params = &data->async.rx_dma_params;
    1434                 :            : 
    1435                 :            :         struct uart_event event = {
    1436                 :            :                 .type = UART_RX_RDY,
    1437                 :            :                 .data.rx.buf = dma_params->buf,
    1438                 :            :                 .data.rx.len = dma_params->counter - dma_params->offset,
    1439                 :            :                 .data.rx.offset = dma_params->offset
    1440                 :            :         };
    1441                 :            : 
    1442                 :            :         dma_params->offset = dma_params->counter;
    1443                 :            : 
    1444                 :            :         if (event.data.rx.len > 0) {
    1445                 :            :                 async_user_callback(dev, &event);
    1446                 :            :         }
    1447                 :            : }
    1448                 :            : 
    1449                 :            : static void async_evt_rx_buf_release(const struct device *dev)
    1450                 :            : {
    1451                 :            :         struct uart_ns16550_dev_data *data = (struct uart_ns16550_dev_data *)dev->data;
    1452                 :            :         struct uart_event evt = {
    1453                 :            :                 .type = UART_RX_BUF_RELEASED,
    1454                 :            :                 .data.rx_buf.buf = data->async.rx_dma_params.buf
    1455                 :            :         };
    1456                 :            : 
    1457                 :            :         async_user_callback(dev, &evt);
    1458                 :            :         data->async.rx_dma_params.buf = NULL;
    1459                 :            :         data->async.rx_dma_params.buf_len = 0U;
    1460                 :            :         data->async.rx_dma_params.offset = 0U;
    1461                 :            :         data->async.rx_dma_params.counter = 0U;
    1462                 :            : }
    1463                 :            : 
    1464                 :            : static void async_evt_rx_buf_request(const struct device *dev)
    1465                 :            : {
    1466                 :            :         struct uart_event evt = {
    1467                 :            :                 .type = UART_RX_BUF_REQUEST
    1468                 :            :         };
    1469                 :            :         async_user_callback(dev, &evt);
    1470                 :            : }
    1471                 :            : 
    1472                 :            : static void uart_ns16550_async_rx_flush(const struct device *dev)
    1473                 :            : {
    1474                 :            :         struct uart_ns16550_dev_data *data = dev->data;
    1475                 :            :         struct uart_ns16550_rx_dma_params *dma_params = &data->async.rx_dma_params;
    1476                 :            :         struct dma_status status;
    1477                 :            : 
    1478                 :            :         dma_get_status(dma_params->dma_dev,
    1479                 :            :                        dma_params->dma_channel,
    1480                 :            :                        &status);
    1481                 :            : 
    1482                 :            :         const int rx_count = dma_params->buf_len - status.pending_length;
    1483                 :            : 
    1484                 :            :         if (rx_count > dma_params->counter) {
    1485                 :            :                 dma_params->counter = rx_count;
    1486                 :            :                 async_evt_rx_rdy(dev);
    1487                 :            :         }
    1488                 :            : }
    1489                 :            : 
    1490                 :            : static int uart_ns16550_rx_disable(const struct device *dev)
    1491                 :            : {
    1492                 :            :         struct uart_ns16550_dev_data *data = (struct uart_ns16550_dev_data *)dev->data;
    1493                 :            :         struct uart_ns16550_rx_dma_params *dma_params = &data->async.rx_dma_params;
    1494                 :            :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1495                 :            :         int ret = 0;
    1496                 :            : 
    1497                 :            :         if (!device_is_ready(dma_params->dma_dev)) {
    1498                 :            :                 ret = -ENODEV;
    1499                 :            :                 goto out;
    1500                 :            :         }
    1501                 :            : 
    1502                 :            :         (void)k_work_cancel_delayable(&data->async.rx_dma_params.timeout_work);
    1503                 :            : 
    1504                 :            :         if (dma_params->buf && (dma_params->buf_len > 0)) {
    1505                 :            :                 uart_ns16550_async_rx_flush(dev);
    1506                 :            :                 async_evt_rx_buf_release(dev);
    1507                 :            :                 if (data->async.next_rx_buffer != NULL) {
    1508                 :            :                         dma_params->buf = data->async.next_rx_buffer;
    1509                 :            :                         dma_params->buf_len = data->async.next_rx_buffer_len;
    1510                 :            :                         data->async.next_rx_buffer = NULL;
    1511                 :            :                         data->async.next_rx_buffer_len = 0;
    1512                 :            :                         async_evt_rx_buf_release(dev);
    1513                 :            :                 }
    1514                 :            :         }
    1515                 :            :         ret = dma_stop(dma_params->dma_dev,
    1516                 :            :                        dma_params->dma_channel);
    1517                 :            : 
    1518                 :            :         struct uart_event event = {
    1519                 :            :                 .type = UART_RX_DISABLED
    1520                 :            :         };
    1521                 :            : 
    1522                 :            :         async_user_callback(dev, &event);
    1523                 :            : 
    1524                 :            : out:
    1525                 :            :         k_spin_unlock(&data->lock, key);
    1526                 :            :         return ret;
    1527                 :            : }
    1528                 :            : 
    1529                 :            : static void prepare_rx_dma_block_config(const struct device *dev)
    1530                 :            : {
    1531                 :            :         struct uart_ns16550_dev_data *data = (struct uart_ns16550_dev_data *)dev->data;
    1532                 :            :         struct uart_ns16550_rx_dma_params *rx_dma_params = &data->async.rx_dma_params;
    1533                 :            : 
    1534                 :            :         assert(rx_dma_params->buf != NULL);
    1535                 :            :         assert(rx_dma_params->buf_len > 0);
    1536                 :            : 
    1537                 :            :         struct dma_block_config *head_block_config = &rx_dma_params->active_dma_block;
    1538                 :            : 
    1539                 :            :         head_block_config->dest_address = (uintptr_t)rx_dma_params->buf;
    1540                 :            :         head_block_config->source_address = data->phys_addr;
    1541                 :            :         head_block_config->block_size = rx_dma_params->buf_len;
    1542                 :            : }
    1543                 :            : 
    1544                 :            : #if UART_NS16550_DMAS_ENABLED
    1545                 :            : static void dma_callback(const struct device *dev, void *user_data, uint32_t channel,
    1546                 :            :                          int status)
    1547                 :            : {
    1548                 :            :         struct device *uart_dev = (struct device *)user_data;
    1549                 :            :         struct uart_ns16550_dev_data *data = (struct uart_ns16550_dev_data *)uart_dev->data;
    1550                 :            :         struct uart_ns16550_rx_dma_params *rx_params = &data->async.rx_dma_params;
    1551                 :            :         struct uart_ns16550_tx_dma_params *tx_params = &data->async.tx_dma_params;
    1552                 :            : 
    1553                 :            :         if (channel == tx_params->dma_channel) {
    1554                 :            :                 async_evt_tx_done(uart_dev);
    1555                 :            :         } else if (channel == rx_params->dma_channel) {
    1556                 :            : 
    1557                 :            :                 rx_params->counter = rx_params->buf_len;
    1558                 :            : 
    1559                 :            :                 async_evt_rx_rdy(uart_dev);
    1560                 :            :                 async_evt_rx_buf_release(uart_dev);
    1561                 :            : 
    1562                 :            :                 rx_params->buf = data->async.next_rx_buffer;
    1563                 :            :                 rx_params->buf_len = data->async.next_rx_buffer_len;
    1564                 :            :                 data->async.next_rx_buffer = NULL;
    1565                 :            :                 data->async.next_rx_buffer_len = 0U;
    1566                 :            : 
    1567                 :            :                 if (rx_params->buf != NULL &&
    1568                 :            :                     rx_params->buf_len > 0) {
    1569                 :            :                         dma_reload(dev, rx_params->dma_channel, data->phys_addr,
    1570                 :            :                                    (uintptr_t)rx_params->buf, rx_params->buf_len);
    1571                 :            :                         dma_start(dev, rx_params->dma_channel);
    1572                 :            :                         async_evt_rx_buf_request(uart_dev);
    1573                 :            :                 } else {
    1574                 :            :                         uart_ns16550_rx_disable(uart_dev);
    1575                 :            :                 }
    1576                 :            :         }
    1577                 :            : }
    1578                 :            : #endif
    1579                 :            : 
    1580                 :            : static int uart_ns16550_callback_set(const struct device *dev, uart_callback_t callback,
    1581                 :            :                                     void *user_data)
    1582                 :            : {
    1583                 :            :         struct uart_ns16550_dev_data *data = dev->data;
    1584                 :            : 
    1585                 :            :         data->async.user_callback = callback;
    1586                 :            :         data->async.user_data = user_data;
    1587                 :            : 
    1588                 :            :         return 0;
    1589                 :            : }
    1590                 :            : 
    1591                 :            : static int uart_ns16550_tx(const struct device *dev, const uint8_t *buf, size_t len,
    1592                 :            :                           int32_t timeout_us)
    1593                 :            : {
    1594                 :            :         struct uart_ns16550_dev_data *data = dev->data;
    1595                 :            :         struct uart_ns16550_tx_dma_params *tx_params = &data->async.tx_dma_params;
    1596                 :            :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1597                 :            :         int ret = 0;
    1598                 :            : 
    1599                 :            :         if (!device_is_ready(tx_params->dma_dev)) {
    1600                 :            :                 ret = -ENODEV;
    1601                 :            :                 goto out;
    1602                 :            :         }
    1603                 :            : 
    1604                 :            :         tx_params->buf = buf;
    1605                 :            :         tx_params->buf_len = len;
    1606                 :            :         tx_params->active_dma_block.source_address = (uintptr_t)buf;
    1607                 :            :         tx_params->active_dma_block.dest_address = data->phys_addr;
    1608                 :            :         tx_params->active_dma_block.block_size = len;
    1609                 :            :         tx_params->active_dma_block.next_block = NULL;
    1610                 :            : 
    1611                 :            :         ret = dma_config(tx_params->dma_dev,
    1612                 :            :                          tx_params->dma_channel,
    1613                 :            :                          (struct dma_config *)&tx_params->dma_cfg);
    1614                 :            : 
    1615                 :            :         if (ret == 0) {
    1616                 :            :                 ret = dma_start(tx_params->dma_dev,
    1617                 :            :                                 tx_params->dma_channel);
    1618                 :            :                 if (ret) {
    1619                 :            :                         ret = -EIO;
    1620                 :            :                         goto out;
    1621                 :            :                 }
    1622                 :            :                 async_timer_start(&data->async.tx_dma_params.timeout_work, timeout_us);
    1623                 :            :         }
    1624                 :            : 
    1625                 :            : out:
    1626                 :            :         k_spin_unlock(&data->lock, key);
    1627                 :            :         return ret;
    1628                 :            : }
    1629                 :            : 
    1630                 :            : static int uart_ns16550_tx_abort(const struct device *dev)
    1631                 :            : {
    1632                 :            :         struct uart_ns16550_dev_data *data = dev->data;
    1633                 :            :         struct uart_ns16550_tx_dma_params *tx_params = &data->async.tx_dma_params;
    1634                 :            :         struct dma_status status;
    1635                 :            :         int ret = 0;
    1636                 :            :         size_t bytes_tx;
    1637                 :            : 
    1638                 :            :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1639                 :            : 
    1640                 :            :         if (!device_is_ready(tx_params->dma_dev)) {
    1641                 :            :                 ret = -ENODEV;
    1642                 :            :                 goto out;
    1643                 :            :         }
    1644                 :            : 
    1645                 :            :         (void)k_work_cancel_delayable(&data->async.tx_dma_params.timeout_work);
    1646                 :            : 
    1647                 :            :         ret = dma_stop(tx_params->dma_dev, tx_params->dma_channel);
    1648                 :            :         dma_get_status(tx_params->dma_dev,
    1649                 :            :                        tx_params->dma_channel,
    1650                 :            :                        &status);
    1651                 :            :         bytes_tx = tx_params->buf_len - status.pending_length;
    1652                 :            : 
    1653                 :            :         if (ret == 0) {
    1654                 :            :                 struct uart_event tx_aborted_event = {
    1655                 :            :                         .type = UART_TX_ABORTED,
    1656                 :            :                         .data.tx.buf = tx_params->buf,
    1657                 :            :                         .data.tx.len = bytes_tx
    1658                 :            :                 };
    1659                 :            :                 async_user_callback(dev, &tx_aborted_event);
    1660                 :            :         }
    1661                 :            : out:
    1662                 :            :         k_spin_unlock(&data->lock, key);
    1663                 :            :         return ret;
    1664                 :            : }
    1665                 :            : 
    1666                 :            : static int uart_ns16550_rx_enable(const struct device *dev, uint8_t *buf, const size_t len,
    1667                 :            :                                   const int32_t timeout_us)
    1668                 :            : {
    1669                 :            :         struct uart_ns16550_dev_data *data = dev->data;
    1670                 :            :         const struct uart_ns16550_device_config *config = dev->config;
    1671                 :            :         struct uart_ns16550_rx_dma_params *rx_dma_params = &data->async.rx_dma_params;
    1672                 :            :         int ret = 0;
    1673                 :            :         k_spinlock_key_t key = k_spin_lock(&data->lock);
    1674                 :            : 
    1675                 :            :         if (!device_is_ready(rx_dma_params->dma_dev)) {
    1676                 :            :                 ret = -ENODEV;
    1677                 :            :                 goto out;
    1678                 :            :         }
    1679                 :            : 
    1680                 :            :         rx_dma_params->timeout_us = timeout_us;
    1681                 :            :         rx_dma_params->buf = buf;
    1682                 :            :         rx_dma_params->buf_len = len;
    1683                 :            : 
    1684                 :            : #if defined(CONFIG_UART_NS16550_INTEL_LPSS_DMA)
    1685                 :            :         ns16550_outword(config, MST(dev), UNMASK_LPSS_INT(rx_dma_params->dma_channel));
    1686                 :            : #else
    1687                 :            :         ns16550_outbyte(config, IER(dev),
    1688                 :            :                         (ns16550_inbyte(config, IER(dev)) | IER_RXRDY));
    1689                 :            :         ns16550_outbyte(config, FCR(dev), FCR_FIFO);
    1690                 :            : #endif
    1691                 :            :         prepare_rx_dma_block_config(dev);
    1692                 :            :         dma_config(rx_dma_params->dma_dev,
    1693                 :            :                    rx_dma_params->dma_channel,
    1694                 :            :                    (struct dma_config *)&rx_dma_params->dma_cfg);
    1695                 :            :         dma_start(rx_dma_params->dma_dev, rx_dma_params->dma_channel);
    1696                 :            :         async_evt_rx_buf_request(dev);
    1697                 :            : out:
    1698                 :            :         k_spin_unlock(&data->lock, key);
    1699                 :            :         return ret;
    1700                 :            : }
    1701                 :            : 
    1702                 :            : static int uart_ns16550_rx_buf_rsp(const struct device *dev, uint8_t *buf, size_t len)
    1703                 :            : {
    1704                 :            :         struct uart_ns16550_dev_data *data = dev->data;
    1705                 :            : 
    1706                 :            :         assert(data->async.next_rx_buffer == NULL);
    1707                 :            :         assert(data->async.next_rx_buffer_len == 0);
    1708                 :            :         data->async.next_rx_buffer = buf;
    1709                 :            :         data->async.next_rx_buffer_len = len;
    1710                 :            : 
    1711                 :            :         return 0;
    1712                 :            : }
    1713                 :            : 
    1714                 :            : static void uart_ns16550_async_rx_timeout(struct k_work *work)
    1715                 :            : {
    1716                 :            :         struct k_work_delayable *work_delay = CONTAINER_OF(work, struct k_work_delayable, work);
    1717                 :            :         struct uart_ns16550_rx_dma_params *rx_params =
    1718                 :            :                         CONTAINER_OF(work_delay, struct uart_ns16550_rx_dma_params,
    1719                 :            :                                      timeout_work);
    1720                 :            :         struct uart_ns16550_async_data *async_data =
    1721                 :            :                         CONTAINER_OF(rx_params, struct uart_ns16550_async_data,
    1722                 :            :                                      rx_dma_params);
    1723                 :            :         const struct device *dev = async_data->uart_dev;
    1724                 :            : 
    1725                 :            :         uart_ns16550_async_rx_flush(dev);
    1726                 :            : 
    1727                 :            : }
    1728                 :            : 
    1729                 :            : static void uart_ns16550_async_tx_timeout(struct k_work *work)
    1730                 :            : {
    1731                 :            :         struct k_work_delayable *work_delay = CONTAINER_OF(work, struct k_work_delayable, work);
    1732                 :            :         struct uart_ns16550_tx_dma_params *tx_params =
    1733                 :            :                         CONTAINER_OF(work_delay, struct uart_ns16550_tx_dma_params,
    1734                 :            :                                      timeout_work);
    1735                 :            :         struct uart_ns16550_async_data *async_data =
    1736                 :            :                         CONTAINER_OF(tx_params, struct uart_ns16550_async_data,
    1737                 :            :                                      tx_dma_params);
    1738                 :            :         const struct device *dev = async_data->uart_dev;
    1739                 :            : 
    1740                 :            :         (void)uart_ns16550_tx_abort(dev);
    1741                 :            : }
    1742                 :            : 
    1743                 :            : #endif /* CONFIG_UART_ASYNC_API */
    1744                 :            : 
    1745                 :            : static const struct uart_driver_api uart_ns16550_driver_api = {
    1746                 :            :         .poll_in = uart_ns16550_poll_in,
    1747                 :            :         .poll_out = uart_ns16550_poll_out,
    1748                 :            :         .err_check = uart_ns16550_err_check,
    1749                 :            : #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
    1750                 :            :         .configure = uart_ns16550_configure,
    1751                 :            :         .config_get = uart_ns16550_config_get,
    1752                 :            : #endif
    1753                 :            : #ifdef CONFIG_UART_INTERRUPT_DRIVEN
    1754                 :            : 
    1755                 :            :         .fifo_fill = uart_ns16550_fifo_fill,
    1756                 :            :         .fifo_read = uart_ns16550_fifo_read,
    1757                 :            :         .irq_tx_enable = uart_ns16550_irq_tx_enable,
    1758                 :            :         .irq_tx_disable = uart_ns16550_irq_tx_disable,
    1759                 :            :         .irq_tx_ready = uart_ns16550_irq_tx_ready,
    1760                 :            :         .irq_tx_complete = uart_ns16550_irq_tx_complete,
    1761                 :            :         .irq_rx_enable = uart_ns16550_irq_rx_enable,
    1762                 :            :         .irq_rx_disable = uart_ns16550_irq_rx_disable,
    1763                 :            :         .irq_rx_ready = uart_ns16550_irq_rx_ready,
    1764                 :            :         .irq_err_enable = uart_ns16550_irq_err_enable,
    1765                 :            :         .irq_err_disable = uart_ns16550_irq_err_disable,
    1766                 :            :         .irq_is_pending = uart_ns16550_irq_is_pending,
    1767                 :            :         .irq_update = uart_ns16550_irq_update,
    1768                 :            :         .irq_callback_set = uart_ns16550_irq_callback_set,
    1769                 :            : 
    1770                 :            : #endif
    1771                 :            : 
    1772                 :            : #ifdef CONFIG_UART_ASYNC_API
    1773                 :            :         .callback_set = uart_ns16550_callback_set,
    1774                 :            :         .tx = uart_ns16550_tx,
    1775                 :            :         .tx_abort = uart_ns16550_tx_abort,
    1776                 :            :         .rx_enable = uart_ns16550_rx_enable,
    1777                 :            :         .rx_disable = uart_ns16550_rx_disable,
    1778                 :            :         .rx_buf_rsp = uart_ns16550_rx_buf_rsp,
    1779                 :            : #endif
    1780                 :            : 
    1781                 :            : #ifdef CONFIG_UART_NS16550_LINE_CTRL
    1782                 :            :         .line_ctrl_set = uart_ns16550_line_ctrl_set,
    1783                 :            : #endif
    1784                 :            : 
    1785                 :            : #ifdef CONFIG_UART_NS16550_DRV_CMD
    1786                 :            :         .drv_cmd = uart_ns16550_drv_cmd,
    1787                 :            : #endif
    1788                 :            : };
    1789                 :            : 
    1790                 :            : #define UART_NS16550_IRQ_FLAGS(n) \
    1791                 :            :         COND_CODE_1(DT_INST_IRQ_HAS_CELL(n, sense),                           \
    1792                 :            :                     (DT_INST_IRQ(n, sense)),                                  \
    1793                 :            :                     (0))
    1794                 :            : 
    1795                 :            : /* IO-port or MMIO based UART */
    1796                 :            : #define UART_NS16550_IRQ_CONFIG(n)                                            \
    1797                 :            :         static void uart_ns16550_irq_config_func##n(const struct device *dev) \
    1798                 :            :         {                                                                     \
    1799                 :            :                 ARG_UNUSED(dev);                                              \
    1800                 :            :                 IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority),        \
    1801                 :            :                             uart_ns16550_isr, DEVICE_DT_INST_GET(n),          \
    1802                 :            :                             UART_NS16550_IRQ_FLAGS(n));                       \
    1803                 :            :                 irq_enable(DT_INST_IRQN(n));                                  \
    1804                 :            :         }
    1805                 :            : 
    1806                 :            : /* PCI(e) with auto IRQ detection */
    1807                 :            : #define UART_NS16550_IRQ_CONFIG_PCIE(n)                                       \
    1808                 :            :         static void uart_ns16550_irq_config_func##n(const struct device *dev) \
    1809                 :            :         {                                                                     \
    1810                 :            :                 BUILD_ASSERT(DT_INST_IRQN(n) == PCIE_IRQ_DETECT,              \
    1811                 :            :                              "Only runtime IRQ configuration is supported");  \
    1812                 :            :                 BUILD_ASSERT(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS),           \
    1813                 :            :                              "NS16550 PCIe requires dynamic interrupts");     \
    1814                 :            :                 const struct uart_ns16550_device_config *dev_cfg = dev->config;\
    1815                 :            :                 unsigned int irq = pcie_alloc_irq(dev_cfg->pcie->bdf);        \
    1816                 :            :                 if (irq == PCIE_CONF_INTR_IRQ_NONE) {                         \
    1817                 :            :                         return;                                               \
    1818                 :            :                 }                                                             \
    1819                 :            :                 pcie_connect_dynamic_irq(dev_cfg->pcie->bdf, irq,       \
    1820                 :            :                                      DT_INST_IRQ(n, priority),                \
    1821                 :            :                                     (void (*)(const void *))uart_ns16550_isr, \
    1822                 :            :                                     DEVICE_DT_INST_GET(n),                    \
    1823                 :            :                                     UART_NS16550_IRQ_FLAGS(n));               \
    1824                 :            :                 pcie_irq_enable(dev_cfg->pcie->bdf, irq);                    \
    1825                 :            :         }
    1826                 :            : 
    1827                 :            : #ifdef CONFIG_UART_INTERRUPT_DRIVEN
    1828                 :            : #define DEV_CONFIG_IRQ_FUNC_INIT(n) \
    1829                 :            :         .irq_config_func = uart_ns16550_irq_config_func##n,
    1830                 :            : #define UART_NS16550_IRQ_FUNC_DECLARE(n) \
    1831                 :            :         static void uart_ns16550_irq_config_func##n(const struct device *dev);
    1832                 :            : #define UART_NS16550_IRQ_FUNC_DEFINE(n) \
    1833                 :            :         UART_NS16550_IRQ_CONFIG(n)
    1834                 :            : 
    1835                 :            : #define DEV_CONFIG_PCIE_IRQ_FUNC_INIT(n) \
    1836                 :            :         .irq_config_func = uart_ns16550_irq_config_func##n,
    1837                 :            : #define UART_NS16550_PCIE_IRQ_FUNC_DECLARE(n) \
    1838                 :            :         static void uart_ns16550_irq_config_func##n(const struct device *dev);
    1839                 :            : #define UART_NS16550_PCIE_IRQ_FUNC_DEFINE(n) \
    1840                 :            :         UART_NS16550_IRQ_CONFIG_PCIE(n)
    1841                 :            : #else
    1842                 :            : /* !CONFIG_UART_INTERRUPT_DRIVEN */
    1843                 :            : #define DEV_CONFIG_IRQ_FUNC_INIT(n)
    1844                 :            : #define UART_NS16550_IRQ_FUNC_DECLARE(n)
    1845                 :            : #define UART_NS16550_IRQ_FUNC_DEFINE(n)
    1846                 :            : 
    1847                 :            : #define DEV_CONFIG_PCIE_IRQ_FUNC_INIT(n)
    1848                 :            : #define UART_NS16550_PCIE_IRQ_FUNC_DECLARE(n)
    1849                 :            : #define UART_NS16550_PCIE_IRQ_FUNC_DEFINE(n)
    1850                 :            : #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
    1851                 :            : 
    1852                 :            : #ifdef CONFIG_UART_ASYNC_API
    1853                 :            : #define DMA_PARAMS(n)                                                           \
    1854                 :            :         .async.tx_dma_params = {                                                \
    1855                 :            :                 .dma_dev =                                                      \
    1856                 :            :                         DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(n, tx)),        \
    1857                 :            :                 .dma_channel =                                                  \
    1858                 :            :                         DT_INST_DMAS_CELL_BY_NAME(n, tx, channel),              \
    1859                 :            :                 .dma_cfg = {                                                    \
    1860                 :            :                         .source_burst_length = 1,                               \
    1861                 :            :                         .dest_burst_length = 1,                                 \
    1862                 :            :                         .source_data_size = 1,                                  \
    1863                 :            :                         .dest_data_size = 1,                                    \
    1864                 :            :                         .complete_callback_en = 0,                              \
    1865                 :            :                         .error_callback_dis = 1,                                \
    1866                 :            :                         .block_count = 1,                                       \
    1867                 :            :                         .channel_direction = MEMORY_TO_PERIPHERAL,              \
    1868                 :            :                         .dma_slot = DT_INST_DMAS_CELL_BY_NAME(n, tx, channel),  \
    1869                 :            :                         .dma_callback = dma_callback,                           \
    1870                 :            :                         .user_data = (void *)DEVICE_DT_INST_GET(n)              \
    1871                 :            :                 },                                                              \
    1872                 :            :         },                                                                      \
    1873                 :            :         .async.rx_dma_params = {                                                \
    1874                 :            :                 .dma_dev =                                                      \
    1875                 :            :                         DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(n, rx)),        \
    1876                 :            :                 .dma_channel =                                                  \
    1877                 :            :                         DT_INST_DMAS_CELL_BY_NAME(n, rx, channel),              \
    1878                 :            :                 .dma_cfg = {                                                    \
    1879                 :            :                         .source_burst_length = 1,                               \
    1880                 :            :                         .dest_burst_length = 1,                                 \
    1881                 :            :                         .source_data_size = 1,                                  \
    1882                 :            :                         .dest_data_size = 1,                                    \
    1883                 :            :                         .complete_callback_en = 0,                              \
    1884                 :            :                         .error_callback_dis = 1,                                \
    1885                 :            :                         .block_count = 1,                                       \
    1886                 :            :                         .channel_direction = PERIPHERAL_TO_MEMORY,              \
    1887                 :            :                         .dma_slot = DT_INST_DMAS_CELL_BY_NAME(n, rx, channel),  \
    1888                 :            :                         .dma_callback = dma_callback,                           \
    1889                 :            :                         .user_data = (void *)DEVICE_DT_INST_GET(n)              \
    1890                 :            :                 },                                                              \
    1891                 :            :         },                                                                      \
    1892                 :            :         COND_CODE_0(DT_INST_ON_BUS(n, pcie),                                    \
    1893                 :            :                         (.phys_addr = DT_INST_REG_ADDR(n),), ())
    1894                 :            : 
    1895                 :            : #define DMA_PARAMS_NULL(n)                                                      \
    1896                 :            :         .async.tx_dma_params = {                                                \
    1897                 :            :                 .dma_dev = NULL                                                 \
    1898                 :            :         },                                                                      \
    1899                 :            :         .async.rx_dma_params = {                                                \
    1900                 :            :                 .dma_dev = NULL                                                 \
    1901                 :            :         },                                                                      \
    1902                 :            : 
    1903                 :            : #define DEV_DATA_ASYNC(n)                                                       \
    1904                 :            :         COND_CODE_0(DT_INST_PROP(n, io_mapped),                                 \
    1905                 :            :                         (COND_CODE_1(DT_INST_NODE_HAS_PROP(n, dmas),            \
    1906                 :            :                                 (DMA_PARAMS(n)), (DMA_PARAMS_NULL(n)))),        \
    1907                 :            :                                 (DMA_PARAMS_NULL(n)))
    1908                 :            : #else
    1909                 :            : #define DEV_DATA_ASYNC(n)
    1910                 :            : #endif /* CONFIG_UART_ASYNC_API */
    1911                 :            : 
    1912                 :            : 
    1913                 :            : #define UART_NS16550_COMMON_DEV_CFG_INITIALIZER(n)                                   \
    1914                 :            :                 COND_CODE_1(DT_INST_NODE_HAS_PROP(n, clock_frequency), (             \
    1915                 :            :                                 .sys_clk_freq = DT_INST_PROP(n, clock_frequency),    \
    1916                 :            :                                 .clock_dev = NULL,                                   \
    1917                 :            :                                 .clock_subsys = NULL,                                \
    1918                 :            :                         ), (                                                         \
    1919                 :            :                                 .sys_clk_freq = 0,                                   \
    1920                 :            :                                 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)),  \
    1921                 :            :                                 .clock_subsys = (clock_control_subsys_t) DT_INST_PHA(\
    1922                 :            :                                                                 0, clocks, clkid),   \
    1923                 :            :                         )                                                            \
    1924                 :            :                 )                                                                    \
    1925                 :            :                 IF_ENABLED(DT_INST_NODE_HAS_PROP(n, pcp),                            \
    1926                 :            :                         (.pcp = DT_INST_PROP_OR(n, pcp, 0),))                        \
    1927                 :            :                 .reg_interval = (1 << DT_INST_PROP(n, reg_shift)),                   \
    1928                 :            :                 IF_ENABLED(CONFIG_PINCTRL,                                           \
    1929                 :            :                         (.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),))              \
    1930                 :            :                 IF_ENABLED(DT_INST_NODE_HAS_PROP(n, resets),                         \
    1931                 :            :                         (.reset_spec = RESET_DT_SPEC_INST_GET(n),))
    1932                 :            : 
    1933                 :            : #define UART_NS16550_COMMON_DEV_DATA_INITIALIZER(n)                                  \
    1934                 :            :                 .uart_config.baudrate = DT_INST_PROP_OR(n, current_speed, 0),        \
    1935                 :            :                 .uart_config.parity = UART_CFG_PARITY_NONE,                          \
    1936                 :            :                 .uart_config.stop_bits = UART_CFG_STOP_BITS_1,                       \
    1937                 :            :                 .uart_config.data_bits = UART_CFG_DATA_BITS_8,                       \
    1938                 :            :                 .uart_config.flow_ctrl =                                             \
    1939                 :            :                         COND_CODE_1(DT_INST_PROP_OR(n, hw_flow_control, 0),          \
    1940                 :            :                                     (UART_CFG_FLOW_CTRL_RTS_CTS),                    \
    1941                 :            :                                     (UART_CFG_FLOW_CTRL_NONE)),                      \
    1942                 :            :                 IF_ENABLED(DT_INST_NODE_HAS_PROP(n, dlf),                            \
    1943                 :            :                         (.dlf = DT_INST_PROP_OR(n, dlf, 0),))                        \
    1944                 :            :                 DEV_DATA_ASYNC(n)                                                    \
    1945                 :            : 
    1946                 :            : #define UART_NS16550_DEVICE_IO_MMIO_INIT(n)                                          \
    1947                 :            :         UART_NS16550_IRQ_FUNC_DECLARE(n);                                            \
    1948                 :            :         IF_ENABLED(CONFIG_PINCTRL, (PINCTRL_DT_INST_DEFINE(n)));                     \
    1949                 :            :         static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_##n = {  \
    1950                 :            :                 COND_CODE_1(DT_INST_PROP_OR(n, io_mapped, 0),                        \
    1951                 :            :                             (.port = DT_INST_REG_ADDR(n),),                          \
    1952                 :            :                             (DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)),))                 \
    1953                 :            :                 IF_ENABLED(DT_INST_PROP_OR(n, io_mapped, 0),                         \
    1954                 :            :                            (.io_map = true,))                                        \
    1955                 :            :                 UART_NS16550_COMMON_DEV_CFG_INITIALIZER(n)                           \
    1956                 :            :                 DEV_CONFIG_IRQ_FUNC_INIT(n)                                          \
    1957                 :            :         };                                                                           \
    1958                 :            :         static struct uart_ns16550_dev_data uart_ns16550_dev_data_##n = {            \
    1959                 :            :                 UART_NS16550_COMMON_DEV_DATA_INITIALIZER(n)                          \
    1960                 :            :         };                                                                           \
    1961                 :            :         DEVICE_DT_INST_DEFINE(n, &uart_ns16550_init, NULL,                           \
    1962                 :            :                               &uart_ns16550_dev_data_##n, &uart_ns16550_dev_cfg_##n, \
    1963                 :            :                               PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY,             \
    1964                 :            :                               &uart_ns16550_driver_api);                             \
    1965                 :            :         UART_NS16550_IRQ_FUNC_DEFINE(n)
    1966                 :            : 
    1967                 :            : #define UART_NS16550_DEVICE_PCIE_INIT(n)                                             \
    1968                 :            :         UART_NS16550_PCIE_IRQ_FUNC_DECLARE(n);                                       \
    1969                 :            :         DEVICE_PCIE_INST_DECLARE(n);                                                 \
    1970                 :            :         IF_ENABLED(CONFIG_PINCTRL, (PINCTRL_DT_INST_DEFINE(n)));                     \
    1971                 :            :         static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_##n = {  \
    1972                 :            :                 UART_NS16550_COMMON_DEV_CFG_INITIALIZER(n)                           \
    1973                 :            :                 DEV_CONFIG_PCIE_IRQ_FUNC_INIT(n)                                     \
    1974                 :            :                 DEVICE_PCIE_INST_INIT(n, pcie)                                       \
    1975                 :            :         };                                                                           \
    1976                 :            :         static struct uart_ns16550_dev_data uart_ns16550_dev_data_##n = {            \
    1977                 :            :                 UART_NS16550_COMMON_DEV_DATA_INITIALIZER(n)                          \
    1978                 :            :         };                                                                           \
    1979                 :            :         DEVICE_DT_INST_DEFINE(n, &uart_ns16550_init, NULL,                           \
    1980                 :            :                               &uart_ns16550_dev_data_##n, &uart_ns16550_dev_cfg_##n, \
    1981                 :            :                               PRE_KERNEL_1,            \
    1982                 :            :                               CONFIG_SERIAL_INIT_PRIORITY,                           \
    1983                 :            :                               &uart_ns16550_driver_api);                             \
    1984                 :            :         UART_NS16550_PCIE_IRQ_FUNC_DEFINE(n)
    1985                 :            : 
    1986                 :            : #define UART_NS16550_DEVICE_INIT(n)                                                  \
    1987                 :            :         COND_CODE_1(DT_INST_ON_BUS(n, pcie),                                         \
    1988                 :            :                     (UART_NS16550_DEVICE_PCIE_INIT(n)),                              \
    1989                 :            :                     (UART_NS16550_DEVICE_IO_MMIO_INIT(n)))
    1990                 :            : 
    1991                 :          1 : DT_INST_FOREACH_STATUS_OKAY(UART_NS16550_DEVICE_INIT)

Generated by: LCOV version 1.16-3-g92e2121