[PATCH 2/7] serial: bflb_uart: add Bouffalolab UART Driver
Ilpo Järvinen
ilpo.jarvinen at linux.intel.com
Mon Nov 21 05:59:13 PST 2022
On Sun, 20 Nov 2022, Jisheng Zhang wrote:
> Add the driver for Bouffalolab UART IP which is found in Bouffalolab
> SoCs such as bl808.
>
> UART driver probe will create path named "/dev/ttySx".
>
> Signed-off-by: Jisheng Zhang <jszhang at kernel.org>
> diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
> index 238a9557b487..8509cdc11d87 100644
> --- a/drivers/tty/serial/Makefile
> +++ b/drivers/tty/serial/Makefile
> @@ -25,6 +25,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
>
> obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
> obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
> +obj-$(CONFIG_SERIAL_BFLB) += bflb_uart.o
> obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
> obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o
> obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
> diff --git a/drivers/tty/serial/bflb_uart.c b/drivers/tty/serial/bflb_uart.c
> new file mode 100644
> index 000000000000..65f98ccf8fa8
> --- /dev/null
> +++ b/drivers/tty/serial/bflb_uart.c
> @@ -0,0 +1,659 @@
> +#define UART_FIFO_CONFIG_1 (0x84)
> +#define UART_TX_FIFO_CNT_SFT 0
> +#define UART_TX_FIFO_CNT_MSK GENMASK(5, 0)
> +#define UART_RX_FIFO_CNT_MSK GENMASK(13, 8)
> +#define UART_TX_FIFO_TH_SFT 16
Use FIELD_PREP() instead of adding a separate *_SFT define.
> +#define UART_TX_FIFO_TH_MSK GENMASK(20, 16)
> +#define UART_RX_FIFO_TH_SFT 24
> +#define UART_RX_FIFO_TH_MSK GENMASK(28, 24)
> +#define UART_FIFO_WDATA 0x88
> +#define UART_FIFO_RDATA 0x8c
> +#define UART_FIFO_RDATA_MSK GENMASK(7, 0)
> + val = rdl(port, UART_URX_CONFIG);
> + val &= ~UART_CR_URX_EN;
> + wrl(port, UART_URX_CONFIG, val);
> +
> + val = rdl(port, UART_INT_MASK);
> + val |= UART_URX_FIFO_INT | UART_URX_RTO_INT |
> + UART_URX_FER_INT;
Fits to single line.
> + port->type = PORT_BFLB;
> +
> + /* Clear mask, so no surprise interrupts. */
> + val = rdl(port, UART_INT_MASK);
> + val |= UART_UTX_END_INT;
> + val |= UART_UTX_FIFO_INT;
> + val |= UART_URX_FIFO_INT;
> + val |= UART_URX_RTO_INT;
> + val |= UART_URX_FER_INT;
Why to split it to this many lines?
> + spin_lock_irqsave(&port->lock, flags);
> +
> + val = rdl(port, UART_INT_MASK);
> + val |= 0xfff;
In most of the other places, the bits used with UART_INT_MASK are named,
but for some reason you don't do it here and the bits extend beyond the
ones which are defined with name.
> + wrl(port, UART_INT_MASK, val);
> +
> + wrl(port, UART_DATA_CONFIG, 0);
> + wrl(port, UART_SW_MODE, 0);
> + wrl(port, UART_URX_RTO_TIMER, 0x4f);
FIELD_PREP(UART_CR_URX_RTO_VALUE_MSK, 0x4f)? It would document what field
is written explicitly.
> +
> + val = rdl(port, UART_FIFO_CONFIG_1);
> + val &= ~UART_RX_FIFO_TH_MSK;
> + val |= BFLB_UART_RX_FIFO_TH << UART_RX_FIFO_TH_SFT;
> + wrl(port, UART_FIFO_CONFIG_1, val);
> +
> + /* Unmask RX interrupts now */
> + val = rdl(port, UART_INT_MASK);
> + val &= ~UART_URX_FIFO_INT;
> + val &= ~UART_URX_RTO_INT;
> + val &= ~UART_URX_FER_INT;
Combine to single line.
> +static int bflb_uart_request_port(struct uart_port *port)
> +{
> + /* UARTs always present */
> + return 0;
> +}
> +static void bflb_uart_release_port(struct uart_port *port)
> +{
> + /* Nothing to release... */
> +}
Both release_port and request_port are NULL checked by the caller, there's
no need to provide and empty one.
> +static const struct uart_ops bflb_uart_ops = {
> + .tx_empty = bflb_uart_tx_empty,
> + .get_mctrl = bflb_uart_get_mctrl,
> + .set_mctrl = bflb_uart_set_mctrl,
> + .start_tx = bflb_uart_start_tx,
> + .stop_tx = bflb_uart_stop_tx,
> + .stop_rx = bflb_uart_stop_rx,
> + .break_ctl = bflb_uart_break_ctl,
> + .startup = bflb_uart_startup,
> + .shutdown = bflb_uart_shutdown,
> + .set_termios = bflb_uart_set_termios,
> + .type = bflb_uart_type,
> + .request_port = bflb_uart_request_port,
> + .release_port = bflb_uart_release_port,
> + .config_port = bflb_uart_config_port,
> + .verify_port = bflb_uart_verify_port,
> +};
> +static void bflb_uart_console_write(struct console *co, const char *s,
> + u_int count)
> +{
> + struct uart_port *port = &bflb_uart_ports[co->index]->port;
> + u32 status, reg, mask;
> +
> + /* save then disable interrupts */
> + mask = rdl(port, UART_INT_MASK);
> + reg = -1;
Use ~0 instead. Why -1 here and 0xfff in the other place?
--
i.
More information about the linux-riscv
mailing list