drivers: prepare 16550 UART driver to support PCI

prepare 16550 UART driver to support PCI:

- [breaking change] change argument of uart_ioctl() from `struct file *filep` to `FAR struct u16550_s *priv`
  Also fix moxart_16550.c build related to this change

- [breaking change] change argument of uart_getreg() and uart_putreg from `uart_addrwidth_t base` to `FAR struct u16550_s *priv`
  Also fix arch/x86/src/qemu/qemu_serial.c and arch/x86_64/src/intel64/intel64_serial.c related to this change

- [breaking change] change argument of uart_dmachan() from `uart_addrwidth_t base` to `FAR struct u16550_s *priv`

- move `struct u16550_s` to public header

- generalize UART_XXX_OFFSET so we can use it with any register increment

- make u16550_bind(), u16550_interrupt(), u16550_interrupt() public

- remove arch/or1k/src/common/or1k_uart.c and use common 16550 MIMO interfacve

- change irq type in `struct u16550_s` from uint8_t to int to match MSI API

Signed-off-by: p-szafonimateusz <p-szafonimateusz@xiaomi.com>
This commit is contained in:
p-szafonimateusz
2024-09-12 10:12:39 +02:00
committed by Xiang Xiao
parent c7e8fd43a4
commit ceb2921d79
8 changed files with 359 additions and 279 deletions
+5 -8
View File
@@ -69,15 +69,12 @@ void uart_decodeirq(int irq, void *context)
}
#ifdef CONFIG_SERIAL_UART_ARCH_IOCTL
int uart_ioctl(struct file *filep, int cmd, unsigned long arg)
int uart_ioctl(FAR struct u16550_s *priv, int cmd, unsigned long arg)
{
struct inode *inode = filep->f_inode;
struct uart_dev_s *dev = inode->i_private;
struct u16550_s *priv = (struct u16550_s *)dev->priv;
int ret = -ENOTTY;
uint32_t vmode;
unsigned int opmode;
int bitm_off;
int ret = -ENOTTY;
uint32_t vmode;
unsigned int opmode;
int bitm_off;
/* TODO: calculate bit offset from UART_BASE address.
* E.g.:
-45
View File
@@ -1,45 +0,0 @@
/****************************************************************************
* arch/or1k/src/common/or1k_uart.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <nuttx/serial/uart_16550.h>
#include "or1k_internal.h"
/****************************************************************************
* Public Functions
****************************************************************************/
uart_datawidth_t uart_getreg(uart_addrwidth_t base, unsigned int offset)
{
return *(uint8_t *)(base + offset);
}
void uart_putreg(uart_addrwidth_t base, unsigned int offset,
uart_datawidth_t value)
{
*(uint8_t *)(base + offset) = value;
}
-1
View File
@@ -40,7 +40,6 @@ CMN_CSRCS = or1k_initialize.c \
or1k_idle.c \
or1k_irq.c \
or1k_nputs.c \
or1k_uart.c \
or1k_timer.c \
or1k_doirq.c \
or1k_cpuinfo.c \
+4 -4
View File
@@ -52,15 +52,15 @@
*
****************************************************************************/
uart_datawidth_t uart_getreg(uart_addrwidth_t base, unsigned int offset)
uart_datawidth_t uart_getreg(struct u16550_s *priv, unsigned int offset)
{
return inb(base + offset);
return inb(priv->uartbase + offset);
}
void uart_putreg(uart_addrwidth_t base,
void uart_putreg(struct u16550_s *priv,
unsigned int offset, uart_datawidth_t value)
{
outb(value, base + offset);
outb(value, priv->uartbase + offset);
}
#else /* USE_SERIALDRIVER */
+4 -4
View File
@@ -52,12 +52,12 @@
*
****************************************************************************/
uart_datawidth_t uart_getreg(uart_addrwidth_t base, unsigned int offset)
uart_datawidth_t uart_getreg(struct u16550_s *priv, unsigned int offset)
{
return inb(base + offset);
return inb(priv->uartbase + offset);
}
void uart_putreg(uart_addrwidth_t base, unsigned int offset,
void uart_putreg(struct u16550_s *priv, unsigned int offset,
uart_datawidth_t value)
{
/* Intel x86 platform require OUT2 of MCR being set
@@ -69,7 +69,7 @@ void uart_putreg(uart_addrwidth_t base, unsigned int offset,
value |= UART_MCR_OUT2;
}
outb(value, base + offset);
outb(value, priv->uartbase + offset);
}
#else /* USE_SERIALDRIVER */
@@ -84,6 +84,7 @@ CONFIG_PTHREAD_STACK_DEFAULT=1024
CONFIG_RAM_SIZE=4194304
CONFIG_RAM_START=0x0000
CONFIG_RAW_BINARY=y
CONFIG_SERIAL_UART_ARCH_MMIO=y
CONFIG_START_DAY=7
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2012
File diff suppressed because it is too large Load Diff
+112 -39
View File
@@ -27,7 +27,8 @@
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <nuttx/serial/serial.h>
#ifdef CONFIG_16550_UART
@@ -37,12 +38,10 @@
/* CONFIGURATION ************************************************************/
/* Are any UARTs enabled? */
#undef HAVE_UART
#if defined(CONFIG_16550_UART0) || defined(CONFIG_16550_UART1) || \
defined(CONFIG_16550_UART2) || defined(CONFIG_16550_UART3)
# define HAVE_UART 1
#undef HAVE_16550_UART_DMA
#if defined(CONFIG_16550_UART0_DMA) || defined(CONFIG_16550_UART1_DMA) || \
defined(CONFIG_16550_UART2_DMA) || defined(CONFIG_16550_UART3_DMA)
# define HAVE_16550_UART_DMA 1
#endif
/* We need to be told the address increment between registers and the
@@ -173,33 +172,20 @@
/* Register offsets *********************************************************/
#define UART_RBR_INCR 0 /* (DLAB =0) Receiver Buffer Register */
#define UART_THR_INCR 0 /* (DLAB =0) Transmit Holding Register */
#define UART_DLL_INCR 0 /* (DLAB =1) Divisor Latch LSB */
#define UART_DLM_INCR 1 /* (DLAB =1) Divisor Latch MSB */
#define UART_IER_INCR 1 /* (DLAB =0) Interrupt Enable Register */
#define UART_IIR_INCR 2 /* Interrupt ID Register */
#define UART_FCR_INCR 2 /* FIFO Control Register */
#define UART_LCR_INCR 3 /* Line Control Register */
#define UART_MCR_INCR 4 /* Modem Control Register */
#define UART_LSR_INCR 5 /* Line Status Register */
#define UART_MSR_INCR 6 /* Modem Status Register */
#define UART_SCR_INCR 7 /* Scratch Pad Register */
#define UART_USR_INCR 31 /* UART Status Register */
#define UART_RBR_OFFSET (CONFIG_16550_REGINCR*UART_RBR_INCR)
#define UART_THR_OFFSET (CONFIG_16550_REGINCR*UART_THR_INCR)
#define UART_DLL_OFFSET (CONFIG_16550_REGINCR*UART_DLL_INCR)
#define UART_DLM_OFFSET (CONFIG_16550_REGINCR*UART_DLM_INCR)
#define UART_IER_OFFSET (CONFIG_16550_REGINCR*UART_IER_INCR)
#define UART_IIR_OFFSET (CONFIG_16550_REGINCR*UART_IIR_INCR)
#define UART_FCR_OFFSET (CONFIG_16550_REGINCR*UART_FCR_INCR)
#define UART_LCR_OFFSET (CONFIG_16550_REGINCR*UART_LCR_INCR)
#define UART_MCR_OFFSET (CONFIG_16550_REGINCR*UART_MCR_INCR)
#define UART_LSR_OFFSET (CONFIG_16550_REGINCR*UART_LSR_INCR)
#define UART_MSR_OFFSET (CONFIG_16550_REGINCR*UART_MSR_INCR)
#define UART_SCR_OFFSET (CONFIG_16550_REGINCR*UART_SCR_INCR)
#define UART_USR_OFFSET (CONFIG_16550_REGINCR*UART_USR_INCR)
#define UART_RBR_OFFSET 0 /* (DLAB =0) Receiver Buffer Register */
#define UART_THR_OFFSET 0 /* (DLAB =0) Transmit Holding Register */
#define UART_DLL_OFFSET 0 /* (DLAB =1) Divisor Latch LSB */
#define UART_DLM_OFFSET 1 /* (DLAB =1) Divisor Latch MSB */
#define UART_IER_OFFSET 1 /* (DLAB =0) Interrupt Enable Register */
#define UART_IIR_OFFSET 2 /* Interrupt ID Register */
#define UART_FCR_OFFSET 2 /* FIFO Control Register */
#define UART_LCR_OFFSET 3 /* Line Control Register */
#define UART_MCR_OFFSET 4 /* Modem Control Register */
#define UART_LSR_OFFSET 5 /* Line Status Register */
#define UART_MSR_OFFSET 6 /* Modem Status Register */
#define UART_SCR_OFFSET 7 /* Scratch Pad Register */
#define UART_USR_OFFSET 31 /* UART Status Register */
#define UART_DLF_OFFSET 48 /* Divisor Latch Fraction Register */
/* Register bit definitions *************************************************/
@@ -333,6 +319,64 @@ typedef uint64_t uart_addrwidth_t;
* Public Data
****************************************************************************/
/* UART 16550 ops */
struct u16550_s;
struct u16550_ops_s
{
CODE int (*isr)(int irq, FAR void *context, FAR void *arg);
CODE uart_datawidth_t (*getreg)(FAR struct u16550_s *priv,
unsigned int offset);
CODE void (*putreg)(FAR struct u16550_s *priv,
unsigned int offset,
uart_datawidth_t value);
CODE int (*ioctl)(FAR struct u16550_s *priv, int cmd, unsigned long arg);
CODE FAR struct dma_chan_s *(*dmachan)(FAR struct u16550_s *priv,
unsigned int ident);
};
/* UART 16550 private data */
struct u16550_s
{
/* UART 16550 operations */
FAR const struct u16550_ops_s *ops;
uart_addrwidth_t uartbase; /* Base address of UART registers */
uint8_t regincr;
#ifdef HAVE_16550_UART_DMA
int32_t dmatx;
FAR struct dma_chan_s *chantx;
int32_t dmarx;
FAR struct dma_chan_s *chanrx;
FAR char *dmarxbuf;
size_t dmarxsize;
volatile size_t dmarxhead;
volatile size_t dmarxtail;
int32_t dmarxtimeout;
#endif
#if !defined(CONFIG_16550_SUPRESS_CONFIG) || defined(HAVE_16550_UART_DMA)
uint32_t baud; /* Configured baud */
uint32_t uartclk; /* UART clock frequency */
#endif
#ifdef CONFIG_CLK
FAR const char *clk_name; /* UART clock name */
FAR struct clk_s *mclk; /* UART clock descriptor */
#endif
uart_datawidth_t ier; /* Saved IER value */
int irq; /* IRQ associated with this UART */
#ifndef CONFIG_16550_SUPRESS_CONFIG
uint8_t parity; /* 0=none, 1=odd, 2=even */
uint8_t bits; /* Number of bits (7 or 8) */
bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */
#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
bool flow; /* flow control (RTS/CTS) enabled */
#endif
#endif
uart_datawidth_t rxtrigger; /* RX trigger level */
};
/****************************************************************************
* Public Functions Definitions
****************************************************************************/
@@ -363,6 +407,36 @@ void u16550_earlyserialinit(void);
void u16550_serialinit(void);
/****************************************************************************
* Name: u16550_bind
*
* Description:
* Bind 16550 compatible device with this driver.
*
****************************************************************************/
int u16550_bind(FAR uart_dev_t *dev);
/****************************************************************************
* Name: u16550_interrupt
*
* Description:
* Handle UART 16550 interrupt.
*
****************************************************************************/
int u16550_interrupt(int irq, FAR void *context, FAR void *arg);
/****************************************************************************
* Name: u16550_putc
*
* Description:
* Write one character to the UART (polled)
*
****************************************************************************/
void u16550_putc(FAR struct u16550_s *priv, int ch);
/****************************************************************************
* Name: uart_getreg(), uart_putreg(), uart_ioctl()
*
@@ -374,17 +448,16 @@ void u16550_serialinit(void);
****************************************************************************/
#ifndef CONFIG_SERIAL_UART_ARCH_MMIO
uart_datawidth_t uart_getreg(uart_addrwidth_t base, unsigned int offset);
void uart_putreg(uart_addrwidth_t base,
uart_datawidth_t uart_getreg(FAR struct u16550_s *priv, unsigned int offset);
void uart_putreg(FAR struct u16550_s *priv,
unsigned int offset,
uart_datawidth_t value);
#endif
struct file; /* Forward reference */
int uart_ioctl(struct file *filep, int cmd, unsigned long arg);
int uart_ioctl(FAR struct u16550_s *priv, int cmd, unsigned long arg);
struct dma_chan_s;
FAR struct dma_chan_s *uart_dmachan(uart_addrwidth_t base,
FAR struct dma_chan_s *uart_dmachan(FAR struct u16550_s *priv,
unsigned int ident);
#endif /* CONFIG_16550_UART */