diff options
Diffstat (limited to 'drivers/tty/serial')
45 files changed, 1454 insertions, 689 deletions
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 33ad9d6de532..52bb21205bb6 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Driver for 8250/16550-type serial ports * @@ -156,7 +156,9 @@ void serial8250_rpm_put(struct uart_8250_port *p); void serial8250_rpm_get_tx(struct uart_8250_port *p); void serial8250_rpm_put_tx(struct uart_8250_port *p); -int serial8250_em485_init(struct uart_8250_port *p); +int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485); +void serial8250_em485_start_tx(struct uart_8250_port *p); +void serial8250_em485_stop_tx(struct uart_8250_port *p); void serial8250_em485_destroy(struct uart_8250_port *p); /* MCR <-> TIOCM conversion */ diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index e70e3cc30050..12d03e678295 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -6,6 +6,10 @@ * * Based on 8250_lpc18xx.c: * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> + * + * The bcm2835aux is capable of RTS auto flow-control, but this driver doesn't + * take advantage of it yet. When adding support, be sure not to enable it + * simultaneously to rs485. */ #include <linux/clk.h> @@ -16,16 +20,64 @@ #include "8250.h" +#define BCM2835_AUX_UART_CNTL 8 +#define BCM2835_AUX_UART_CNTL_RXEN 0x01 /* Receiver enable */ +#define BCM2835_AUX_UART_CNTL_TXEN 0x02 /* Transmitter enable */ +#define BCM2835_AUX_UART_CNTL_AUTORTS 0x04 /* RTS set by RX fill level */ +#define BCM2835_AUX_UART_CNTL_AUTOCTS 0x08 /* CTS stops transmitter */ +#define BCM2835_AUX_UART_CNTL_RTS3 0x00 /* RTS set until 3 chars left */ +#define BCM2835_AUX_UART_CNTL_RTS2 0x10 /* RTS set until 2 chars left */ +#define BCM2835_AUX_UART_CNTL_RTS1 0x20 /* RTS set until 1 chars left */ +#define BCM2835_AUX_UART_CNTL_RTS4 0x30 /* RTS set until 4 chars left */ +#define BCM2835_AUX_UART_CNTL_RTSINV 0x40 /* Invert auto RTS polarity */ +#define BCM2835_AUX_UART_CNTL_CTSINV 0x80 /* Invert auto CTS polarity */ + /** * struct bcm2835aux_data - driver private data of BCM2835 auxiliary UART * @clk: clock producer of the port's uartclk * @line: index of the port's serial8250_ports[] entry + * @cntl: cached copy of CNTL register */ struct bcm2835aux_data { struct clk *clk; int line; + u32 cntl; }; +static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up) +{ + if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) { + struct bcm2835aux_data *data = dev_get_drvdata(up->port.dev); + + data->cntl &= ~BCM2835_AUX_UART_CNTL_RXEN; + serial_out(up, BCM2835_AUX_UART_CNTL, data->cntl); + } + + /* + * On the bcm2835aux, the MCR register contains no other + * flags besides RTS. So no need for a read-modify-write. + */ + if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) + serial8250_out_MCR(up, 0); + else + serial8250_out_MCR(up, UART_MCR_RTS); +} + +static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up) +{ + if (up->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) + serial8250_out_MCR(up, 0); + else + serial8250_out_MCR(up, UART_MCR_RTS); + + if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) { + struct bcm2835aux_data *data = dev_get_drvdata(up->port.dev); + + data->cntl |= BCM2835_AUX_UART_CNTL_RXEN; + serial_out(up, BCM2835_AUX_UART_CNTL, data->cntl); + } +} + static int bcm2835aux_serial_probe(struct platform_device *pdev) { struct uart_8250_port up = { }; @@ -47,6 +99,14 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) up.port.fifosize = 8; up.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST | UPF_IOREMAP; + up.port.rs485_config = serial8250_em485_config; + up.rs485_start_tx = bcm2835aux_rs485_start_tx; + up.rs485_stop_tx = bcm2835aux_rs485_stop_tx; + + /* initialize cached copy with power-on reset value */ + data->cntl = BCM2835_AUX_UART_CNTL_RXEN | BCM2835_AUX_UART_CNTL_TXEN; + + platform_set_drvdata(pdev, data); /* get the clock - this also enables the HW */ data->clk = devm_clk_get(&pdev->dev, NULL); @@ -102,8 +162,6 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) } data->line = ret; - platform_set_drvdata(pdev, data); - return 0; dis_clk: @@ -137,6 +195,24 @@ static struct platform_driver bcm2835aux_serial_driver = { }; module_platform_driver(bcm2835aux_serial_driver); +#ifdef CONFIG_SERIAL_8250_CONSOLE + +static int __init early_bcm2835aux_setup(struct earlycon_device *device, + const char *options) +{ + if (!device->port.membase) + return -ENODEV; + + device->port.iotype = UPIO_MEM32; + device->port.regshift = 2; + + return early_serial8250_setup(device, NULL); +} + +OF_EARLYCON_DECLARE(bcm2835aux, "brcm,bcm2835-aux-uart", + early_bcm2835aux_setup); +#endif + MODULE_DESCRIPTION("BCM2835 auxiliar UART driver"); MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index f2a33c9082a6..45d9117cab68 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -608,6 +608,14 @@ static int univ8250_console_setup(struct console *co, char *options) return retval; } +static int univ8250_console_exit(struct console *co) +{ + struct uart_port *port; + + port = &serial8250_ports[co->index].port; + return serial8250_console_exit(port); +} + /** * univ8250_console_match - non-standard console matching * @co: registering console @@ -666,6 +674,7 @@ static struct console univ8250_console = { .write = univ8250_console_write, .device = uart_console_device, .setup = univ8250_console_setup, + .exit = univ8250_console_exit, .match = univ8250_console_match, .flags = CON_PRINTBUFFER | CON_ANYTIME, .index = -1, @@ -1007,14 +1016,18 @@ int serial8250_register_8250_port(struct uart_8250_port *up) uart->port.unthrottle = up->port.unthrottle; uart->port.rs485_config = up->port.rs485_config; uart->port.rs485 = up->port.rs485; + uart->rs485_start_tx = up->rs485_start_tx; + uart->rs485_stop_tx = up->rs485_stop_tx; uart->dma = up->dma; /* Take tx_loadsz from fifosize if it wasn't set separately */ if (uart->port.fifosize && !uart->tx_loadsz) uart->tx_loadsz = uart->port.fifosize; - if (up->port.dev) + if (up->port.dev) { uart->port.dev = up->port.dev; + uart_get_rs485_mode(uart->port.dev, &uart->port.rs485); + } if (up->port.flags & UPF_FIXED_TYPE) uart->port.type = up->port.type; diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h index 87a4db2a8aba..9a12953832d3 100644 --- a/drivers/tty/serial/8250/8250_dwlib.h +++ b/drivers/tty/serial/8250/8250_dwlib.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* Synopsys DesignWare 8250 library header file. */ #include <linux/types.h> diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index d330da76d6b6..59449b6500cd 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -135,7 +135,7 @@ struct exar8250 { unsigned int nr; struct exar8250_board *board; void __iomem *virt; - int line[0]; + int line[]; }; static void exar_pm(struct uart_port *port, unsigned int state, unsigned int old) diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 60eff3240c8a..4dee8a9e0c95 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -156,6 +156,11 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port) return 0; } +static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port) +{ + return 0; +} + #ifdef CONFIG_SERIAL_8250_DMA static const struct dw_dma_platform_data qrk_serial_dma_pdata = { .nr_channels = 2, @@ -356,6 +361,7 @@ static const struct lpss8250_board byt_board = { static const struct lpss8250_board ehl_board = { .freq = 200000000, .base_baud = 12500000, + .setup = ehl_serial_setup, }; static const struct lpss8250_board qrk_board = { diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index 4d067f515f74..f839380c2f4c 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -32,6 +32,7 @@ #define MTK_UART_RXTRI_AD 0x14 /* RX Trigger address */ #define MTK_UART_FRACDIV_L 0x15 /* Fractional divider LSB address */ #define MTK_UART_FRACDIV_M 0x16 /* Fractional divider MSB address */ +#define MTK_UART_DEBUG0 0x18 #define MTK_UART_IER_XOFFI 0x20 /* Enable XOFF character interrupt */ #define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */ #define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */ @@ -388,9 +389,18 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, static int __maybe_unused mtk8250_runtime_suspend(struct device *dev) { struct mtk8250_data *data = dev_get_drvdata(dev); + struct uart_8250_port *up = serial8250_get_port(data->line); - clk_disable_unprepare(data->uart_clk); - clk_disable_unprepare(data->bus_clk); + /* wait until UART in idle status */ + while + (serial_in(up, MTK_UART_DEBUG0)); + + if (data->clk_count == 0U) { + dev_dbg(dev, "%s clock count is 0\n", __func__); + } else { + clk_disable_unprepare(data->bus_clk); + data->clk_count--; + } return 0; } @@ -400,16 +410,16 @@ static int __maybe_unused mtk8250_runtime_resume(struct device *dev) struct mtk8250_data *data = dev_get_drvdata(dev); int err; - err = clk_prepare_enable(data->uart_clk); - if (err) { - dev_warn(dev, "Can't enable clock\n"); - return err; - } - - err = clk_prepare_enable(data->bus_clk); - if (err) { - dev_warn(dev, "Can't enable bus clock\n"); - return err; + if (data->clk_count > 0U) { + dev_dbg(dev, "%s clock count is %d\n", __func__, + data->clk_count); + } else { + err = clk_prepare_enable(data->bus_clk); + if (err) { + dev_warn(dev, "Can't enable bus clock\n"); + return err; + } + data->clk_count++; } return 0; @@ -419,12 +429,14 @@ static void mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) { if (!state) - pm_runtime_get_sync(port->dev); + if (!mtk8250_runtime_resume(port->dev)) + pm_runtime_get_sync(port->dev); serial8250_do_pm(port, state, old); if (state) - pm_runtime_put_sync_suspend(port->dev); + if (!pm_runtime_put_sync_suspend(port->dev)) + mtk8250_runtime_suspend(port->dev); } #ifdef CONFIG_SERIAL_8250_DMA @@ -501,6 +513,8 @@ static int mtk8250_probe(struct platform_device *pdev) if (!data) return -ENOMEM; + data->clk_count = 0; + if (pdev->dev.of_node) { err = mtk8250_probe_of(pdev, &uart.port, data); if (err) @@ -533,6 +547,7 @@ static int mtk8250_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); + pm_runtime_enable(&pdev->dev); err = mtk8250_runtime_resume(&pdev->dev); if (err) return err; @@ -541,9 +556,6 @@ static int mtk8250_probe(struct platform_device *pdev) if (data->line < 0) return data->line; - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); - data->rx_wakeup_irq = platform_get_irq_optional(pdev, 1); return 0; @@ -556,11 +568,13 @@ static int mtk8250_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); serial8250_unregister_port(data->line); - mtk8250_runtime_suspend(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + mtk8250_runtime_suspend(&pdev->dev); + return 0; } diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index f6687756ec5e..65e9045dafe6 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -7,7 +7,6 @@ #include <linux/console.h> #include <linux/module.h> #include <linux/slab.h> -#include <linux/delay.h> #include <linux/serial_core.h> #include <linux/serial_reg.h> #include <linux/of_address.h> @@ -26,67 +25,16 @@ struct of_serial_info { int line; }; -#ifdef CONFIG_ARCH_TEGRA -static void tegra_serial_handle_break(struct uart_port *p) -{ - unsigned int status, tmout = 10000; - - do { - status = p->serial_in(p, UART_LSR); - if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) - status = p->serial_in(p, UART_RX); - else - break; - if (--tmout == 0) - break; - udelay(1); - } while (1); -} -#else -static inline void tegra_serial_handle_break(struct uart_port *port) -{ -} -#endif - -static int of_8250_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - /* Clamp the delays to [0, 100ms] */ - rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); - rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); - - port->rs485 = *rs485; - - /* - * Both serial8250_em485_init and serial8250_em485_destroy - * are idempotent - */ - if (rs485->flags & SER_RS485_ENABLED) { - int ret = serial8250_em485_init(up); - - if (ret) { - rs485->flags &= ~SER_RS485_ENABLED; - port->rs485.flags &= ~SER_RS485_ENABLED; - } - return ret; - } - - serial8250_em485_destroy(up); - - return 0; -} - /* * Fill a struct uart_port for a given device node */ static int of_platform_serial_setup(struct platform_device *ofdev, - int type, struct uart_port *port, + int type, struct uart_8250_port *up, struct of_serial_info *info) { struct resource resource; struct device_node *np = ofdev->dev.of_node; + struct uart_port *port = &up->port; u32 clk, spd, prop; int ret, irq; @@ -207,13 +155,11 @@ static int of_platform_serial_setup(struct platform_device *ofdev, port->flags |= UPF_SKIP_TEST; port->dev = &ofdev->dev; - port->rs485_config = of_8250_rs485_config; + port->rs485_config = serial8250_em485_config; + up->rs485_start_tx = serial8250_em485_start_tx; + up->rs485_stop_tx = serial8250_em485_stop_tx; switch (type) { - case PORT_TEGRA: - port->handle_break = tegra_serial_handle_break; - break; - case PORT_RT2880: port->iotype = UPIO_AU; break; @@ -258,7 +204,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev) return -ENOMEM; memset(&port8250, 0, sizeof(port8250)); - ret = of_platform_serial_setup(ofdev, port_type, &port8250.port, info); + ret = of_platform_serial_setup(ofdev, port_type, &port8250, info); if (ret) goto err_free; @@ -358,7 +304,6 @@ static const struct of_device_id of_platform_serial_table[] = { { .compatible = "ns16550", .data = (void *)PORT_16550, }, { .compatible = "ns16750", .data = (void *)PORT_16750, }, { .compatible = "ns16850", .data = (void *)PORT_16850, }, - { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, }, { .compatible = "ralink,rt2880-uart", .data = (void *)PORT_RT2880, }, { .compatible = "intel,xscale-uart", .data = (void *)PORT_XSCALE, }, diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 76fe72bfb8bb..16cfb887c5a3 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -40,6 +40,7 @@ * The same errata is applicable to AM335x and DRA7x processors too. */ #define UART_ERRATA_CLOCK_DISABLE (1 << 3) +#define UART_HAS_EFR2 BIT(4) #define OMAP_UART_FCR_RX_TRIG 6 #define OMAP_UART_FCR_TX_TRIG 4 @@ -93,6 +94,10 @@ #define OMAP_UART_REV_52 0x0502 #define OMAP_UART_REV_63 0x0603 +/* Enhanced features register 2 */ +#define UART_OMAP_EFR2 0x23 +#define UART_OMAP_EFR2_TIMEOUT_BEHAVE BIT(6) + struct omap8250_priv { int line; u8 habit; @@ -105,6 +110,8 @@ struct omap8250_priv { u8 delayed_restore; u16 quot; + u8 tx_trigger; + u8 rx_trigger; bool is_suspending; int wakeirq; int wakeups_enabled; @@ -118,6 +125,17 @@ struct omap8250_priv { bool throttled; }; +struct omap8250_dma_params { + u32 rx_size; + u8 rx_trigger; + u8 tx_trigger; +}; + +struct omap8250_platdata { + struct omap8250_dma_params *dma_params; + u8 habit; +}; + #ifdef CONFIG_SERIAL_8250_DMA static void omap_8250_rx_dma_flush(struct uart_8250_port *p); #else @@ -295,8 +313,8 @@ static void omap8250_restore_regs(struct uart_8250_port *up) serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_RESTORE(16) | OMAP_UART_TCR_HALT(52)); serial_out(up, UART_TI752_TLR, - TRIGGER_TLR_MASK(TX_TRIGGER) << UART_TI752_TLR_TX | - TRIGGER_TLR_MASK(RX_TRIGGER) << UART_TI752_TLR_RX); + TRIGGER_TLR_MASK(priv->tx_trigger) << UART_TI752_TLR_TX | + TRIGGER_TLR_MASK(priv->rx_trigger) << UART_TI752_TLR_RX); serial_out(up, UART_LCR, 0); @@ -435,8 +453,8 @@ static void omap_8250_set_termios(struct uart_port *port, * This is because threshold and trigger values are the same. */ up->fcr = UART_FCR_ENABLE_FIFO; - up->fcr |= TRIGGER_FCR_MASK(TX_TRIGGER) << OMAP_UART_FCR_TX_TRIG; - up->fcr |= TRIGGER_FCR_MASK(RX_TRIGGER) << OMAP_UART_FCR_RX_TRIG; + up->fcr |= TRIGGER_FCR_MASK(priv->tx_trigger) << OMAP_UART_FCR_TX_TRIG; + up->fcr |= TRIGGER_FCR_MASK(priv->rx_trigger) << OMAP_UART_FCR_RX_TRIG; priv->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY | OMAP_UART_SCR_TX_TRIG_GRANU1_MASK; @@ -651,7 +669,7 @@ static int omap_8250_startup(struct uart_port *port) priv->wer |= OMAP_UART_TX_WAKEUP_EN; serial_out(up, UART_OMAP_WER, priv->wer); - if (up->dma) + if (up->dma && !(priv->habit & UART_HAS_EFR2)) up->dma->rx_dma(up); pm_runtime_mark_last_busy(port->dev); @@ -676,6 +694,8 @@ static void omap_8250_shutdown(struct uart_port *port) pm_runtime_get_sync(port->dev); serial_out(up, UART_OMAP_WER, 0); + if (priv->habit & UART_HAS_EFR2) + serial_out(up, UART_OMAP_EFR2, 0x0); up->ier = 0; serial_out(up, UART_IER, 0); @@ -699,14 +719,12 @@ static void omap_8250_shutdown(struct uart_port *port) static void omap_8250_throttle(struct uart_port *port) { struct omap8250_priv *priv = port->private_data; - struct uart_8250_port *up = up_to_u8250p(port); unsigned long flags; pm_runtime_get_sync(port->dev); spin_lock_irqsave(&port->lock, flags); - up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); - serial_out(up, UART_IER, up->ier); + port->ops->stop_rx(port); priv->throttled = true; spin_unlock_irqrestore(&port->lock, flags); @@ -714,36 +732,6 @@ static void omap_8250_throttle(struct uart_port *port) pm_runtime_put_autosuspend(port->dev); } -static int omap_8250_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - /* Clamp the delays to [0, 100ms] */ - rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); - rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); - - port->rs485 = *rs485; - - /* - * Both serial8250_em485_init and serial8250_em485_destroy - * are idempotent - */ - if (rs485->flags & SER_RS485_ENABLED) { - int ret = serial8250_em485_init(up); - - if (ret) { - rs485->flags &= ~SER_RS485_ENABLED; - port->rs485.flags &= ~SER_RS485_ENABLED; - } - return ret; - } - - serial8250_em485_destroy(up); - - return 0; -} - static void omap_8250_unthrottle(struct uart_port *port) { struct omap8250_priv *priv = port->private_data; @@ -757,6 +745,7 @@ static void omap_8250_unthrottle(struct uart_port *port) if (up->dma) up->dma->rx_dma(up); up->ier |= UART_IER_RLSI | UART_IER_RDI; + port->read_status_mask |= UART_LSR_DR; serial_out(up, UART_IER, up->ier); spin_unlock_irqrestore(&port->lock, flags); @@ -767,32 +756,50 @@ static void omap_8250_unthrottle(struct uart_port *port) #ifdef CONFIG_SERIAL_8250_DMA static int omap_8250_rx_dma(struct uart_8250_port *p); +/* Must be called while priv->rx_dma_lock is held */ static void __dma_rx_do_complete(struct uart_8250_port *p) { - struct omap8250_priv *priv = p->port.private_data; struct uart_8250_dma *dma = p->dma; struct tty_port *tty_port = &p->port.state->port; + struct dma_chan *rxchan = dma->rxchan; + dma_cookie_t cookie; struct dma_tx_state state; int count; - unsigned long flags; int ret; - spin_lock_irqsave(&priv->rx_dma_lock, flags); - if (!dma->rx_running) - goto unlock; + goto out; + cookie = dma->rx_cookie; dma->rx_running = 0; - dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); + dmaengine_tx_status(rxchan, cookie, &state); + + count = dma->rx_size - state.residue + state.in_flight_bytes; + if (count < dma->rx_size) { + dmaengine_terminate_async(rxchan); + + /* + * Poll for teardown to complete which guarantees in + * flight data is drained. + */ + if (state.in_flight_bytes) { + int poll_count = 25; - count = dma->rx_size - state.residue; + while (dmaengine_tx_status(rxchan, cookie, NULL) && + poll_count--) + cpu_relax(); + if (!poll_count) + dev_err(p->port.dev, "teardown incomplete\n"); + } + } + if (!count) + goto out; ret = tty_insert_flip_string(tty_port, dma->rx_buf, count); p->port.icount.rx += ret; p->port.icount.buf_overrun += count - ret; -unlock: - spin_unlock_irqrestore(&priv->rx_dma_lock, flags); +out: tty_flip_buffer_push(tty_port); } @@ -818,8 +825,12 @@ static void __dma_rx_complete(void *param) return; } __dma_rx_do_complete(p); - if (!priv->throttled) - omap_8250_rx_dma(p); + if (!priv->throttled) { + p->ier |= UART_IER_RLSI | UART_IER_RDI; + serial_out(p, UART_IER, p->ier); + if (!(priv->habit & UART_HAS_EFR2)) + omap_8250_rx_dma(p); + } spin_unlock_irqrestore(&p->port.lock, flags); } @@ -845,10 +856,8 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p) if (WARN_ON_ONCE(ret)) priv->rx_dma_broken = true; } - spin_unlock_irqrestore(&priv->rx_dma_lock, flags); - __dma_rx_do_complete(p); - dmaengine_terminate_all(dma->rxchan); + spin_unlock_irqrestore(&priv->rx_dma_lock, flags); } static int omap_8250_rx_dma(struct uart_8250_port *p) @@ -864,8 +873,20 @@ static int omap_8250_rx_dma(struct uart_8250_port *p) spin_lock_irqsave(&priv->rx_dma_lock, flags); - if (dma->rx_running) + if (dma->rx_running) { + enum dma_status state; + + state = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, NULL); + if (state == DMA_COMPLETE) { + /* + * Disable RX interrupts to allow RX DMA completion + * callback to run. + */ + p->ier &= ~(UART_IER_RLSI | UART_IER_RDI); + serial_out(p, UART_IER, p->ier); + } goto out; + } desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM, @@ -1036,6 +1057,46 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) return omap_8250_rx_dma(up); } +static unsigned char omap_8250_handle_rx_dma(struct uart_8250_port *up, + u8 iir, unsigned char status) +{ + if ((status & (UART_LSR_DR | UART_LSR_BI)) && + (iir & UART_IIR_RDI)) { + if (handle_rx_dma(up, iir)) { + status = serial8250_rx_chars(up, status); + omap_8250_rx_dma(up); + } + } + + return status; +} + +static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, + unsigned char status) +{ + /* + * Queue a new transfer if FIFO has data. + */ + if ((status & (UART_LSR_DR | UART_LSR_BI)) && + (up->ier & UART_IER_RDI)) { + omap_8250_rx_dma(up); + serial_out(up, UART_OMAP_EFR2, UART_OMAP_EFR2_TIMEOUT_BEHAVE); + } else if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) { + /* + * Disable RX timeout, read IIR to clear + * current timeout condition, clear EFR2 to + * periodic timeouts, re-enable interrupts. + */ + up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); + serial_out(up, UART_IER, up->ier); + omap_8250_rx_dma_flush(up); + serial_in(up, UART_IIR); + serial_out(up, UART_OMAP_EFR2, 0x0); + up->ier |= UART_IER_RLSI | UART_IER_RDI; + serial_out(up, UART_IER, up->ier); + } +} + /* * This is mostly serial8250_handle_irq(). We have a slightly different DMA * hoook for RX/TX and need different logic for them in the ISR. Therefore we @@ -1044,6 +1105,7 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) static int omap_8250_dma_handle_irq(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); + struct omap8250_priv *priv = up->port.private_data; unsigned char status; unsigned long flags; u8 iir; @@ -1053,19 +1115,18 @@ static int omap_8250_dma_handle_irq(struct uart_port *port) iir = serial_port_in(port, UART_IIR); if (iir & UART_IIR_NO_INT) { serial8250_rpm_put(up); - return 0; + return IRQ_HANDLED; } spin_lock_irqsave(&port->lock, flags); status = serial_port_in(port, UART_LSR); - if (status & (UART_LSR_DR | UART_LSR_BI)) { - if (handle_rx_dma(up, iir)) { - status = serial8250_rx_chars(up, status); - omap_8250_rx_dma(up); - } - } + if (priv->habit & UART_HAS_EFR2) + am654_8250_handle_rx_dma(up, iir, status); + else + status = omap_8250_handle_rx_dma(up, iir, status); + serial8250_modem_status(up); if (status & UART_LSR_THRE && up->dma->tx_err) { if (uart_tx_stopped(&up->port) || @@ -1107,18 +1168,41 @@ static int omap8250_no_handle_irq(struct uart_port *port) return 0; } -static const u8 omap4_habit = UART_ERRATA_CLOCK_DISABLE; -static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE; -static const u8 dra742_habit = UART_ERRATA_CLOCK_DISABLE; +static struct omap8250_dma_params am654_dma = { + .rx_size = SZ_2K, + .rx_trigger = 1, + .tx_trigger = TX_TRIGGER, +}; + +static struct omap8250_dma_params am33xx_dma = { + .rx_size = RX_TRIGGER, + .rx_trigger = RX_TRIGGER, + .tx_trigger = TX_TRIGGER, +}; + +static struct omap8250_platdata am654_platdata = { + .dma_params = &am654_dma, + .habit = UART_HAS_EFR2, +}; + +static struct omap8250_platdata am33xx_platdata = { + .dma_params = &am33xx_dma, + .habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE, +}; + +static struct omap8250_platdata omap4_platdata = { + .dma_params = &am33xx_dma, + .habit = UART_ERRATA_CLOCK_DISABLE, +}; static const struct of_device_id omap8250_dt_ids[] = { - { .compatible = "ti,am654-uart" }, + { .compatible = "ti,am654-uart", .data = &am654_platdata, }, { .compatible = "ti,omap2-uart" }, { .compatible = "ti,omap3-uart" }, - { .compatible = "ti,omap4-uart", .data = &omap4_habit, }, - { .compatible = "ti,am3352-uart", .data = &am3352_habit, }, - { .compatible = "ti,am4372-uart", .data = &am3352_habit, }, - { .compatible = "ti,dra742-uart", .data = &dra742_habit, }, + { .compatible = "ti,omap4-uart", .data = &omap4_platdata, }, + { .compatible = "ti,am3352-uart", .data = &am33xx_platdata, }, + { .compatible = "ti,am4372-uart", .data = &am33xx_platdata, }, + { .compatible = "ti,dra742-uart", .data = &omap4_platdata, }, {}, }; MODULE_DEVICE_TABLE(of, omap8250_dt_ids); @@ -1129,10 +1213,10 @@ static int omap8250_probe(struct platform_device *pdev) struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct device_node *np = pdev->dev.of_node; struct omap8250_priv *priv; + const struct omap8250_platdata *pdata; struct uart_8250_port up; int ret; void __iomem *membase; - const struct of_device_id *id; if (!regs || !irq) { dev_err(&pdev->dev, "missing registers or irq\n"); @@ -1187,7 +1271,9 @@ static int omap8250_probe(struct platform_device *pdev) up.port.shutdown = omap_8250_shutdown; up.port.throttle = omap_8250_throttle; up.port.unthrottle = omap_8250_unthrottle; - up.port.rs485_config = omap_8250_rs485_config; + up.port.rs485_config = serial8250_em485_config; + up.rs485_start_tx = serial8250_em485_start_tx; + up.rs485_stop_tx = serial8250_em485_stop_tx; up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); ret = of_alias_get_id(np, "serial"); @@ -1211,9 +1297,9 @@ static int omap8250_probe(struct platform_device *pdev) priv->wakeirq = irq_of_parse_and_map(np, 1); - id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev); - if (id && id->data) - priv->habit |= *(u8 *)id->data; + pdata = of_device_get_match_data(&pdev->dev); + if (pdata) + priv->habit |= pdata->habit; if (!up.port.uartclk) { up.port.uartclk = DEFAULT_CLK_SPEED; @@ -1230,6 +1316,7 @@ static int omap8250_probe(struct platform_device *pdev) spin_lock_init(&priv->rx_dma_lock); device_init_wakeup(&pdev->dev, true); + pm_runtime_enable(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev); /* @@ -1243,12 +1330,13 @@ static int omap8250_probe(struct platform_device *pdev) pm_runtime_set_autosuspend_delay(&pdev->dev, -1); pm_runtime_irq_safe(&pdev->dev); - pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); omap_serial_fill_features_erratas(&up, priv); up.port.handle_irq = omap8250_no_handle_irq; + priv->rx_trigger = RX_TRIGGER; + priv->tx_trigger = TX_TRIGGER; #ifdef CONFIG_SERIAL_8250_DMA /* * Oh DMA support. If there are no DMA properties in the DT then @@ -1260,13 +1348,26 @@ static int omap8250_probe(struct platform_device *pdev) */ ret = of_property_count_strings(np, "dma-names"); if (ret == 2) { + struct omap8250_dma_params *dma_params = NULL; + up.dma = &priv->omap8250_dma; - priv->omap8250_dma.fn = the_no_dma_filter_fn; - priv->omap8250_dma.tx_dma = omap_8250_tx_dma; - priv->omap8250_dma.rx_dma = omap_8250_rx_dma; - priv->omap8250_dma.rx_size = RX_TRIGGER; - priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER; - priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER; + up.dma->fn = the_no_dma_filter_fn; + up.dma->tx_dma = omap_8250_tx_dma; + up.dma->rx_dma = omap_8250_rx_dma; + if (pdata) + dma_params = pdata->dma_params; + + if (dma_params) { + up.dma->rx_size = dma_params->rx_size; + up.dma->rxconf.src_maxburst = dma_params->rx_trigger; + up.dma->txconf.dst_maxburst = dma_params->tx_trigger; + priv->rx_trigger = dma_params->rx_trigger; + priv->tx_trigger = dma_params->tx_trigger; + } else { + up.dma->rx_size = RX_TRIGGER; + up.dma->rxconf.src_maxburst = RX_TRIGGER; + up.dma->txconf.dst_maxburst = TX_TRIGGER; + } } #endif ret = serial8250_register_8250_port(&up); @@ -1464,7 +1565,7 @@ static int omap8250_runtime_resume(struct device *dev) if (omap8250_lost_context(up)) omap8250_restore_regs(up); - if (up->dma && up->dma->rxchan) + if (up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2)) omap_8250_rx_dma(up); priv->latency = priv->calc_latency; diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 939685fed396..0804469ff052 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -53,7 +53,7 @@ struct serial_private { unsigned int nr; struct pci_serial_quirk *quirk; const struct pciserial_board *board; - int line[0]; + int line[]; }; static const struct pci_device_id pci_use_msi[] = { diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 0325f2e53b74..f77bf820b7a3 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -557,17 +557,6 @@ static void serial8250_clear_fifos(struct uart_8250_port *p) } } -static inline void serial8250_em485_rts_after_send(struct uart_8250_port *p) -{ - unsigned char mcr = serial8250_in_MCR(p); - - if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) - mcr |= UART_MCR_RTS; - else - mcr &= ~UART_MCR_RTS; - serial8250_out_MCR(p, mcr); -} - static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t); static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t); @@ -615,7 +604,7 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put); * * Return 0 - success, -errno - otherwise */ -int serial8250_em485_init(struct uart_8250_port *p) +static int serial8250_em485_init(struct uart_8250_port *p) { if (p->em485) return 0; @@ -632,11 +621,12 @@ int serial8250_em485_init(struct uart_8250_port *p) p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx; p->em485->port = p; p->em485->active_timer = NULL; - serial8250_em485_rts_after_send(p); + p->em485->tx_stopped = true; + + p->rs485_stop_tx(p); return 0; } -EXPORT_SYMBOL_GPL(serial8250_em485_init); /** * serial8250_em485_destroy() - put uart_8250_port into normal state @@ -664,6 +654,52 @@ void serial8250_em485_destroy(struct uart_8250_port *p) } EXPORT_SYMBOL_GPL(serial8250_em485_destroy); +/** + * serial8250_em485_config() - generic ->rs485_config() callback + * @port: uart port + * @rs485: rs485 settings + * + * Generic callback usable by 8250 uart drivers to activate rs485 settings + * if the uart is incapable of driving RTS as a Transmit Enable signal in + * hardware, relying on software emulation instead. + */ +int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* pick sane settings if the user hasn't */ + if (!!(rs485->flags & SER_RS485_RTS_ON_SEND) == + !!(rs485->flags & SER_RS485_RTS_AFTER_SEND)) { + rs485->flags |= SER_RS485_RTS_ON_SEND; + rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; + } + + /* clamp the delays to [0, 100ms] */ + rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); + rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); + + memset(rs485->padding, 0, sizeof(rs485->padding)); + port->rs485 = *rs485; + + /* + * Both serial8250_em485_init() and serial8250_em485_destroy() + * are idempotent. + */ + if (rs485->flags & SER_RS485_ENABLED) { + int ret = serial8250_em485_init(up); + + if (ret) { + rs485->flags &= ~SER_RS485_ENABLED; + port->rs485.flags &= ~SER_RS485_ENABLED; + } + return ret; + } + + serial8250_em485_destroy(up); + return 0; +} +EXPORT_SYMBOL_GPL(serial8250_em485_config); + /* * These two wrappers ensure that enable_runtime_pm_tx() can be called more than * once and disable_runtime_pm_tx() will still disable RPM because the fifo is @@ -1318,8 +1354,8 @@ out_lock: fintek_8250_probe(up); if (up->capabilities != old_capabilities) { - pr_warn("%s: detected caps %08x should be %08x\n", - port->name, old_capabilities, up->capabilities); + dev_warn(port->dev, "detected caps %08x should be %08x\n", + old_capabilities, up->capabilities); } out: DEBUG_AUTOCONF("iir=%d ", scratch); @@ -1394,9 +1430,21 @@ static void serial8250_stop_rx(struct uart_port *port) serial8250_rpm_put(up); } -static void __do_stop_tx_rs485(struct uart_8250_port *p) +/** + * serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback + * @up: uart 8250 port + * + * Generic callback usable by 8250 uart drivers to stop rs485 transmission. + */ +void serial8250_em485_stop_tx(struct uart_8250_port *p) { - serial8250_em485_rts_after_send(p); + unsigned char mcr = serial8250_in_MCR(p); + + if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) + mcr |= UART_MCR_RTS; + else + mcr &= ~UART_MCR_RTS; + serial8250_out_MCR(p, mcr); /* * Empty the RX FIFO, we are not interested in anything @@ -1410,6 +1458,8 @@ static void __do_stop_tx_rs485(struct uart_8250_port *p) serial_port_out(&p->port, UART_IER, p->ier); } } +EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx); + static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t) { struct uart_8250_em485 *em485; @@ -1422,8 +1472,9 @@ static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t) serial8250_rpm_get(p); spin_lock_irqsave(&p->port.lock, flags); if (em485->active_timer == &em485->stop_tx_timer) { - __do_stop_tx_rs485(p); + p->rs485_stop_tx(p); em485->active_timer = NULL; + em485->tx_stopped = true; } spin_unlock_irqrestore(&p->port.lock, flags); serial8250_rpm_put(p); @@ -1444,7 +1495,7 @@ static void __stop_tx_rs485(struct uart_8250_port *p) struct uart_8250_em485 *em485 = p->em485; /* - * __do_stop_tx_rs485 is going to set RTS according to config + * rs485_stop_tx() is going to set RTS according to config * AND flush RX FIFO if required. */ if (p->port.rs485.delay_rts_after_send > 0) { @@ -1452,7 +1503,9 @@ static void __stop_tx_rs485(struct uart_8250_port *p) start_hrtimer_ms(&em485->stop_tx_timer, p->port.rs485.delay_rts_after_send); } else { - __do_stop_tx_rs485(p); + p->rs485_stop_tx(p); + em485->active_timer = NULL; + em485->tx_stopped = true; } } @@ -1477,8 +1530,6 @@ static inline void __stop_tx(struct uart_8250_port *p) if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) return; - em485->active_timer = NULL; - __stop_tx_rs485(p); } __do_stop_tx(p); @@ -1528,25 +1579,42 @@ static inline void __start_tx(struct uart_port *port) } } -static inline void start_tx_rs485(struct uart_port *port) +/** + * serial8250_em485_start_tx() - generic ->rs485_start_tx() callback + * @up: uart 8250 port + * + * Generic callback usable by 8250 uart drivers to start rs485 transmission. + * Assumes that setting the RTS bit in the MCR register means RTS is high. + * (Some chips use inverse semantics.) Further assumes that reception is + * stoppable by disabling the UART_IER_RDI interrupt. (Some chips set the + * UART_LSR_DR bit even when UART_IER_RDI is disabled, foiling this approach.) + */ +void serial8250_em485_start_tx(struct uart_8250_port *up) { - struct uart_8250_port *up = up_to_u8250p(port); - struct uart_8250_em485 *em485 = up->em485; - unsigned char mcr; + unsigned char mcr = serial8250_in_MCR(up); if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) serial8250_stop_rx(&up->port); + if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) + mcr |= UART_MCR_RTS; + else + mcr &= ~UART_MCR_RTS; + serial8250_out_MCR(up, mcr); +} +EXPORT_SYMBOL_GPL(serial8250_em485_start_tx); + +static inline void start_tx_rs485(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + struct uart_8250_em485 *em485 = up->em485; + em485->active_timer = NULL; - mcr = serial8250_in_MCR(up); - if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) != - !!(mcr & UART_MCR_RTS)) { - if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) - mcr |= UART_MCR_RTS; - else - mcr &= ~UART_MCR_RTS; - serial8250_out_MCR(up, mcr); + if (em485->tx_stopped) { + em485->tx_stopped = false; + + up->rs485_start_tx(up); if (up->port.rs485.delay_rts_before_send > 0) { em485->active_timer = &em485->start_tx_timer; @@ -1683,7 +1751,7 @@ void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) lsr &= port->read_status_mask; if (lsr & UART_LSR_BI) { - pr_debug("%s: handling break\n", __func__); + dev_dbg(port->dev, "handling break\n"); flag = TTY_BREAK; } else if (lsr & UART_LSR_PE) flag = TTY_PARITY; @@ -1815,6 +1883,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) unsigned char status; unsigned long flags; struct uart_8250_port *up = up_to_u8250p(port); + bool skip_rx = false; if (iir & UART_IIR_NO_INT) return 0; @@ -1823,7 +1892,20 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) status = serial_port_in(port, UART_LSR); - if (status & (UART_LSR_DR | UART_LSR_BI)) { + /* + * If port is stopped and there are no error conditions in the + * FIFO, then don't drain the FIFO, as this may lead to TTY buffer + * overflow. Not servicing, RX FIFO would trigger auto HW flow + * control when FIFO occupancy reaches preset threshold, thus + * halting RX. This only works when auto HW flow control is + * available. + */ + if (!(status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) && + (port->status & (UPSTAT_AUTOCTS | UPSTAT_AUTORTS)) && + !(port->read_status_mask & UART_LSR_DR)) + skip_rx = true; + + if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) { if (!up->dma || handle_rx_dma(up, iir)) status = serial8250_rx_chars(up, status); } @@ -1924,6 +2006,13 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl) struct uart_8250_port *up = up_to_u8250p(port); unsigned char mcr; + if (port->rs485.flags & SER_RS485_ENABLED) { + if (serial8250_in_MCR(up) & UART_MCR_RTS) + mctrl |= TIOCM_RTS; + else + mctrl &= ~TIOCM_RTS; + } + mcr = serial8250_TIOCM_to_MCR(mctrl); mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; @@ -2134,7 +2223,7 @@ int serial8250_do_startup(struct uart_port *port) */ if (!(port->flags & UPF_BUGGY_UART) && (serial_port_in(port, UART_LSR) == 0xff)) { - pr_info_ratelimited("%s: LSR safety check engaged!\n", port->name); + dev_info_ratelimited(port->dev, "LSR safety check engaged!\n"); retval = -ENODEV; goto out; } @@ -2166,8 +2255,7 @@ int serial8250_do_startup(struct uart_port *port) (port->type == PORT_ALTR_16550_F128)) && (port->fifosize > 1)) { /* Bounds checking of TX threshold (valid 0 to fifosize-2) */ if ((up->tx_loadsz < 2) || (up->tx_loadsz > port->fifosize)) { - pr_err("%s TX FIFO Threshold errors, skipping\n", - port->name); + dev_err(port->dev, "TX FIFO Threshold errors, skipping\n"); } else { serial_port_out(port, UART_ALTR_AFR, UART_ALTR_EN_TXFIFO_LW); @@ -2268,8 +2356,7 @@ int serial8250_do_startup(struct uart_port *port) if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { if (!(up->bugs & UART_BUG_TXEN)) { up->bugs |= UART_BUG_TXEN; - pr_debug("%s - enabling bad tx status workarounds\n", - port->name); + dev_dbg(port->dev, "enabling bad tx status workarounds\n"); } } else { up->bugs &= ~UART_BUG_TXEN; @@ -2294,10 +2381,14 @@ dont_test_tx_en: * Request DMA channels for both RX and TX. */ if (up->dma) { - retval = serial8250_request_dma(up); - if (retval) { - pr_warn_ratelimited("%s - failed to request DMA\n", - port->name); + const char *msg = NULL; + + if (uart_console(port)) + msg = "forbid DMA for kernel console"; + else if (serial8250_request_dma(up)) + msg = "failed to request DMA"; + if (msg) { + dev_warn_ratelimited(port->dev, "%s\n", msg); up->dma = NULL; } } @@ -2880,7 +2971,7 @@ static int do_serial8250_get_rxtrig(struct tty_port *port) return rxtrig_bytes; } -static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev, +static ssize_t rx_trig_bytes_show(struct device *dev, struct device_attribute *attr, char *buf) { struct tty_port *port = dev_get_drvdata(dev); @@ -2926,7 +3017,7 @@ static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes) return ret; } -static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev, +static ssize_t rx_trig_bytes_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct tty_port *port = dev_get_drvdata(dev); @@ -2947,18 +3038,16 @@ static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev, return count; } -static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP, - serial8250_get_attr_rx_trig_bytes, - serial8250_set_attr_rx_trig_bytes); +static DEVICE_ATTR_RW(rx_trig_bytes); static struct attribute *serial8250_dev_attrs[] = { &dev_attr_rx_trig_bytes.attr, - NULL, - }; + NULL +}; static struct attribute_group serial8250_dev_attr_group = { .attrs = serial8250_dev_attrs, - }; +}; static void register_dev_spec_attr_grp(struct uart_8250_port *up) { @@ -2987,6 +3076,9 @@ static void serial8250_config_port(struct uart_port *port, int flags) if (flags & UART_CONFIG_TYPE) autoconfig(up); + if (port->rs485.flags & SER_RS485_ENABLED) + port->rs485_config(port, &port->rs485); + /* if access method is AU, it is a 16550 with a quirk */ if (port->type == PORT_16550A && port->iotype == UPIO_AU) up->bugs |= UART_BUG_NOMSR; @@ -3127,10 +3219,14 @@ static void serial8250_console_restore(struct uart_8250_port *up) * any possible real use of the port... * * The console_lock must be held when we get here. + * + * Doing runtime PM is really a bad idea for the kernel console. + * Thus, we assume the function is called when device is powered up. */ void serial8250_console_write(struct uart_8250_port *up, const char *s, unsigned int count) { + struct uart_8250_em485 *em485 = up->em485; struct uart_port *port = &up->port; unsigned long flags; unsigned int ier; @@ -3138,8 +3234,6 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, touch_nmi_watchdog(); - serial8250_rpm_get(up); - if (oops_in_progress) locked = spin_trylock_irqsave(&port->lock, flags); else @@ -3161,6 +3255,12 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, up->canary = 0; } + if (em485) { + if (em485->tx_stopped) + up->rs485_start_tx(up); + mdelay(port->rs485.delay_rts_before_send); + } + uart_console_write(port, s, count, serial8250_console_putchar); /* @@ -3168,6 +3268,13 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, * and restore the IER */ wait_for_xmitr(up, BOTH_EMPTY); + + if (em485) { + mdelay(port->rs485.delay_rts_after_send); + if (em485->tx_stopped) + up->rs485_stop_tx(up); + } + serial_port_out(port, UART_IER, ier); /* @@ -3182,7 +3289,6 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, if (locked) spin_unlock_irqrestore(&port->lock, flags); - serial8250_rpm_put(up); } static unsigned int probe_baud(struct uart_port *port) @@ -3206,6 +3312,7 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe) int bits = 8; int parity = 'n'; int flow = 'n'; + int ret; if (!port->iobase && !port->membase) return -ENODEV; @@ -3215,7 +3322,22 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe) else if (probe) baud = probe_baud(port); - return uart_set_options(port, port->cons, baud, parity, bits, flow); + ret = uart_set_options(port, port->cons, baud, parity, bits, flow); + if (ret) + return ret; + + if (port->dev) + pm_runtime_get_sync(port->dev); + + return 0; +} + +int serial8250_console_exit(struct uart_port *port) +{ + if (port->dev) + pm_runtime_put_sync(port->dev); + + return 0; } #endif /* CONFIG_SERIAL_8250_CONSOLE */ diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c index c47188860e32..11612d174716 100644 --- a/drivers/tty/serial/8250/8250_pxa.c +++ b/drivers/tty/serial/8250/8250_pxa.c @@ -123,7 +123,7 @@ static int serial_pxa_probe(struct platform_device *pdev) uart.port.regshift = 2; uart.port.irq = irqres->start; uart.port.fifosize = 64; - uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST; + uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE; uart.port.dev = &pdev->dev; uart.port.uartclk = clk_get_rate(data->clk); uart.port.pm = serial_pxa_pm; diff --git a/drivers/tty/serial/8250/8250_tegra.c b/drivers/tty/serial/8250/8250_tegra.c new file mode 100644 index 000000000000..c0ffad1572c6 --- /dev/null +++ b/drivers/tty/serial/8250/8250_tegra.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Serial Port driver for Tegra devices + * + * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. + */ + +#include <linux/acpi.h> +#include <linux/clk.h> +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/reset.h> +#include <linux/slab.h> + +#include "8250.h" + +struct tegra_uart { + struct clk *clk; + struct reset_control *rst; + int line; +}; + +static void tegra_uart_handle_break(struct uart_port *p) +{ + unsigned int status, tmout = 10000; + + do { + status = p->serial_in(p, UART_LSR); + if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) + status = p->serial_in(p, UART_RX); + else + break; + if (--tmout == 0) + break; + udelay(1); + } while (1); +} + +static int tegra_uart_probe(struct platform_device *pdev) +{ + struct uart_8250_port port8250; + struct tegra_uart *uart; + struct uart_port *port; + struct resource *res; + int ret; + + uart = devm_kzalloc(&pdev->dev, sizeof(*uart), GFP_KERNEL); + if (!uart) + return -ENOMEM; + + memset(&port8250, 0, sizeof(port8250)); + + port = &port8250.port; + spin_lock_init(&port->lock); + + port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | + UPF_FIXED_TYPE; + port->iotype = UPIO_MEM32; + port->regshift = 2; + port->type = PORT_TEGRA; + port->irqflags |= IRQF_SHARED; + port->dev = &pdev->dev; + port->handle_break = tegra_uart_handle_break; + + ret = of_alias_get_id(pdev->dev.of_node, "serial"); + if (ret >= 0) + port->line = ret; + + ret = platform_get_irq(pdev, 0); + if (ret < 0) + return ret; + + port->irq = ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + port->membase = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!port->membase) + return -ENOMEM; + + port->mapbase = res->start; + port->mapsize = resource_size(res); + + uart->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); + if (IS_ERR(uart->rst)) + return PTR_ERR(uart->rst); + + if (device_property_read_u32(&pdev->dev, "clock-frequency", + &port->uartclk)) { + uart->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(uart->clk)) { + dev_err(&pdev->dev, "failed to get clock!\n"); + return -ENODEV; + } + + ret = clk_prepare_enable(uart->clk); + if (ret < 0) + return ret; + + port->uartclk = clk_get_rate(uart->clk); + } + + ret = reset_control_deassert(uart->rst); + if (ret) + goto err_clkdisable; + + ret = serial8250_register_8250_port(&port8250); + if (ret < 0) + goto err_clkdisable; + + platform_set_drvdata(pdev, uart); + uart->line = ret; + + return 0; + +err_clkdisable: + clk_disable_unprepare(uart->clk); + + return ret; +} + +static int tegra_uart_remove(struct platform_device *pdev) +{ + struct tegra_uart *uart = platform_get_drvdata(pdev); + + serial8250_unregister_port(uart->line); + reset_control_assert(uart->rst); + clk_disable_unprepare(uart->clk); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int tegra_uart_suspend(struct device *dev) +{ + struct tegra_uart *uart = dev_get_drvdata(dev); + struct uart_8250_port *port8250 = serial8250_get_port(uart->line); + struct uart_port *port = &port8250->port; + + serial8250_suspend_port(uart->line); + + if (!uart_console(port) || console_suspend_enabled) + clk_disable_unprepare(uart->clk); + + return 0; +} + +static int tegra_uart_resume(struct device *dev) +{ + struct tegra_uart *uart = dev_get_drvdata(dev); + struct uart_8250_port *port8250 = serial8250_get_port(uart->line); + struct uart_port *port = &port8250->port; + + if (!uart_console(port) || console_suspend_enabled) + clk_prepare_enable(uart->clk); + + serial8250_resume_port(uart->line); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(tegra_uart_pm_ops, tegra_uart_suspend, + tegra_uart_resume); + +static const struct of_device_id tegra_uart_of_match[] = { + { .compatible = "nvidia,tegra20-uart", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tegra_uart_of_match); + +static const struct acpi_device_id tegra_uart_acpi_match[] = { + { "NVDA0100", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, tegra_uart_acpi_match); + +static struct platform_driver tegra_uart_driver = { + .driver = { + .name = "tegra-uart", + .pm = &tegra_uart_pm_ops, + .of_match_table = tegra_uart_of_match, + .acpi_match_table = ACPI_PTR(tegra_uart_acpi_match), + }, + .probe = tegra_uart_probe, + .remove = tegra_uart_remove, +}; + +module_platform_driver(tegra_uart_driver); + +MODULE_AUTHOR("Jeff Brasen <jbrasen@nvidia.com>"); +MODULE_DESCRIPTION("NVIDIA Tegra 8250 Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index f16824bbb573..af0688156dd0 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -500,6 +500,15 @@ config SERIAL_8250_PXA applicable to both devicetree and legacy boards, and early console is part of its support. +config SERIAL_8250_TEGRA + tristate "8250 support for Tegra serial ports" + default SERIAL_8250 + depends on SERIAL_8250 + depends on ARCH_TEGRA || COMPILE_TEST + help + Select this option if you have machine with an NVIDIA Tegra SoC and + wish to enable 8250 serial driver for the Tegra serial interfaces. + config SERIAL_OF_PLATFORM tristate "Devicetree based probing for 8250 ports" depends on SERIAL_8250 && OF diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 51a6079d3f1f..a8bfb654d490 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o +obj-$(CONFIG_SERIAL_8250_TEGRA) += 8250_tegra.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 52eaac21ff9f..d6644f3d81fc 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -260,15 +260,6 @@ config SERIAL_SAMSUNG_UARTS help Select the number of available UART ports for the Samsung S3C serial driver - -config SERIAL_SAMSUNG_DEBUG - bool "Samsung SoC serial debug" - depends on SERIAL_SAMSUNG && DEBUG_LL - help - Add support for debugging the serial driver. Since this is - generally being used as a console, we use our own output - routines that go via the low-level debug printascii() - function. config SERIAL_SAMSUNG_CONSOLE bool "Support for console on Samsung SoC serial port" @@ -1111,7 +1102,7 @@ config SERIAL_SC16IS7XX_SPI help Enable SC16IS7xx driver on SPI bus, If required say y, and say n to spi if not required, - This is additional support to exsisting driver. + This is additional support to existing driver. You must select at least one bus for the driver to be built. config SERIAL_TIMBERDALE @@ -1279,6 +1270,7 @@ config SERIAL_AR933X tristate "AR933X serial port support" depends on HAVE_CLK && ATH79 select SERIAL_CORE + select SERIAL_MCTRL_GPIO if GPIOLIB help If you have an Atheros AR933X SOC based board and want to use the built-in UART of the SoC, say Y to this option. @@ -1452,8 +1444,8 @@ config SERIAL_MEN_Z135 config SERIAL_SPRD tristate "Support for Spreadtrum serial" - depends on ARCH_SPRD select SERIAL_CORE + depends on COMMON_CLK help This enables the driver for the Spreadtrum's serial. diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index ea12f10610b6..7e7f1398019f 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -13,6 +13,7 @@ #include <linux/console.h> #include <linux/sysrq.h> #include <linux/delay.h> +#include <linux/gpio/consumer.h> #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_platform.h> @@ -29,6 +30,8 @@ #include <asm/mach-ath79/ar933x_uart.h> +#include "serial_mctrl_gpio.h" + #define DRIVER_NAME "ar933x-uart" #define AR933X_UART_MAX_SCALE 0xff @@ -47,6 +50,8 @@ struct ar933x_uart_port { unsigned int min_baud; unsigned int max_baud; struct clk *clk; + struct mctrl_gpios *gpios; + struct gpio_desc *rts_gpiod; }; static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up, @@ -100,6 +105,18 @@ static inline void ar933x_uart_stop_tx_interrupt(struct ar933x_uart_port *up) ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); } +static inline void ar933x_uart_start_rx_interrupt(struct ar933x_uart_port *up) +{ + up->ier |= AR933X_UART_INT_RX_VALID; + ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); +} + +static inline void ar933x_uart_stop_rx_interrupt(struct ar933x_uart_port *up) +{ + up->ier &= ~AR933X_UART_INT_RX_VALID; + ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); +} + static inline void ar933x_uart_putc(struct ar933x_uart_port *up, int ch) { unsigned int rdata; @@ -125,11 +142,21 @@ static unsigned int ar933x_uart_tx_empty(struct uart_port *port) static unsigned int ar933x_uart_get_mctrl(struct uart_port *port) { - return TIOCM_CAR; + struct ar933x_uart_port *up = + container_of(port, struct ar933x_uart_port, port); + int ret = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + + mctrl_gpio_get(up->gpios, &ret); + + return ret; } static void ar933x_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) { + struct ar933x_uart_port *up = + container_of(port, struct ar933x_uart_port, port); + + mctrl_gpio_set(up->gpios, mctrl); } static void ar933x_uart_start_tx(struct uart_port *port) @@ -140,6 +167,37 @@ static void ar933x_uart_start_tx(struct uart_port *port) ar933x_uart_start_tx_interrupt(up); } +static void ar933x_uart_wait_tx_complete(struct ar933x_uart_port *up) +{ + unsigned int status; + unsigned int timeout = 60000; + + /* Wait up to 60ms for the character(s) to be sent. */ + do { + status = ar933x_uart_read(up, AR933X_UART_CS_REG); + if (--timeout == 0) + break; + udelay(1); + } while (status & AR933X_UART_CS_TX_BUSY); + + if (timeout == 0) + dev_err(up->port.dev, "waiting for TX timed out\n"); +} + +static void ar933x_uart_rx_flush(struct ar933x_uart_port *up) +{ + unsigned int status; + + /* clear RX_VALID interrupt */ + ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_RX_VALID); + + /* remove characters from the RX FIFO */ + do { + ar933x_uart_write(up, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR); + status = ar933x_uart_read(up, AR933X_UART_DATA_REG); + } while (status & AR933X_UART_DATA_RX_CSR); +} + static void ar933x_uart_stop_tx(struct uart_port *port) { struct ar933x_uart_port *up = @@ -153,8 +211,7 @@ static void ar933x_uart_stop_rx(struct uart_port *port) struct ar933x_uart_port *up = container_of(port, struct ar933x_uart_port, port); - up->ier &= ~AR933X_UART_INT_RX_VALID; - ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); + ar933x_uart_stop_rx_interrupt(up); } static void ar933x_uart_break_ctl(struct uart_port *port, int break_state) @@ -336,11 +393,20 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_port *up) static void ar933x_uart_tx_chars(struct ar933x_uart_port *up) { struct circ_buf *xmit = &up->port.state->xmit; + struct serial_rs485 *rs485conf = &up->port.rs485; int count; + bool half_duplex_send = false; if (uart_tx_stopped(&up->port)) return; + if ((rs485conf->flags & SER_RS485_ENABLED) && + (up->port.x_char || !uart_circ_empty(xmit))) { + ar933x_uart_stop_rx_interrupt(up); + gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_ON_SEND)); + half_duplex_send = true; + } + count = up->port.fifosize; do { unsigned int rdata; @@ -368,8 +434,14 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_port *up) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&up->port); - if (!uart_circ_empty(xmit)) + if (!uart_circ_empty(xmit)) { ar933x_uart_start_tx_interrupt(up); + } else if (half_duplex_send) { + ar933x_uart_wait_tx_complete(up); + ar933x_uart_rx_flush(up); + ar933x_uart_start_rx_interrupt(up); + gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_AFTER_SEND)); + } } static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id) @@ -427,8 +499,7 @@ static int ar933x_uart_startup(struct uart_port *port) AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE); /* Enable RX interrupts */ - up->ier = AR933X_UART_INT_RX_VALID; - ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); + ar933x_uart_start_rx_interrupt(up); spin_unlock_irqrestore(&up->port.lock, flags); @@ -511,6 +582,21 @@ static const struct uart_ops ar933x_uart_ops = { .verify_port = ar933x_uart_verify_port, }; +static int ar933x_config_rs485(struct uart_port *port, + struct serial_rs485 *rs485conf) +{ + struct ar933x_uart_port *up = + container_of(port, struct ar933x_uart_port, port); + + if ((rs485conf->flags & SER_RS485_ENABLED) && + !up->rts_gpiod) { + dev_err(port->dev, "RS485 needs rts-gpio\n"); + return 1; + } + port->rs485 = *rs485conf; + return 0; +} + #ifdef CONFIG_SERIAL_AR933X_CONSOLE static struct ar933x_uart_port * ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS]; @@ -680,6 +766,8 @@ static int ar933x_uart_probe(struct platform_device *pdev) goto err_disable_clk; } + uart_get_rs485_mode(&pdev->dev, &port->rs485); + port->mapbase = mem_res->start; port->line = id; port->irq = irq_res->start; @@ -690,6 +778,7 @@ static int ar933x_uart_probe(struct platform_device *pdev) port->regshift = 2; port->fifosize = AR933X_UART_FIFO_SIZE; port->ops = &ar933x_uart_ops; + port->rs485_config = ar933x_config_rs485; baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1); up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD); @@ -697,6 +786,18 @@ static int ar933x_uart_probe(struct platform_device *pdev) baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP); up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD); + up->gpios = mctrl_gpio_init(port, 0); + if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS) + return PTR_ERR(up->gpios); + + up->rts_gpiod = mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS); + + if ((port->rs485.flags & SER_RS485_ENABLED) && + !up->rts_gpiod) { + dev_err(&pdev->dev, "lacking rts-gpio, disabling RS485\n"); + port->rs485.flags &= ~SER_RS485_ENABLED; + } + #ifdef CONFIG_SERIAL_AR933X_CONSOLE ar933x_console_ports[up->port.line] = up; #endif diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index a39c87a7c2e1..8d7080efad9b 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -20,15 +20,12 @@ #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_device.h> -#include <linux/of_gpio.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> #include <linux/atmel_pdc.h> #include <linux/uaccess.h> #include <linux/platform_data/atmel.h> #include <linux/timer.h> -#include <linux/gpio.h> -#include <linux/gpio/consumer.h> #include <linux/err.h> #include <linux/irq.h> #include <linux/suspend.h> @@ -2679,18 +2676,8 @@ static struct console atmel_console = { #define ATMEL_CONSOLE_DEVICE (&atmel_console) -static inline bool atmel_is_console_port(struct uart_port *port) -{ - return port->cons && port->cons->index == port->line; -} - #else #define ATMEL_CONSOLE_DEVICE NULL - -static inline bool atmel_is_console_port(struct uart_port *port) -{ - return false; -} #endif static struct uart_driver atmel_uart = { @@ -2719,14 +2706,14 @@ static int atmel_serial_suspend(struct platform_device *pdev, struct uart_port *port = platform_get_drvdata(pdev); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - if (atmel_is_console_port(port) && console_suspend_enabled) { + if (uart_console(port) && console_suspend_enabled) { /* Drain the TX shifter */ while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY)) cpu_relax(); } - if (atmel_is_console_port(port) && !console_suspend_enabled) { + if (uart_console(port) && !console_suspend_enabled) { /* Cache register values as we won't get a full shutdown/startup * cycle */ @@ -2762,7 +2749,7 @@ static int atmel_serial_resume(struct platform_device *pdev) struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); unsigned long flags; - if (atmel_is_console_port(port) && !console_suspend_enabled) { + if (uart_console(port) && !console_suspend_enabled) { atmel_uart_writel(port, ATMEL_US_MR, atmel_port->cache.mr); atmel_uart_writel(port, ATMEL_US_IER, atmel_port->cache.imr); atmel_uart_writel(port, ATMEL_US_BRGR, atmel_port->cache.brgr); @@ -2916,7 +2903,7 @@ static int atmel_serial_probe(struct platform_device *pdev) goto err_add_port; #ifdef CONFIG_SERIAL_ATMEL_CONSOLE - if (atmel_is_console_port(&atmel_port->uart) + if (uart_console(&atmel_port->uart) && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) { /* * The serial core enabled the clock for us, so undo @@ -2959,7 +2946,7 @@ err_add_port: kfree(atmel_port->rx_ring.buf); atmel_port->rx_ring.buf = NULL; err_alloc_ring: - if (!atmel_is_console_port(&atmel_port->uart)) { + if (!uart_console(&atmel_port->uart)) { clk_put(atmel_port->clk); atmel_port->clk = NULL; } diff --git a/drivers/tty/serial/atmel_serial.h b/drivers/tty/serial/atmel_serial.h index d811d4f2d0c0..0d8a0f9cc5c3 100644 --- a/drivers/tty/serial/atmel_serial.h +++ b/drivers/tty/serial/atmel_serial.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * include/linux/atmel_serial.h * diff --git a/drivers/tty/serial/cpm_uart/cpm_uart.h b/drivers/tty/serial/cpm_uart/cpm_uart.h index 9f175a92fb5d..6113b953ce25 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart.h +++ b/drivers/tty/serial/cpm_uart/cpm_uart.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Driver for CPM (SCC/SMC) serial ports * @@ -13,6 +13,8 @@ #include <linux/platform_device.h> #include <linux/fs_uart_pd.h> +struct gpio_desc; + #if defined(CONFIG_CPM2) #include "cpm_uart_cpm2.h" #elif defined(CONFIG_CPM1) @@ -80,7 +82,7 @@ struct uart_cpm_port { int wait_closing; /* value to combine with opcode to form cpm command */ u32 command; - int gpios[NUM_GPIOS]; + struct gpio_desc *gpios[NUM_GPIOS]; }; extern int cpm_uart_nr; diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index d4b81b06e0cb..a04f74d2e854 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c @@ -30,8 +30,7 @@ #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_platform.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/clk.h> #include <asm/io.h> @@ -88,11 +87,11 @@ static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) struct uart_cpm_port *pinfo = container_of(port, struct uart_cpm_port, port); - if (pinfo->gpios[GPIO_RTS] >= 0) - gpio_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS)); + if (pinfo->gpios[GPIO_RTS]) + gpiod_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS)); - if (pinfo->gpios[GPIO_DTR] >= 0) - gpio_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR)); + if (pinfo->gpios[GPIO_DTR]) + gpiod_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR)); } static unsigned int cpm_uart_get_mctrl(struct uart_port *port) @@ -101,23 +100,23 @@ static unsigned int cpm_uart_get_mctrl(struct uart_port *port) container_of(port, struct uart_cpm_port, port); unsigned int mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; - if (pinfo->gpios[GPIO_CTS] >= 0) { - if (gpio_get_value(pinfo->gpios[GPIO_CTS])) + if (pinfo->gpios[GPIO_CTS]) { + if (gpiod_get_value(pinfo->gpios[GPIO_CTS])) mctrl &= ~TIOCM_CTS; } - if (pinfo->gpios[GPIO_DSR] >= 0) { - if (gpio_get_value(pinfo->gpios[GPIO_DSR])) + if (pinfo->gpios[GPIO_DSR]) { + if (gpiod_get_value(pinfo->gpios[GPIO_DSR])) mctrl &= ~TIOCM_DSR; } - if (pinfo->gpios[GPIO_DCD] >= 0) { - if (gpio_get_value(pinfo->gpios[GPIO_DCD])) + if (pinfo->gpios[GPIO_DCD]) { + if (gpiod_get_value(pinfo->gpios[GPIO_DCD])) mctrl &= ~TIOCM_CAR; } - if (pinfo->gpios[GPIO_RI] >= 0) { - if (!gpio_get_value(pinfo->gpios[GPIO_RI])) + if (pinfo->gpios[GPIO_RI]) { + if (!gpiod_get_value(pinfo->gpios[GPIO_RI])) mctrl |= TIOCM_RNG; } @@ -1139,6 +1138,7 @@ static int cpm_uart_init_port(struct device_node *np, { const u32 *data; void __iomem *mem, *pram; + struct device *dev = pinfo->port.dev; int len; int ret; int i; @@ -1211,29 +1211,23 @@ static int cpm_uart_init_port(struct device_node *np, } for (i = 0; i < NUM_GPIOS; i++) { - int gpio; + struct gpio_desc *gpiod; - pinfo->gpios[i] = -1; + pinfo->gpios[i] = NULL; - gpio = of_get_gpio(np, i); + gpiod = devm_gpiod_get_index(dev, NULL, i, GPIOD_ASIS); - if (gpio_is_valid(gpio)) { - ret = gpio_request(gpio, "cpm_uart"); - if (ret) { - pr_err("can't request gpio #%d: %d\n", i, ret); - continue; - } + if (gpiod) { if (i == GPIO_RTS || i == GPIO_DTR) - ret = gpio_direction_output(gpio, 0); + ret = gpiod_direction_output(gpiod, 0); else - ret = gpio_direction_input(gpio); + ret = gpiod_direction_input(gpiod); if (ret) { pr_err("can't set direction for gpio #%d: %d\n", i, ret); - gpio_free(gpio); continue; } - pinfo->gpios[i] = gpio; + pinfo->gpios[i] = gpiod; } } diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index c14873b67803..2ae9190b64bb 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -170,6 +170,7 @@ static int __init register_earlycon(char *buf, const struct earlycon_id *match) int __init setup_earlycon(char *buf) { const struct earlycon_id **p_match; + bool empty_compatible = true; if (!buf || !buf[0]) return -EINVAL; @@ -177,6 +178,7 @@ int __init setup_earlycon(char *buf) if (early_con.flags & CON_ENABLED) return -EALREADY; +again: for (p_match = __earlycon_table; p_match < __earlycon_table_end; p_match++) { const struct earlycon_id *match = *p_match; @@ -185,6 +187,10 @@ int __init setup_earlycon(char *buf) if (strncmp(buf, match->name, len)) continue; + /* prefer entries with empty compatible */ + if (empty_compatible && *match->compatible) + continue; + if (buf[len]) { if (buf[len] != ',') continue; @@ -195,6 +201,11 @@ int __init setup_earlycon(char *buf) return register_earlycon(buf, match); } + if (empty_compatible) { + empty_compatible = false; + goto again; + } + return -ENOENT; } diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index 2ac87128d7fd..f12f29cf4f31 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -200,7 +200,7 @@ static void efm32_uart_rx_chars(struct efm32_uart_port *efm_port) /* * This is a reserved bit and I only saw it read as 0. But to be * sure not to be confused too much by new devices adhere to the - * warning in the reference manual that reserverd bits might + * warning in the reference manual that reserved bits might * read as 1 in the future. */ rxdata &= ~SW_UARTn_RXDATAX_BERR; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index c31b8f3db6bf..5d41075964f2 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -234,6 +234,7 @@ static DEFINE_IDA(fsl_lpuart_ida); enum lpuart_type { VF610_LPUART, LS1021A_LPUART, + LS1028A_LPUART, IMX7ULP_LPUART, IMX8QXP_LPUART, }; @@ -278,11 +279,16 @@ static const struct lpuart_soc_data vf_data = { .iotype = UPIO_MEM, }; -static const struct lpuart_soc_data ls_data = { +static const struct lpuart_soc_data ls1021a_data = { .devtype = LS1021A_LPUART, .iotype = UPIO_MEM32BE, }; +static const struct lpuart_soc_data ls1028a_data = { + .devtype = LS1028A_LPUART, + .iotype = UPIO_MEM32, +}; + static struct lpuart_soc_data imx7ulp_data = { .devtype = IMX7ULP_LPUART, .iotype = UPIO_MEM32, @@ -297,7 +303,8 @@ static struct lpuart_soc_data imx8qxp_data = { static const struct of_device_id lpuart_dt_ids[] = { { .compatible = "fsl,vf610-lpuart", .data = &vf_data, }, - { .compatible = "fsl,ls1021a-lpuart", .data = &ls_data, }, + { .compatible = "fsl,ls1021a-lpuart", .data = &ls1021a_data, }, + { .compatible = "fsl,ls1028a-lpuart", .data = &ls1028a_data, }, { .compatible = "fsl,imx7ulp-lpuart", .data = &imx7ulp_data, }, { .compatible = "fsl,imx8qxp-lpuart", .data = &imx8qxp_data, }, { /* sentinel */ } @@ -307,6 +314,11 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids); /* Forward declare this for the dma callbacks*/ static void lpuart_dma_tx_complete(void *arg); +static inline bool is_ls1028a_lpuart(struct lpuart_port *sport) +{ + return sport->devtype == LS1028A_LPUART; +} + static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport) { return sport->devtype == IMX8QXP_LPUART; @@ -409,6 +421,7 @@ static void lpuart_dma_tx(struct lpuart_port *sport) struct circ_buf *xmit = &sport->port.state->xmit; struct scatterlist *sgl = sport->tx_sgl; struct device *dev = sport->port.dev; + struct dma_chan *chan = sport->dma_tx_chan; int ret; if (sport->dma_tx_in_progress) @@ -427,17 +440,19 @@ static void lpuart_dma_tx(struct lpuart_port *sport) sg_set_buf(sgl + 1, xmit->buf, xmit->head); } - ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); + ret = dma_map_sg(chan->device->dev, sgl, sport->dma_tx_nents, + DMA_TO_DEVICE); if (!ret) { dev_err(dev, "DMA mapping error for TX.\n"); return; } - sport->dma_tx_desc = dmaengine_prep_slave_sg(sport->dma_tx_chan, sgl, + sport->dma_tx_desc = dmaengine_prep_slave_sg(chan, sgl, ret, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); if (!sport->dma_tx_desc) { - dma_unmap_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); + dma_unmap_sg(chan->device->dev, sgl, sport->dma_tx_nents, + DMA_TO_DEVICE); dev_err(dev, "Cannot prepare TX slave DMA!\n"); return; } @@ -446,7 +461,7 @@ static void lpuart_dma_tx(struct lpuart_port *sport) sport->dma_tx_desc->callback_param = sport; sport->dma_tx_in_progress = true; sport->dma_tx_cookie = dmaengine_submit(sport->dma_tx_desc); - dma_async_issue_pending(sport->dma_tx_chan); + dma_async_issue_pending(chan); } static bool lpuart_stopped_or_empty(struct uart_port *port) @@ -459,11 +474,13 @@ static void lpuart_dma_tx_complete(void *arg) struct lpuart_port *sport = arg; struct scatterlist *sgl = &sport->tx_sgl[0]; struct circ_buf *xmit = &sport->port.state->xmit; + struct dma_chan *chan = sport->dma_tx_chan; unsigned long flags; spin_lock_irqsave(&sport->port.lock, flags); - dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); + dma_unmap_sg(chan->device->dev, sgl, sport->dma_tx_nents, + DMA_TO_DEVICE); xmit->tail = (xmit->tail + sport->dma_tx_bytes) & (UART_XMIT_SIZE - 1); @@ -529,15 +546,16 @@ static bool lpuart_is_32(struct lpuart_port *sport) static void lpuart_flush_buffer(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); + struct dma_chan *chan = sport->dma_tx_chan; u32 val; if (sport->lpuart_dma_tx_use) { if (sport->dma_tx_in_progress) { - dma_unmap_sg(sport->port.dev, &sport->tx_sgl[0], + dma_unmap_sg(chan->device->dev, &sport->tx_sgl[0], sport->dma_tx_nents, DMA_TO_DEVICE); sport->dma_tx_in_progress = false; } - dmaengine_terminate_all(sport->dma_tx_chan); + dmaengine_terminate_all(chan); } if (lpuart_is_32(sport)) { @@ -993,6 +1011,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) struct tty_port *port = &sport->port.state->port; struct dma_tx_state state; enum dma_status dmastat; + struct dma_chan *chan = sport->dma_rx_chan; struct circ_buf *ring = &sport->rx_ring; unsigned long flags; int count = 0; @@ -1053,10 +1072,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) spin_lock_irqsave(&sport->port.lock, flags); - dmastat = dmaengine_tx_status(sport->dma_rx_chan, - sport->dma_rx_cookie, - &state); - + dmastat = dmaengine_tx_status(chan, sport->dma_rx_cookie, &state); if (dmastat == DMA_ERROR) { dev_err(sport->port.dev, "Rx DMA transfer failed!\n"); spin_unlock_irqrestore(&sport->port.lock, flags); @@ -1064,7 +1080,8 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) } /* CPU claims ownership of RX DMA buffer */ - dma_sync_sg_for_cpu(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); + dma_sync_sg_for_cpu(chan->device->dev, &sport->rx_sgl, 1, + DMA_FROM_DEVICE); /* * ring->head points to the end of data already written by the DMA. @@ -1106,7 +1123,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) sport->port.icount.rx += count; } - dma_sync_sg_for_device(sport->port.dev, &sport->rx_sgl, 1, + dma_sync_sg_for_device(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); spin_unlock_irqrestore(&sport->port.lock, flags); @@ -1138,6 +1155,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport) struct tty_port *port = &sport->port.state->port; struct tty_struct *tty = port->tty; struct ktermios *termios = &tty->termios; + struct dma_chan *chan = sport->dma_rx_chan; baud = tty_get_baud_rate(tty); @@ -1159,7 +1177,8 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport) return -ENOMEM; sg_init_one(&sport->rx_sgl, ring->buf, sport->rx_dma_rng_buf_len); - nent = dma_map_sg(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); + nent = dma_map_sg(chan->device->dev, &sport->rx_sgl, 1, + DMA_FROM_DEVICE); if (!nent) { dev_err(sport->port.dev, "DMA Rx mapping error\n"); @@ -1170,7 +1189,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport) dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; dma_rx_sconfig.src_maxburst = 1; dma_rx_sconfig.direction = DMA_DEV_TO_MEM; - ret = dmaengine_slave_config(sport->dma_rx_chan, &dma_rx_sconfig); + ret = dmaengine_slave_config(chan, &dma_rx_sconfig); if (ret < 0) { dev_err(sport->port.dev, @@ -1178,7 +1197,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport) return ret; } - sport->dma_rx_desc = dmaengine_prep_dma_cyclic(sport->dma_rx_chan, + sport->dma_rx_desc = dmaengine_prep_dma_cyclic(chan, sg_dma_address(&sport->rx_sgl), sport->rx_sgl.length, sport->rx_sgl.length / 2, @@ -1192,7 +1211,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport) sport->dma_rx_desc->callback = lpuart_dma_rx_complete; sport->dma_rx_desc->callback_param = sport; sport->dma_rx_cookie = dmaengine_submit(sport->dma_rx_desc); - dma_async_issue_pending(sport->dma_rx_chan); + dma_async_issue_pending(chan); if (lpuart_is_32(sport)) { unsigned long temp = lpuart32_read(&sport->port, UARTBAUD); @@ -1210,11 +1229,12 @@ static void lpuart_dma_rx_free(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); + struct dma_chan *chan = sport->dma_rx_chan; - if (sport->dma_rx_chan) - dmaengine_terminate_all(sport->dma_rx_chan); + if (chan) + dmaengine_terminate_all(chan); - dma_unmap_sg(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); + dma_unmap_sg(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); kfree(sport->rx_ring.buf); sport->rx_ring.tail = 0; sport->rx_ring.head = 0; @@ -1490,39 +1510,77 @@ static void rx_dma_timer_init(struct lpuart_port *sport) add_timer(&sport->lpuart_timer); } +static void lpuart_request_dma(struct lpuart_port *sport) +{ + sport->dma_tx_chan = dma_request_chan(sport->port.dev, "tx"); + if (IS_ERR(sport->dma_tx_chan)) { + dev_info_once(sport->port.dev, + "DMA tx channel request failed, operating without tx DMA (%ld)\n", + PTR_ERR(sport->dma_tx_chan)); + sport->dma_tx_chan = NULL; + } + + sport->dma_rx_chan = dma_request_chan(sport->port.dev, "rx"); + if (IS_ERR(sport->dma_rx_chan)) { + dev_info_once(sport->port.dev, + "DMA rx channel request failed, operating without rx DMA (%ld)\n", + PTR_ERR(sport->dma_rx_chan)); + sport->dma_rx_chan = NULL; + } +} + static void lpuart_tx_dma_startup(struct lpuart_port *sport) { u32 uartbaud; + int ret; - if (sport->dma_tx_chan && !lpuart_dma_tx_request(&sport->port)) { - init_waitqueue_head(&sport->dma_wait); - sport->lpuart_dma_tx_use = true; - if (lpuart_is_32(sport)) { - uartbaud = lpuart32_read(&sport->port, UARTBAUD); - lpuart32_write(&sport->port, - uartbaud | UARTBAUD_TDMAE, UARTBAUD); - } else { - writeb(readb(sport->port.membase + UARTCR5) | - UARTCR5_TDMAS, sport->port.membase + UARTCR5); - } + if (!sport->dma_tx_chan) + goto err; + + ret = lpuart_dma_tx_request(&sport->port); + if (ret) + goto err; + + init_waitqueue_head(&sport->dma_wait); + sport->lpuart_dma_tx_use = true; + if (lpuart_is_32(sport)) { + uartbaud = lpuart32_read(&sport->port, UARTBAUD); + lpuart32_write(&sport->port, + uartbaud | UARTBAUD_TDMAE, UARTBAUD); } else { - sport->lpuart_dma_tx_use = false; + writeb(readb(sport->port.membase + UARTCR5) | + UARTCR5_TDMAS, sport->port.membase + UARTCR5); } + + return; + +err: + sport->lpuart_dma_tx_use = false; } static void lpuart_rx_dma_startup(struct lpuart_port *sport) { - if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) { - /* set Rx DMA timeout */ - sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT); - if (!sport->dma_rx_timeout) - sport->dma_rx_timeout = 1; + int ret; - sport->lpuart_dma_rx_use = true; - rx_dma_timer_init(sport); - } else { - sport->lpuart_dma_rx_use = false; - } + if (!sport->dma_rx_chan) + goto err; + + ret = lpuart_start_rx_dma(sport); + if (ret) + goto err; + + /* set Rx DMA timeout */ + sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT); + if (!sport->dma_rx_timeout) + sport->dma_rx_timeout = 1; + + sport->lpuart_dma_rx_use = true; + rx_dma_timer_init(sport); + + return; + +err: + sport->lpuart_dma_rx_use = false; } static int lpuart_startup(struct uart_port *port) @@ -1541,6 +1599,8 @@ static int lpuart_startup(struct uart_port *port) sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTPFIFO_RXSIZE_OFF) & UARTPFIFO_FIFOSIZE_MASK); + lpuart_request_dma(sport); + spin_lock_irqsave(&sport->port.lock, flags); lpuart_setup_watermark_enable(sport); @@ -1587,11 +1647,23 @@ static int lpuart32_startup(struct uart_port *port) sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTFIFO_RXSIZE_OFF) & UARTFIFO_FIFOSIZE_MASK); + /* + * The LS1028A has a fixed length of 16 words. Although it supports the + * RX/TXSIZE fields their encoding is different. Eg the reference manual + * states 0b101 is 16 words. + */ + if (is_ls1028a_lpuart(sport)) { + sport->rxfifo_size = 16; + sport->txfifo_size = 16; + sport->port.fifosize = sport->txfifo_size; + } + + lpuart_request_dma(sport); + spin_lock_irqsave(&sport->port.lock, flags); lpuart32_setup_watermark_enable(sport); - lpuart_rx_dma_startup(sport); lpuart_tx_dma_startup(sport); @@ -1615,6 +1687,11 @@ static void lpuart_dma_shutdown(struct lpuart_port *sport) dmaengine_terminate_all(sport->dma_tx_chan); } } + + if (sport->dma_tx_chan) + dma_release_channel(sport->dma_tx_chan); + if (sport->dma_rx_chan) + dma_release_channel(sport->dma_rx_chan); } static void lpuart_shutdown(struct uart_port *port) @@ -1811,11 +1888,12 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios, spin_unlock_irqrestore(&sport->port.lock, flags); } -static void -lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate) +static void __lpuart32_serial_setbrg(struct uart_port *port, + unsigned int baudrate, bool use_rx_dma, + bool use_tx_dma) { u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp; - u32 clk = sport->port.uartclk; + u32 clk = port->uartclk; /* * The idea is to use the best OSR (over-sampling rate) possible. @@ -1861,10 +1939,10 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate) /* handle buadrate outside acceptable rate */ if (baud_diff > ((baudrate / 100) * 3)) - dev_warn(sport->port.dev, + dev_warn(port->dev, "unacceptable baud rate difference of more than 3%%\n"); - tmp = lpuart32_read(&sport->port, UARTBAUD); + tmp = lpuart32_read(port, UARTBAUD); if ((osr > 3) && (osr < 8)) tmp |= UARTBAUD_BOTHEDGE; @@ -1875,14 +1953,23 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate) tmp &= ~UARTBAUD_SBR_MASK; tmp |= sbr & UARTBAUD_SBR_MASK; - if (!sport->lpuart_dma_rx_use) + if (!use_rx_dma) tmp &= ~UARTBAUD_RDMAE; - if (!sport->lpuart_dma_tx_use) + if (!use_tx_dma) tmp &= ~UARTBAUD_TDMAE; - lpuart32_write(&sport->port, tmp, UARTBAUD); + lpuart32_write(port, tmp, UARTBAUD); +} + +static void lpuart32_serial_setbrg(struct lpuart_port *sport, + unsigned int baudrate) +{ + __lpuart32_serial_setbrg(&sport->port, baudrate, + sport->lpuart_dma_rx_use, + sport->lpuart_dma_tx_use); } + static void lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) @@ -2376,6 +2463,30 @@ static int __init lpuart32_early_console_setup(struct earlycon_device *device, return 0; } +static int __init ls1028a_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + u32 cr; + + if (!device->port.membase) + return -ENODEV; + + device->port.iotype = UPIO_MEM32; + device->con->write = lpuart32_early_write; + + /* set the baudrate */ + if (device->port.uartclk && device->baud) + __lpuart32_serial_setbrg(&device->port, device->baud, + false, false); + + /* enable transmitter */ + cr = lpuart32_read(&device->port, UARTCTRL); + cr |= UARTCTRL_TE; + lpuart32_write(&device->port, cr, UARTCTRL); + + return 0; +} + static int __init lpuart32_imx_early_console_setup(struct earlycon_device *device, const char *opt) { @@ -2390,6 +2501,7 @@ static int __init lpuart32_imx_early_console_setup(struct earlycon_device *devic } OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup); +OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup); EARLYCON_DECLARE(lpuart, lpuart_early_console_setup); EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup); @@ -2520,16 +2632,6 @@ static int lpuart_probe(struct platform_device *pdev) sport->port.rs485_config(&sport->port, &sport->port.rs485); - sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx"); - if (!sport->dma_tx_chan) - dev_info(sport->port.dev, "DMA tx channel request failed, " - "operating without tx DMA\n"); - - sport->dma_rx_chan = dma_request_slave_channel(sport->port.dev, "rx"); - if (!sport->dma_rx_chan) - dev_info(sport->port.dev, "DMA rx channel request failed, " - "operating without rx DMA\n"); - return 0; failed_attach_port: diff --git a/drivers/tty/serial/icom.h b/drivers/tty/serial/icom.h index 8a77e739b333..26e3aa7b01e2 100644 --- a/drivers/tty/serial/icom.h +++ b/drivers/tty/serial/icom.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * icom.h * diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 31033d517e82..7d16fe41932f 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -39,7 +39,7 @@ #include <linux/fs.h> #include <linux/ip.h> #include <linux/dmapool.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/sched.h> #include <linux/time.h> #include <linux/wait.h> @@ -61,7 +61,6 @@ #define IFX_SPI_HEADER_F (-2) #define PO_POST_DELAY 200 -#define IFX_MDM_RST_PMU 4 /* forward reference */ static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev); @@ -81,7 +80,7 @@ static struct notifier_block ifx_modem_reboot_notifier_block = { static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev) { - gpio_set_value(IFX_MDM_RST_PMU, 1); + gpiod_set_value(ifx_dev->gpio.pmu_reset, 1); msleep(PO_POST_DELAY); return 0; @@ -107,7 +106,7 @@ static int ifx_modem_reboot_callback(struct notifier_block *nfb, */ static inline void mrdy_set_high(struct ifx_spi_device *ifx) { - gpio_set_value(ifx->gpio.mrdy, 1); + gpiod_set_value(ifx->gpio.mrdy, 1); } /** @@ -117,7 +116,7 @@ static inline void mrdy_set_high(struct ifx_spi_device *ifx) */ static inline void mrdy_set_low(struct ifx_spi_device *ifx) { - gpio_set_value(ifx->gpio.mrdy, 0); + gpiod_set_value(ifx->gpio.mrdy, 0); } /** @@ -244,7 +243,7 @@ static inline void swap_buf_32(unsigned char *buf, int len, void *end) */ static void mrdy_assert(struct ifx_spi_device *ifx_dev) { - int val = gpio_get_value(ifx_dev->gpio.srdy); + int val = gpiod_get_value(ifx_dev->gpio.srdy); if (!val) { if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags)) { @@ -691,7 +690,7 @@ complete_exit: clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &(ifx_dev->flags)); queue_length = kfifo_len(&ifx_dev->tx_fifo); - srdy = gpio_get_value(ifx_dev->gpio.srdy); + srdy = gpiod_get_value(ifx_dev->gpio.srdy); if (!srdy) ifx_spi_power_state_clear(ifx_dev, IFX_SPI_POWER_SRDY); @@ -898,7 +897,7 @@ static irqreturn_t ifx_spi_srdy_interrupt(int irq, void *dev) static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev) { struct ifx_spi_device *ifx_dev = dev; - int val = gpio_get_value(ifx_dev->gpio.reset_out); + int val = gpiod_get_value(ifx_dev->gpio.reset_out); int solreset = test_bit(MR_START, &ifx_dev->mdm_reset_state); if (val == 0) { @@ -954,14 +953,14 @@ static int ifx_spi_reset(struct ifx_spi_device *ifx_dev) * to reset properly */ set_bit(MR_START, &ifx_dev->mdm_reset_state); - gpio_set_value(ifx_dev->gpio.po, 0); - gpio_set_value(ifx_dev->gpio.reset, 0); + gpiod_set_value(ifx_dev->gpio.po, 0); + gpiod_set_value(ifx_dev->gpio.reset, 0); msleep(25); - gpio_set_value(ifx_dev->gpio.reset, 1); + gpiod_set_value(ifx_dev->gpio.reset, 1); msleep(1); - gpio_set_value(ifx_dev->gpio.po, 1); + gpiod_set_value(ifx_dev->gpio.po, 1); msleep(1); - gpio_set_value(ifx_dev->gpio.po, 0); + gpiod_set_value(ifx_dev->gpio.po, 0); ret = wait_event_timeout(ifx_dev->mdm_reset_wait, test_bit(MR_COMPLETE, &ifx_dev->mdm_reset_state), @@ -992,22 +991,23 @@ static int ifx_spi_spi_probe(struct spi_device *spi) int srdy; struct ifx_modem_platform_data *pl_data; struct ifx_spi_device *ifx_dev; + struct device *dev = &spi->dev; if (saved_ifx_dev) { - dev_dbg(&spi->dev, "ignoring subsequent detection"); + dev_dbg(dev, "ignoring subsequent detection"); return -ENODEV; } - pl_data = dev_get_platdata(&spi->dev); + pl_data = dev_get_platdata(dev); if (!pl_data) { - dev_err(&spi->dev, "missing platform data!"); + dev_err(dev, "missing platform data!"); return -ENODEV; } /* initialize structure to hold our device variables */ ifx_dev = kzalloc(sizeof(struct ifx_spi_device), GFP_KERNEL); if (!ifx_dev) { - dev_err(&spi->dev, "spi device allocation failed"); + dev_err(dev, "spi device allocation failed"); return -ENOMEM; } saved_ifx_dev = ifx_dev; @@ -1026,7 +1026,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi) spi->bits_per_word = spi_bpw; ret = spi_setup(spi); if (ret) { - dev_err(&spi->dev, "SPI setup wasn't successful %d", ret); + dev_err(dev, "SPI setup wasn't successful %d", ret); kfree(ifx_dev); return -ENODEV; } @@ -1049,7 +1049,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi) &ifx_dev->tx_bus, GFP_KERNEL); if (!ifx_dev->tx_buffer) { - dev_err(&spi->dev, "DMA-TX buffer allocation failed"); + dev_err(dev, "DMA-TX buffer allocation failed"); ret = -ENOMEM; goto error_ret; } @@ -1058,7 +1058,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi) &ifx_dev->rx_bus, GFP_KERNEL); if (!ifx_dev->rx_buffer) { - dev_err(&spi->dev, "DMA-RX buffer allocation failed"); + dev_err(dev, "DMA-RX buffer allocation failed"); ret = -ENOMEM; goto error_ret; } @@ -1075,122 +1075,83 @@ static int ifx_spi_spi_probe(struct spi_device *spi) /* create our tty port */ ret = ifx_spi_create_port(ifx_dev); if (ret != 0) { - dev_err(&spi->dev, "create default tty port failed"); + dev_err(dev, "create default tty port failed"); goto error_ret; } - ifx_dev->gpio.reset = pl_data->rst_pmu; - ifx_dev->gpio.po = pl_data->pwr_on; - ifx_dev->gpio.mrdy = pl_data->mrdy; - ifx_dev->gpio.srdy = pl_data->srdy; - ifx_dev->gpio.reset_out = pl_data->rst_out; - - dev_info(&spi->dev, "gpios %d, %d, %d, %d, %d", - ifx_dev->gpio.reset, ifx_dev->gpio.po, ifx_dev->gpio.mrdy, - ifx_dev->gpio.srdy, ifx_dev->gpio.reset_out); - - /* Configure gpios */ - ret = gpio_request(ifx_dev->gpio.reset, "ifxModem"); - if (ret < 0) { - dev_err(&spi->dev, "Unable to allocate GPIO%d (RESET)", - ifx_dev->gpio.reset); + ifx_dev->gpio.reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ifx_dev->gpio.reset)) { + dev_err(dev, "could not obtain reset GPIO\n"); + ret = PTR_ERR(ifx_dev->gpio.reset); goto error_ret; } - ret += gpio_direction_output(ifx_dev->gpio.reset, 0); - ret += gpio_export(ifx_dev->gpio.reset, 1); - if (ret) { - dev_err(&spi->dev, "Unable to configure GPIO%d (RESET)", - ifx_dev->gpio.reset); - ret = -EBUSY; - goto error_ret2; - } - - ret = gpio_request(ifx_dev->gpio.po, "ifxModem"); - ret += gpio_direction_output(ifx_dev->gpio.po, 0); - ret += gpio_export(ifx_dev->gpio.po, 1); - if (ret) { - dev_err(&spi->dev, "Unable to configure GPIO%d (ON)", - ifx_dev->gpio.po); - ret = -EBUSY; - goto error_ret3; - } - - ret = gpio_request(ifx_dev->gpio.mrdy, "ifxModem"); - if (ret < 0) { - dev_err(&spi->dev, "Unable to allocate GPIO%d (MRDY)", - ifx_dev->gpio.mrdy); - goto error_ret3; - } - ret += gpio_export(ifx_dev->gpio.mrdy, 1); - ret += gpio_direction_output(ifx_dev->gpio.mrdy, 0); - if (ret) { - dev_err(&spi->dev, "Unable to configure GPIO%d (MRDY)", - ifx_dev->gpio.mrdy); - ret = -EBUSY; - goto error_ret4; + gpiod_set_consumer_name(ifx_dev->gpio.reset, "ifxModem reset"); + ifx_dev->gpio.po = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW); + if (IS_ERR(ifx_dev->gpio.po)) { + dev_err(dev, "could not obtain power GPIO\n"); + ret = PTR_ERR(ifx_dev->gpio.po); + goto error_ret; } - - ret = gpio_request(ifx_dev->gpio.srdy, "ifxModem"); - if (ret < 0) { - dev_err(&spi->dev, "Unable to allocate GPIO%d (SRDY)", - ifx_dev->gpio.srdy); - ret = -EBUSY; - goto error_ret4; + gpiod_set_consumer_name(ifx_dev->gpio.po, "ifxModem power"); + ifx_dev->gpio.mrdy = devm_gpiod_get(dev, "mrdy", GPIOD_OUT_LOW); + if (IS_ERR(ifx_dev->gpio.mrdy)) { + dev_err(dev, "could not obtain mrdy GPIO\n"); + ret = PTR_ERR(ifx_dev->gpio.mrdy); + goto error_ret; } - ret += gpio_export(ifx_dev->gpio.srdy, 1); - ret += gpio_direction_input(ifx_dev->gpio.srdy); - if (ret) { - dev_err(&spi->dev, "Unable to configure GPIO%d (SRDY)", - ifx_dev->gpio.srdy); - ret = -EBUSY; - goto error_ret5; + gpiod_set_consumer_name(ifx_dev->gpio.mrdy, "ifxModem mrdy"); + ifx_dev->gpio.srdy = devm_gpiod_get(dev, "srdy", GPIOD_IN); + if (IS_ERR(ifx_dev->gpio.srdy)) { + dev_err(dev, "could not obtain srdy GPIO\n"); + ret = PTR_ERR(ifx_dev->gpio.srdy); + goto error_ret; } - - ret = gpio_request(ifx_dev->gpio.reset_out, "ifxModem"); - if (ret < 0) { - dev_err(&spi->dev, "Unable to allocate GPIO%d (RESET_OUT)", - ifx_dev->gpio.reset_out); - goto error_ret5; + gpiod_set_consumer_name(ifx_dev->gpio.srdy, "ifxModem srdy"); + ifx_dev->gpio.reset_out = devm_gpiod_get(dev, "rst_out", GPIOD_IN); + if (IS_ERR(ifx_dev->gpio.reset_out)) { + dev_err(dev, "could not obtain rst_out GPIO\n"); + ret = PTR_ERR(ifx_dev->gpio.reset_out); + goto error_ret; } - ret += gpio_export(ifx_dev->gpio.reset_out, 1); - ret += gpio_direction_input(ifx_dev->gpio.reset_out); - if (ret) { - dev_err(&spi->dev, "Unable to configure GPIO%d (RESET_OUT)", - ifx_dev->gpio.reset_out); - ret = -EBUSY; - goto error_ret6; + gpiod_set_consumer_name(ifx_dev->gpio.reset_out, "ifxModem reset out"); + ifx_dev->gpio.pmu_reset = devm_gpiod_get(dev, "pmu_reset", GPIOD_ASIS); + if (IS_ERR(ifx_dev->gpio.pmu_reset)) { + dev_err(dev, "could not obtain pmu_reset GPIO\n"); + ret = PTR_ERR(ifx_dev->gpio.pmu_reset); + goto error_ret; } + gpiod_set_consumer_name(ifx_dev->gpio.pmu_reset, "ifxModem PMU reset"); - ret = request_irq(gpio_to_irq(ifx_dev->gpio.reset_out), + ret = request_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), ifx_spi_reset_interrupt, IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, DRVNAME, ifx_dev); if (ret) { - dev_err(&spi->dev, "Unable to get irq %x\n", - gpio_to_irq(ifx_dev->gpio.reset_out)); - goto error_ret6; + dev_err(dev, "Unable to get irq %x\n", + gpiod_to_irq(ifx_dev->gpio.reset_out)); + goto error_ret; } ret = ifx_spi_reset(ifx_dev); - ret = request_irq(gpio_to_irq(ifx_dev->gpio.srdy), + ret = request_irq(gpiod_to_irq(ifx_dev->gpio.srdy), ifx_spi_srdy_interrupt, IRQF_TRIGGER_RISING, DRVNAME, ifx_dev); if (ret) { - dev_err(&spi->dev, "Unable to get irq %x", - gpio_to_irq(ifx_dev->gpio.srdy)); - goto error_ret7; + dev_err(dev, "Unable to get irq %x", + gpiod_to_irq(ifx_dev->gpio.srdy)); + goto error_ret2; } /* set pm runtime power state and register with power system */ - pm_runtime_set_active(&spi->dev); - pm_runtime_enable(&spi->dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); /* handle case that modem is already signaling SRDY */ /* no outgoing tty open at this point, this just satisfies the * modem's read and should reset communication properly */ - srdy = gpio_get_value(ifx_dev->gpio.srdy); + srdy = gpiod_get_value(ifx_dev->gpio.srdy); if (srdy) { mrdy_assert(ifx_dev); @@ -1199,18 +1160,8 @@ static int ifx_spi_spi_probe(struct spi_device *spi) mrdy_set_low(ifx_dev); return 0; -error_ret7: - free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev); -error_ret6: - gpio_free(ifx_dev->gpio.srdy); -error_ret5: - gpio_free(ifx_dev->gpio.mrdy); -error_ret4: - gpio_free(ifx_dev->gpio.reset); -error_ret3: - gpio_free(ifx_dev->gpio.po); error_ret2: - gpio_free(ifx_dev->gpio.reset_out); + free_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), ifx_dev); error_ret: ifx_spi_free_device(ifx_dev); saved_ifx_dev = NULL; @@ -1234,14 +1185,8 @@ static int ifx_spi_spi_remove(struct spi_device *spi) pm_runtime_disable(&spi->dev); /* free irq */ - free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev); - free_irq(gpio_to_irq(ifx_dev->gpio.srdy), ifx_dev); - - gpio_free(ifx_dev->gpio.srdy); - gpio_free(ifx_dev->gpio.mrdy); - gpio_free(ifx_dev->gpio.reset); - gpio_free(ifx_dev->gpio.po); - gpio_free(ifx_dev->gpio.reset_out); + free_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), ifx_dev); + free_irq(gpiod_to_irq(ifx_dev->gpio.srdy), ifx_dev); /* free allocations */ ifx_spi_free_device(ifx_dev); diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h index c5a2514212ff..ecb841d928a7 100644 --- a/drivers/tty/serial/ifx6x60.h +++ b/drivers/tty/serial/ifx6x60.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /**************************************************************************** * * Driver for the IFX spi modem. @@ -10,6 +10,8 @@ #ifndef _IFX6X60_H #define _IFX6X60_H +struct gpio_desc; + #define DRVNAME "ifx6x60" #define TTYNAME "ttyIFX" @@ -94,11 +96,12 @@ struct ifx_spi_device { struct { /* gpio lines */ - unsigned short srdy; /* slave-ready gpio */ - unsigned short mrdy; /* master-ready gpio */ - unsigned short reset; /* modem-reset gpio */ - unsigned short po; /* modem-on gpio */ - unsigned short reset_out; /* modem-in-reset gpio */ + struct gpio_desc *srdy; /* slave-ready gpio */ + struct gpio_desc *mrdy; /* master-ready gpio */ + struct gpio_desc *reset; /* modem-reset gpio */ + struct gpio_desc *po; /* modem-on gpio */ + struct gpio_desc *reset_out; /* modem-in-reset gpio */ + struct gpio_desc *pmu_reset; /* PMU reset gpio */ /* state/stats */ int unack_srdy_int_nb; } gpio; diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index d337782b3648..f4d68109bc8b 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -195,6 +195,8 @@ struct imx_port { unsigned int have_rtscts:1; unsigned int have_rtsgpio:1; unsigned int dte_mode:1; + unsigned int inverted_tx:1; + unsigned int inverted_rx:1; struct clk *clk_ipg; struct clk *clk_per; const struct imx_uart_data *devdata; @@ -1335,7 +1337,7 @@ static int imx_uart_startup(struct uart_port *port) int retval, i; unsigned long flags; int dma_is_inited = 0; - u32 ucr1, ucr2, ucr4; + u32 ucr1, ucr2, ucr3, ucr4; retval = clk_prepare_enable(sport->clk_per); if (retval) @@ -1387,11 +1389,29 @@ static int imx_uart_startup(struct uart_port *port) imx_uart_writel(sport, ucr1, UCR1); - ucr4 = imx_uart_readl(sport, UCR4) & ~UCR4_OREN; + ucr4 = imx_uart_readl(sport, UCR4) & ~(UCR4_OREN | UCR4_INVR); if (!sport->dma_is_enabled) ucr4 |= UCR4_OREN; + if (sport->inverted_rx) + ucr4 |= UCR4_INVR; imx_uart_writel(sport, ucr4, UCR4); + ucr3 = imx_uart_readl(sport, UCR3) & ~UCR3_INVT; + /* + * configure tx polarity before enabling tx + */ + if (sport->inverted_tx) + ucr3 |= UCR3_INVT; + + if (!imx_uart_is_imx1(sport)) { + ucr3 |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD; + + if (sport->dte_mode) + /* disable broken interrupts */ + ucr3 &= ~(UCR3_RI | UCR3_DCD); + } + imx_uart_writel(sport, ucr3, UCR3); + ucr2 = imx_uart_readl(sport, UCR2) & ~UCR2_ATEN; ucr2 |= (UCR2_RXEN | UCR2_TXEN); if (!sport->have_rtscts) @@ -1404,20 +1424,6 @@ static int imx_uart_startup(struct uart_port *port) ucr2 &= ~UCR2_RTSEN; imx_uart_writel(sport, ucr2, UCR2); - if (!imx_uart_is_imx1(sport)) { - u32 ucr3; - - ucr3 = imx_uart_readl(sport, UCR3); - - ucr3 |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD; - - if (sport->dte_mode) - /* disable broken interrupts */ - ucr3 &= ~(UCR3_RI | UCR3_DCD); - - imx_uart_writel(sport, ucr3, UCR3); - } - /* * Enable modem status interrupts */ @@ -2184,6 +2190,12 @@ static int imx_uart_probe_dt(struct imx_port *sport, if (of_get_property(np, "rts-gpios", NULL)) sport->have_rtsgpio = 1; + if (of_get_property(np, "fsl,inverted-tx", NULL)) + sport->inverted_tx = 1; + + if (of_get_property(np, "fsl,inverted-rx", NULL)) + sport->inverted_rx = 1; + return 0; } #else diff --git a/drivers/tty/serial/jsm/jsm.h b/drivers/tty/serial/jsm/jsm.h index 7a128aaa3a66..8489c07f4cd5 100644 --- a/drivers/tty/serial/jsm/jsm.h +++ b/drivers/tty/serial/jsm/jsm.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /************************************************************************ * Copyright 2003 Digi International (www.digi.com) * diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index c7d51b51898f..c9f94fa82be4 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -169,15 +169,13 @@ static int configure_kgdboc(void) if (!p) goto noconfig; - cons = console_drivers; - while (cons) { + for_each_console(cons) { int idx; if (cons->device && cons->device(cons, &idx) == p && idx == tty_line) { kgdboc_io_ops.is_console = 1; break; } - cons = cons->next; } kgdb_tty_driver = p; diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index f67226df30d4..c5e46ff972e4 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -11,7 +11,6 @@ #include <linux/clk.h> #include <linux/console.h> #include <linux/device.h> -#include <linux/gpio.h> #include <linux/init.h> #include <linux/io.h> #include <linux/ioport.h> diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index e0b720ac754b..f7d6b3c9ea45 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -37,8 +37,6 @@ #include <linux/of_gpio.h> #include <linux/platform_data/serial-omap.h> -#include <dt-bindings/gpio/gpio.h> - #define OMAP_MAX_HSUART_PORTS 10 #define UART_BUILD_REVISION(x, y) (((x) << 8) | (y)) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 0a96217dba67..40fa7a27722d 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -310,32 +310,32 @@ static ssize_t port_show_regs(struct file *file, char __user *user_buf, if (!buf) return 0; - len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len, "PCH EG20T port[%d] regs:\n", priv->port.line); - len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len, "=================================\n"); - len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len, "IER: \t0x%02x\n", ioread8(priv->membase + UART_IER)); - len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len, "IIR: \t0x%02x\n", ioread8(priv->membase + UART_IIR)); - len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len, "LCR: \t0x%02x\n", ioread8(priv->membase + UART_LCR)); - len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len, "MCR: \t0x%02x\n", ioread8(priv->membase + UART_MCR)); - len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len, "LSR: \t0x%02x\n", ioread8(priv->membase + UART_LSR)); - len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len, "MSR: \t0x%02x\n", ioread8(priv->membase + UART_MSR)); - len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len, "BRCSR: \t0x%02x\n", ioread8(priv->membase + PCH_UART_BRCSR)); lcr = ioread8(priv->membase + UART_LCR); iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR); - len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len, "DLL: \t0x%02x\n", ioread8(priv->membase + UART_DLL)); - len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len, "DLM: \t0x%02x\n", ioread8(priv->membase + UART_DLM)); iowrite8(lcr, priv->membase + UART_LCR); diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c index 484b7e8d5381..0a12fb11e698 100644 --- a/drivers/tty/serial/pic32_uart.c +++ b/drivers/tty/serial/pic32_uart.c @@ -768,11 +768,6 @@ static int __init pic32_console_init(void) } console_initcall(pic32_console_init); -static inline bool is_pic32_console_port(struct uart_port *port) -{ - return port->cons && port->cons->index == port->line; -} - /* * Late console initialization. */ @@ -873,8 +868,7 @@ static int pic32_uart_probe(struct platform_device *pdev) } #ifdef CONFIG_SERIAL_PIC32_CONSOLE - if (is_pic32_console_port(port) && - (pic32_console.flags & CON_ENABLED)) { + if (uart_console(port) && (pic32_console.flags & CON_ENABLED)) { /* The peripheral clock has been enabled by console_setup, * so disable it till the port is used. */ diff --git a/drivers/tty/serial/pic32_uart.h b/drivers/tty/serial/pic32_uart.h index 2f2b56927dc6..b15639cc336b 100644 --- a/drivers/tty/serial/pic32_uart.h +++ b/drivers/tty/serial/pic32_uart.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * PIC32 Integrated Serial Driver. * diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 0bd1684cabb3..6119090ce045 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -21,6 +21,7 @@ /* UART specific GENI registers */ #define SE_UART_LOOPBACK_CFG 0x22c +#define SE_UART_IO_MACRO_CTRL 0x240 #define SE_UART_TX_TRANS_CFG 0x25c #define SE_UART_TX_WORD_LEN 0x268 #define SE_UART_TX_STOP_BIT_LEN 0x26c @@ -95,6 +96,12 @@ #define CTS_RTS_SORTED BIT(1) #define RX_TX_CTS_RTS_SORTED (RX_TX_SORTED | CTS_RTS_SORTED) +/* UART pin swap value */ +#define DEFAULT_IO_MACRO_IO0_IO1_MASK GENMASK(3, 0) +#define IO_MACRO_IO0_SEL 0x3 +#define DEFAULT_IO_MACRO_IO2_IO3_MASK GENMASK(15, 4) +#define IO_MACRO_IO2_IO3_SWAP 0x4640 + #ifdef CONFIG_CONSOLE_POLL #define CONSOLE_RX_BYTES_PW 1 #else @@ -113,12 +120,14 @@ struct qcom_geni_serial_port { unsigned int baud; unsigned int tx_bytes_pw; unsigned int rx_bytes_pw; - u32 *rx_fifo; + void *rx_fifo; u32 loopback; bool brk; unsigned int tx_remaining; int wakeup_irq; + bool rx_tx_swap; + bool cts_rts_swap; }; static const struct uart_ops qcom_geni_console_pops; @@ -505,7 +514,6 @@ static int handle_rx_console(struct uart_port *uport, u32 bytes, bool drop) static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop) { - unsigned char *buf; struct tty_port *tport; struct qcom_geni_serial_port *port = to_dev_port(uport, uport); u32 num_bytes_pw = port->tx_fifo_width / BITS_PER_BYTE; @@ -517,8 +525,7 @@ static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop) if (drop) return 0; - buf = (unsigned char *)port->rx_fifo; - ret = tty_insert_flip_string(tport, buf, bytes); + ret = tty_insert_flip_string(tport, port->rx_fifo, bytes); if (ret != bytes) { dev_err(uport->dev, "%s:Unable to push data ret %d_bytes %d\n", __func__, ret, bytes); @@ -818,17 +825,7 @@ static void get_tx_fifo_size(struct qcom_geni_serial_port *port) static void qcom_geni_serial_shutdown(struct uart_port *uport) { - unsigned long flags; - - /* Stop the console before stopping the current tx */ - if (uart_console(uport)) - console_stop(uport->cons); - disable_irq(uport->irq); - spin_lock_irqsave(&uport->lock, flags); - qcom_geni_serial_stop_tx(uport); - qcom_geni_serial_stop_rx(uport); - spin_unlock_irqrestore(&uport->lock, flags); } static int qcom_geni_serial_port_setup(struct uart_port *uport) @@ -836,6 +833,7 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) struct qcom_geni_serial_port *port = to_dev_port(uport, uport); u32 rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; u32 proto; + u32 pin_swap; if (uart_console(uport)) { port->tx_bytes_pw = 1; @@ -856,6 +854,20 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) get_tx_fifo_size(port); writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT); + + pin_swap = readl(uport->membase + SE_UART_IO_MACRO_CTRL); + if (port->rx_tx_swap) { + pin_swap &= ~DEFAULT_IO_MACRO_IO2_IO3_MASK; + pin_swap |= IO_MACRO_IO2_IO3_SWAP; + } + if (port->cts_rts_swap) { + pin_swap &= ~DEFAULT_IO_MACRO_IO0_IO1_MASK; + pin_swap |= IO_MACRO_IO0_SEL; + } + /* Configure this register if RX-TX, CTS-RTS pins are swapped */ + if (port->rx_tx_swap || port->cts_rts_swap) + writel(pin_swap, uport->membase + SE_UART_IO_MACRO_CTRL); + /* * Make an unconditional cancel on the main sequencer to reset * it else we could end up in data loss scenarios. @@ -868,12 +880,6 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) false, false, true); geni_se_init(&port->se, UART_RX_WM, port->rx_fifo_depth - 2); geni_se_select_mode(&port->se, GENI_SE_FIFO); - if (!uart_console(uport)) { - port->rx_fifo = devm_kcalloc(uport->dev, - port->rx_fifo_depth, sizeof(u32), GFP_KERNEL); - if (!port->rx_fifo) - return -ENOMEM; - } port->setup = true; return 0; @@ -1284,6 +1290,13 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS; port->tx_fifo_width = DEF_FIFO_WIDTH_BITS; + if (!console) { + port->rx_fifo = devm_kcalloc(uport->dev, + port->rx_fifo_depth, sizeof(u32), GFP_KERNEL); + if (!port->rx_fifo) + return -ENOMEM; + } + port->name = devm_kasprintf(uport->dev, GFP_KERNEL, "qcom_geni_serial_%s%d", uart_console(uport) ? "console" : "uart", uport->line); @@ -1299,6 +1312,12 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) if (!console) port->wakeup_irq = platform_get_irq_optional(pdev, 1); + if (of_property_read_bool(pdev->dev.of_node, "rx-tx-swap")) + port->rx_tx_swap = true; + + if (of_property_read_bool(pdev->dev.of_node, "cts-rts-swap")) + port->cts_rts_swap = true; + uport->private_data = drv; platform_set_drvdata(pdev, port); port->handle_rx = console ? handle_rx_console : handle_rx_uart; diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 7d3ae31cc720..06e8071d5601 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -329,7 +329,7 @@ struct sc16is7xx_port { struct task_struct *kworker_task; struct kthread_work irq_work; struct mutex efr_lock; - struct sc16is7xx_one p[0]; + struct sc16is7xx_one p[]; }; static unsigned long sc16is7xx_lines; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 76e506ee335c..66a5e2faf57e 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -20,6 +20,7 @@ #include <linux/device.h> #include <linux/serial.h> /* for serial_state and serial_icounter_struct */ #include <linux/serial_core.h> +#include <linux/sysrq.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/security.h> @@ -40,6 +41,8 @@ static struct lock_class_key port_lock_key; #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) +#define SYSRQ_TIMEOUT (HZ * 5) + static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, struct ktermios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); @@ -1908,6 +1911,24 @@ static int uart_proc_show(struct seq_file *m, void *v) } #endif +static inline bool uart_console_enabled(struct uart_port *port) +{ + return uart_console(port) && (port->cons->flags & CON_ENABLED); +} + +/* + * Ensure that the serial console lock is initialised early. + * If this port is a console, then the spinlock is already initialised. + */ +static inline void uart_port_spin_lock_init(struct uart_port *port) +{ + if (uart_console(port)) + return; + + spin_lock_init(&port->lock); + lockdep_set_class(&port->lock, &port_lock_key); +} + #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL) /** * uart_console_write - write a console message to a serial port @@ -2060,16 +2081,7 @@ uart_set_options(struct uart_port *port, struct console *co, struct ktermios termios; static struct ktermios dummy; - /* - * Ensure that the serial console lock is initialised - * early. - * If this port is a console, then the spinlock is already - * initialised. - */ - if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) { - spin_lock_init(&port->lock); - lockdep_set_class(&port->lock, &port_lock_key); - } + uart_port_spin_lock_init(port); memset(&termios, 0, sizeof(struct ktermios)); @@ -2605,7 +2617,7 @@ struct tty_driver *uart_console_device(struct console *co, int *index) } EXPORT_SYMBOL_GPL(uart_console_device); -static ssize_t uart_get_attr_uartclk(struct device *dev, +static ssize_t uartclk_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2615,7 +2627,7 @@ static ssize_t uart_get_attr_uartclk(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", tmp.baud_base * 16); } -static ssize_t uart_get_attr_type(struct device *dev, +static ssize_t type_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2624,7 +2636,8 @@ static ssize_t uart_get_attr_type(struct device *dev, uart_get_info(port, &tmp); return snprintf(buf, PAGE_SIZE, "%d\n", tmp.type); } -static ssize_t uart_get_attr_line(struct device *dev, + +static ssize_t line_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2634,7 +2647,7 @@ static ssize_t uart_get_attr_line(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", tmp.line); } -static ssize_t uart_get_attr_port(struct device *dev, +static ssize_t port_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2648,7 +2661,7 @@ static ssize_t uart_get_attr_port(struct device *dev, return snprintf(buf, PAGE_SIZE, "0x%lX\n", ioaddr); } -static ssize_t uart_get_attr_irq(struct device *dev, +static ssize_t irq_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2658,7 +2671,7 @@ static ssize_t uart_get_attr_irq(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", tmp.irq); } -static ssize_t uart_get_attr_flags(struct device *dev, +static ssize_t flags_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2668,7 +2681,7 @@ static ssize_t uart_get_attr_flags(struct device *dev, return snprintf(buf, PAGE_SIZE, "0x%X\n", tmp.flags); } -static ssize_t uart_get_attr_xmit_fifo_size(struct device *dev, +static ssize_t xmit_fifo_size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2678,8 +2691,7 @@ static ssize_t uart_get_attr_xmit_fifo_size(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", tmp.xmit_fifo_size); } - -static ssize_t uart_get_attr_close_delay(struct device *dev, +static ssize_t close_delay_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2689,8 +2701,7 @@ static ssize_t uart_get_attr_close_delay(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", tmp.close_delay); } - -static ssize_t uart_get_attr_closing_wait(struct device *dev, +static ssize_t closing_wait_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2700,7 +2711,7 @@ static ssize_t uart_get_attr_closing_wait(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", tmp.closing_wait); } -static ssize_t uart_get_attr_custom_divisor(struct device *dev, +static ssize_t custom_divisor_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2710,7 +2721,7 @@ static ssize_t uart_get_attr_custom_divisor(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", tmp.custom_divisor); } -static ssize_t uart_get_attr_io_type(struct device *dev, +static ssize_t io_type_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2720,7 +2731,7 @@ static ssize_t uart_get_attr_io_type(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", tmp.io_type); } -static ssize_t uart_get_attr_iomem_base(struct device *dev, +static ssize_t iomem_base_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2730,7 +2741,7 @@ static ssize_t uart_get_attr_iomem_base(struct device *dev, return snprintf(buf, PAGE_SIZE, "0x%lX\n", (unsigned long)tmp.iomem_base); } -static ssize_t uart_get_attr_iomem_reg_shift(struct device *dev, +static ssize_t iomem_reg_shift_show(struct device *dev, struct device_attribute *attr, char *buf) { struct serial_struct tmp; @@ -2740,40 +2751,92 @@ static ssize_t uart_get_attr_iomem_reg_shift(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift); } -static DEVICE_ATTR(type, S_IRUSR | S_IRGRP, uart_get_attr_type, NULL); -static DEVICE_ATTR(line, S_IRUSR | S_IRGRP, uart_get_attr_line, NULL); -static DEVICE_ATTR(port, S_IRUSR | S_IRGRP, uart_get_attr_port, NULL); -static DEVICE_ATTR(irq, S_IRUSR | S_IRGRP, uart_get_attr_irq, NULL); -static DEVICE_ATTR(flags, S_IRUSR | S_IRGRP, uart_get_attr_flags, NULL); -static DEVICE_ATTR(xmit_fifo_size, S_IRUSR | S_IRGRP, uart_get_attr_xmit_fifo_size, NULL); -static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL); -static DEVICE_ATTR(close_delay, S_IRUSR | S_IRGRP, uart_get_attr_close_delay, NULL); -static DEVICE_ATTR(closing_wait, S_IRUSR | S_IRGRP, uart_get_attr_closing_wait, NULL); -static DEVICE_ATTR(custom_divisor, S_IRUSR | S_IRGRP, uart_get_attr_custom_divisor, NULL); -static DEVICE_ATTR(io_type, S_IRUSR | S_IRGRP, uart_get_attr_io_type, NULL); -static DEVICE_ATTR(iomem_base, S_IRUSR | S_IRGRP, uart_get_attr_iomem_base, NULL); -static DEVICE_ATTR(iomem_reg_shift, S_IRUSR | S_IRGRP, uart_get_attr_iomem_reg_shift, NULL); +static ssize_t console_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tty_port *port = dev_get_drvdata(dev); + struct uart_state *state = container_of(port, struct uart_state, port); + struct uart_port *uport; + bool console = false; + + mutex_lock(&port->mutex); + uport = uart_port_check(state); + if (uport) + console = uart_console_enabled(uport); + mutex_unlock(&port->mutex); + + return sprintf(buf, "%c\n", console ? 'Y' : 'N'); +} + +static ssize_t console_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct tty_port *port = dev_get_drvdata(dev); + struct uart_state *state = container_of(port, struct uart_state, port); + struct uart_port *uport; + bool oldconsole, newconsole; + int ret; + + ret = kstrtobool(buf, &newconsole); + if (ret) + return ret; + + mutex_lock(&port->mutex); + uport = uart_port_check(state); + if (uport) { + oldconsole = uart_console_enabled(uport); + if (oldconsole && !newconsole) { + ret = unregister_console(uport->cons); + } else if (!oldconsole && newconsole) { + if (uart_console(uport)) + register_console(uport->cons); + else + ret = -ENOENT; + } + } else { + ret = -ENXIO; + } + mutex_unlock(&port->mutex); + + return ret < 0 ? ret : count; +} + +static DEVICE_ATTR_RO(uartclk); +static DEVICE_ATTR_RO(type); +static DEVICE_ATTR_RO(line); +static DEVICE_ATTR_RO(port); +static DEVICE_ATTR_RO(irq); +static DEVICE_ATTR_RO(flags); +static DEVICE_ATTR_RO(xmit_fifo_size); +static DEVICE_ATTR_RO(close_delay); +static DEVICE_ATTR_RO(closing_wait); +static DEVICE_ATTR_RO(custom_divisor); +static DEVICE_ATTR_RO(io_type); +static DEVICE_ATTR_RO(iomem_base); +static DEVICE_ATTR_RO(iomem_reg_shift); +static DEVICE_ATTR_RW(console); static struct attribute *tty_dev_attrs[] = { + &dev_attr_uartclk.attr, &dev_attr_type.attr, &dev_attr_line.attr, &dev_attr_port.attr, &dev_attr_irq.attr, &dev_attr_flags.attr, &dev_attr_xmit_fifo_size.attr, - &dev_attr_uartclk.attr, &dev_attr_close_delay.attr, &dev_attr_closing_wait.attr, &dev_attr_custom_divisor.attr, &dev_attr_io_type.attr, &dev_attr_iomem_base.attr, &dev_attr_iomem_reg_shift.attr, - NULL, - }; + &dev_attr_console.attr, + NULL +}; static const struct attribute_group tty_dev_attr_group = { .attrs = tty_dev_attrs, - }; +}; /** * uart_add_one_port - attach a driver-defined port structure @@ -2824,14 +2887,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) goto out; } - /* - * If this port is a console, then the spinlock is already - * initialised. - */ - if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) { - spin_lock_init(&uport->lock); - lockdep_set_class(&uport->lock, &port_lock_key); - } + uart_port_spin_lock_init(uport); + if (uport->cons && uport->dev) of_console_check(uport->dev->of_node, uport->cons->name, uport->line); @@ -3082,6 +3139,60 @@ void uart_insert_char(struct uart_port *port, unsigned int status, } EXPORT_SYMBOL_GPL(uart_insert_char); +#ifdef CONFIG_MAGIC_SYSRQ_SERIAL +static const char sysrq_toggle_seq[] = CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE; + +static void uart_sysrq_on(struct work_struct *w) +{ + int sysrq_toggle_seq_len = strlen(sysrq_toggle_seq); + + sysrq_toggle_support(1); + pr_info("SysRq is enabled by magic sequence '%*pE' on serial\n", + sysrq_toggle_seq_len, sysrq_toggle_seq); +} +static DECLARE_WORK(sysrq_enable_work, uart_sysrq_on); + +/** + * uart_try_toggle_sysrq - Enables SysRq from serial line + * @port: uart_port structure where char(s) after BREAK met + * @ch: new character in the sequence after received BREAK + * + * Enables magic SysRq when the required sequence is met on port + * (see CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE). + * + * Returns false if @ch is out of enabling sequence and should be + * handled some other way, true if @ch was consumed. + */ +static bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch) +{ + int sysrq_toggle_seq_len = strlen(sysrq_toggle_seq); + + if (!sysrq_toggle_seq_len) + return false; + + BUILD_BUG_ON(ARRAY_SIZE(sysrq_toggle_seq) >= U8_MAX); + if (sysrq_toggle_seq[port->sysrq_seq] != ch) { + port->sysrq_seq = 0; + return false; + } + + if (++port->sysrq_seq < sysrq_toggle_seq_len) { + port->sysrq = jiffies + SYSRQ_TIMEOUT; + return true; + } + + schedule_work(&sysrq_enable_work); + + port->sysrq = 0; + return true; +} +#else +static inline bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch) +{ + return false; +} +#endif + int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) { if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) @@ -3091,9 +3202,13 @@ int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) return 0; if (ch && time_before(jiffies, port->sysrq)) { - handle_sysrq(ch); - port->sysrq = 0; - return 1; + if (sysrq_mask()) { + handle_sysrq(ch); + port->sysrq = 0; + return 1; + } + if (uart_try_toggle_sysrq(port, ch)) + return 1; } port->sysrq = 0; @@ -3110,9 +3225,13 @@ int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch) return 0; if (ch && time_before(jiffies, port->sysrq)) { - port->sysrq_ch = ch; - port->sysrq = 0; - return 1; + if (sysrq_mask()) { + port->sysrq_ch = ch; + port->sysrq = 0; + return 1; + } + if (uart_try_toggle_sysrq(port, ch)) + return 1; } port->sysrq = 0; @@ -3120,22 +3239,19 @@ int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch) } EXPORT_SYMBOL_GPL(uart_prepare_sysrq_char); -void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) +void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long flags) +__releases(&port->lock) { - int sysrq_ch; + if (port->has_sysrq) { + int sysrq_ch = port->sysrq_ch; - if (!port->has_sysrq) { - spin_unlock_irqrestore(&port->lock, irqflags); - return; + port->sysrq_ch = 0; + spin_unlock_irqrestore(&port->lock, flags); + if (sysrq_ch) + handle_sysrq(sysrq_ch); + } else { + spin_unlock_irqrestore(&port->lock, flags); } - - sysrq_ch = port->sysrq_ch; - port->sysrq_ch = 0; - - spin_unlock_irqrestore(&port->lock, irqflags); - - if (sysrq_ch) - handle_sysrq(sysrq_ch); } EXPORT_SYMBOL_GPL(uart_unlock_and_check_sysrq); @@ -3149,14 +3265,12 @@ int uart_handle_break(struct uart_port *port) if (port->handle_break) port->handle_break(port); - if (port->has_sysrq) { - if (port->cons && port->cons->index == port->line) { - if (!port->sysrq) { - port->sysrq = jiffies + HZ*5; - return 1; - } - port->sysrq = 0; + if (port->has_sysrq && uart_console(port)) { + if (!port->sysrq) { + port->sysrq = jiffies + SYSRQ_TIMEOUT; + return 1; } + port->sysrq = 0; } if (port->flags & UPF_SAK) diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h index 1b2ff503b2c2..b134a0ffc894 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.h +++ b/drivers/tty/serial/serial_mctrl_gpio.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Helpers for controlling modem lines via GPIO * diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c index d5f81b98e4d7..13eadcb8aec4 100644 --- a/drivers/tty/serial/sifive.c +++ b/drivers/tty/serial/sifive.c @@ -618,10 +618,10 @@ static void sifive_serial_shutdown(struct uart_port *port) * * On the V0 SoC, the UART IP block is derived from the CPU clock source * after a synchronous divide-by-two divider, so any CPU clock rate change - * requires the UART baud rate to be updated. This presumably could corrupt any - * serial word currently being transmitted or received. It would probably - * be better to stop receives and transmits, then complete the baud rate - * change, then re-enable them. + * requires the UART baud rate to be updated. This presumably corrupts any + * serial word currently being transmitted or received. In order to avoid + * corrupting the output data stream, we drain the transmit queue before + * allowing the clock's rate to be changed. */ static int sifive_serial_clk_notifier(struct notifier_block *nb, unsigned long event, void *data) @@ -629,6 +629,26 @@ static int sifive_serial_clk_notifier(struct notifier_block *nb, struct clk_notifier_data *cnd = data; struct sifive_serial_port *ssp = notifier_to_sifive_serial_port(nb); + if (event == PRE_RATE_CHANGE) { + /* + * The TX watermark is always set to 1 by this driver, which + * means that the TX busy bit will lower when there are 0 bytes + * left in the TX queue -- in other words, when the TX FIFO is + * empty. + */ + __ssp_wait_for_xmitr(ssp); + /* + * On the cycle the TX FIFO goes empty there is still a full + * UART frame left to be transmitted in the shift register. + * The UART provides no way for software to directly determine + * when that last frame has been transmitted, so we just sleep + * here instead. As we're not tracking the number of stop bits + * they're just worst cased here. The rest of the serial + * framing parameters aren't configurable by software. + */ + udelay(DIV_ROUND_UP(12 * 1000 * 1000, ssp->baud_rate)); + } + if (event == POST_RATE_CHANGE && ssp->clkin_rate != cnd->new_rate) { ssp->clkin_rate = cnd->new_rate; __ssp_update_div(ssp); @@ -709,6 +729,29 @@ static const char *sifive_serial_type(struct uart_port *port) return port->type == PORT_SIFIVE_V0 ? "SiFive UART v0" : NULL; } +#ifdef CONFIG_CONSOLE_POLL +static int sifive_serial_poll_get_char(struct uart_port *port) +{ + struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); + char is_empty, ch; + + ch = __ssp_receive_char(ssp, &is_empty); + if (is_empty) + return NO_POLL_CHAR; + + return ch; +} + +static void sifive_serial_poll_put_char(struct uart_port *port, + unsigned char c) +{ + struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); + + __ssp_wait_for_xmitr(ssp); + __ssp_transmit_char(ssp, c); +} +#endif /* CONFIG_CONSOLE_POLL */ + /* * Early console support */ @@ -877,6 +920,10 @@ static const struct uart_ops sifive_serial_uops = { .request_port = sifive_serial_request_port, .config_port = sifive_serial_config_port, .verify_port = sifive_serial_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = sifive_serial_poll_get_char, + .poll_put_char = sifive_serial_poll_put_char, +#endif }; static struct uart_driver sifive_serial_uart_driver = { diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h index 637b09d3fe79..fb88ac565227 100644 --- a/drivers/tty/serial/sirfsoc_uart.h +++ b/drivers/tty/serial/sirfsoc_uart.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Drivers for CSR SiRFprimaII onboard UARTs. * diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index 3d3c70634589..9a7ae6384edf 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -1013,7 +1013,7 @@ static void sprd_console_write(struct console *co, const char *s, spin_unlock_irqrestore(&port->lock, flags); } -static int __init sprd_console_setup(struct console *co, char *options) +static int sprd_console_setup(struct console *co, char *options) { struct sprd_uart_port *sprd_uart_port; int baud = 115200; @@ -1102,29 +1102,6 @@ static struct uart_driver sprd_uart_driver = { .cons = SPRD_CONSOLE, }; -static int sprd_probe_dt_alias(int index, struct device *dev) -{ - struct device_node *np; - int ret = index; - - if (!IS_ENABLED(CONFIG_OF)) - return ret; - - np = dev->of_node; - if (!np) - return ret; - - ret = of_alias_get_id(np, "serial"); - if (ret < 0) - ret = index; - else if (ret >= ARRAY_SIZE(sprd_port) || sprd_port[ret] != NULL) { - dev_warn(dev, "requested serial port %d not available.\n", ret); - ret = index; - } - - return ret; -} - static int sprd_remove(struct platform_device *dev) { struct sprd_uart_port *sup = platform_get_drvdata(dev); @@ -1132,14 +1109,13 @@ static int sprd_remove(struct platform_device *dev) if (sup) { uart_remove_one_port(&sprd_uart_driver, &sup->port); sprd_port[sup->port.line] = NULL; + sprd_rx_free_buf(sup); sprd_ports_num--; } if (!sprd_ports_num) uart_unregister_driver(&sprd_uart_driver); - sprd_rx_free_buf(sup); - return 0; } @@ -1147,7 +1123,8 @@ static bool sprd_uart_is_console(struct uart_port *uport) { struct console *cons = sprd_uart_driver.cons; - if (cons && cons->index >= 0 && cons->index == uport->line) + if ((cons && cons->index >= 0 && cons->index == uport->line) || + of_console_check(uport->dev->of_node, SPRD_TTY_NAME, uport->line)) return true; return false; @@ -1203,14 +1180,11 @@ static int sprd_probe(struct platform_device *pdev) int index; int ret; - for (index = 0; index < ARRAY_SIZE(sprd_port); index++) - if (sprd_port[index] == NULL) - break; - - if (index == ARRAY_SIZE(sprd_port)) - return -EBUSY; - - index = sprd_probe_dt_alias(index, &pdev->dev); + index = of_alias_get_id(pdev->dev.of_node, "serial"); + if (index < 0 || index >= ARRAY_SIZE(sprd_port)) { + dev_err(&pdev->dev, "got a wrong serial alias id %d\n", index); + return -EINVAL; + } sprd_port[index] = devm_kzalloc(&pdev->dev, sizeof(*sprd_port[index]), GFP_KERNEL); @@ -1262,10 +1236,8 @@ static int sprd_probe(struct platform_device *pdev) sprd_ports_num++; ret = uart_add_one_port(&sprd_uart_driver, up); - if (ret) { - sprd_port[index] = NULL; + if (ret) sprd_remove(pdev); - } platform_set_drvdata(pdev, up); diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h index a175c1094dc8..db8bf0d4982d 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) Maxime Coquelin 2015 * Copyright (C) STMicroelectronics SA 2017 diff --git a/drivers/tty/serial/timbuart.h b/drivers/tty/serial/timbuart.h index fb00b172117d..007e59af636d 100644 --- a/drivers/tty/serial/timbuart.h +++ b/drivers/tty/serial/timbuart.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * timbuart.c timberdale FPGA GPIO driver * Copyright (c) 2009 Intel Corporation diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 98db9dc168ff..6b26f767768e 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -650,8 +650,8 @@ static unsigned int cdns_uart_tx_empty(struct uart_port *port) unsigned int status; status = readl(port->membase + CDNS_UART_SR) & - CDNS_UART_SR_TXEMPTY; - return status ? TIOCSER_TEMT : 0; + (CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE); + return (status == CDNS_UART_SR_TXEMPTY) ? TIOCSER_TEMT : 0; } /** @@ -693,20 +693,8 @@ static void cdns_uart_set_termios(struct uart_port *port, u32 cval = 0; unsigned int baud, minbaud, maxbaud; unsigned long flags; - unsigned int ctrl_reg, mode_reg, val; - int err; - - /* Wait for the transmit FIFO to empty before making changes */ - if (!(readl(port->membase + CDNS_UART_CR) & - CDNS_UART_CR_TX_DIS)) { - err = readl_poll_timeout(port->membase + CDNS_UART_SR, - val, (val & CDNS_UART_SR_TXEMPTY), - 1000, TX_TIMEOUT); - if (err) { - dev_err(port->dev, "timed out waiting for tx empty"); - return; - } - } + unsigned int ctrl_reg, mode_reg; + spin_lock_irqsave(&port->lock, flags); /* Disable the TX and RX to set baud rate */ |