diff options
Diffstat (limited to 'drivers/tty/serial')
67 files changed, 1102 insertions, 908 deletions
diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c index 32b3acf8150a..718e010fcb04 100644 --- a/drivers/tty/serial/21285.c +++ b/drivers/tty/serial/21285.c @@ -41,8 +41,43 @@ static const char serial21285_name[] = "Footbridge UART"; -#define tx_enabled(port) ((port)->unused[0]) -#define rx_enabled(port) ((port)->unused[1]) +/* + * We only need 2 bits of data, so instead of creating a whole structure for + * this, use bits of the private_data pointer of the uart port structure. + */ +#define tx_enabled_bit 0 +#define rx_enabled_bit 1 + +static bool is_enabled(struct uart_port *port, int bit) +{ + unsigned long private_data = (unsigned long)port->private_data; + + if (test_bit(bit, &private_data)) + return true; + return false; +} + +static void enable(struct uart_port *port, int bit) +{ + unsigned long private_data = (unsigned long)port->private_data; + + set_bit(bit, &private_data); +} + +static void disable(struct uart_port *port, int bit) +{ + unsigned long private_data = (unsigned long)port->private_data; + + clear_bit(bit, &private_data); +} + +#define is_tx_enabled(port) is_enabled(port, tx_enabled_bit) +#define tx_enable(port) enable(port, tx_enabled_bit) +#define tx_disable(port) disable(port, tx_enabled_bit) + +#define is_rx_enabled(port) is_enabled(port, rx_enabled_bit) +#define rx_enable(port) enable(port, rx_enabled_bit) +#define rx_disable(port) disable(port, rx_enabled_bit) /* * The documented expression for selecting the divisor is: @@ -57,25 +92,25 @@ static const char serial21285_name[] = "Footbridge UART"; static void serial21285_stop_tx(struct uart_port *port) { - if (tx_enabled(port)) { + if (is_tx_enabled(port)) { disable_irq_nosync(IRQ_CONTX); - tx_enabled(port) = 0; + tx_disable(port); } } static void serial21285_start_tx(struct uart_port *port) { - if (!tx_enabled(port)) { + if (!is_tx_enabled(port)) { enable_irq(IRQ_CONTX); - tx_enabled(port) = 1; + tx_enable(port); } } static void serial21285_stop_rx(struct uart_port *port) { - if (rx_enabled(port)) { + if (is_rx_enabled(port)) { disable_irq_nosync(IRQ_CONRX); - rx_enabled(port) = 0; + rx_disable(port); } } @@ -185,8 +220,8 @@ static int serial21285_startup(struct uart_port *port) { int ret; - tx_enabled(port) = 1; - rx_enabled(port) = 1; + tx_enable(port); + rx_enable(port); ret = request_irq(IRQ_CONRX, serial21285_rx_chars, 0, serial21285_name, port); diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c index 6e67fd89445a..d657aa14c3e4 100644 --- a/drivers/tty/serial/8250/8250_aspeed_vuart.c +++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c @@ -5,10 +5,6 @@ * Copyright (C) 2016 Jeremy Kerr <jk@ozlabs.org>, IBM Corp. * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp. */ -#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/device.h> #include <linux/module.h> #include <linux/of_address.h> @@ -406,6 +402,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev) port.port.unthrottle = aspeed_vuart_unthrottle; port.port.status = UPSTAT_SYNC_FIFO; port.port.dev = &pdev->dev; + port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); if (rc < 0) diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index 8ce700c1a7fc..e70e3cc30050 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -16,14 +16,19 @@ #include "8250.h" +/** + * 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 + */ struct bcm2835aux_data { - struct uart_8250_port uart; struct clk *clk; int line; }; static int bcm2835aux_serial_probe(struct platform_device *pdev) { + struct uart_8250_port up = { }; struct bcm2835aux_data *data; struct resource *res; int ret; @@ -34,23 +39,21 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) return -ENOMEM; /* initialize data */ - spin_lock_init(&data->uart.port.lock); - data->uart.capabilities = UART_CAP_FIFO | UART_CAP_MINI; - data->uart.port.dev = &pdev->dev; - data->uart.port.regshift = 2; - data->uart.port.type = PORT_16550; - data->uart.port.iotype = UPIO_MEM; - data->uart.port.fifosize = 8; - data->uart.port.flags = UPF_SHARE_IRQ | - UPF_FIXED_PORT | - UPF_FIXED_TYPE | - UPF_SKIP_TEST; + up.capabilities = UART_CAP_FIFO | UART_CAP_MINI; + up.port.dev = &pdev->dev; + up.port.regshift = 2; + up.port.type = PORT_16550; + up.port.iotype = UPIO_MEM; + up.port.fifosize = 8; + up.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE | + UPF_SKIP_TEST | UPF_IOREMAP; /* get the clock - this also enables the HW */ data->clk = devm_clk_get(&pdev->dev, NULL); ret = PTR_ERR_OR_ZERO(data->clk); if (ret) { - dev_err(&pdev->dev, "could not get clk: %d\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "could not get clk: %d\n", ret); return ret; } @@ -58,7 +61,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) ret = platform_get_irq(pdev, 0); if (ret < 0) return ret; - data->uart.port.irq = ret; + up.port.irq = ret; /* map the main registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -66,15 +69,13 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) dev_err(&pdev->dev, "memory resource not found"); return -EINVAL; } - data->uart.port.membase = devm_ioremap_resource(&pdev->dev, res); - ret = PTR_ERR_OR_ZERO(data->uart.port.membase); - if (ret) - return ret; + up.port.mapbase = res->start; + up.port.mapsize = resource_size(res); /* Check for a fixed line number */ ret = of_alias_get_id(pdev->dev.of_node, "serial"); if (ret >= 0) - data->uart.port.line = ret; + up.port.line = ret; /* enable the clock as a last step */ ret = clk_prepare_enable(data->clk); @@ -89,13 +90,14 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) * so we have to multiply the actual clock by 2 * to get identical baudrates. */ - data->uart.port.uartclk = clk_get_rate(data->clk) * 2; + up.port.uartclk = clk_get_rate(data->clk) * 2; /* register the port */ - ret = serial8250_register_8250_port(&data->uart); + ret = serial8250_register_8250_port(&up); if (ret < 0) { - dev_err(&pdev->dev, "unable to register 8250 port - %d\n", - ret); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "unable to register 8250 port - %d\n", ret); goto dis_clk; } data->line = ret; @@ -113,7 +115,7 @@ static int bcm2835aux_serial_remove(struct platform_device *pdev) { struct bcm2835aux_data *data = platform_get_drvdata(pdev); - serial8250_unregister_port(data->uart.port.line); + serial8250_unregister_port(data->line); clk_disable_unprepare(data->clk); return 0; diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index e682390ce0de..0894a22fd702 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -816,6 +816,7 @@ static int serial8250_probe(struct platform_device *dev) uart.port.flags = p->flags; uart.port.mapbase = p->mapbase; uart.port.hub6 = p->hub6; + uart.port.has_sysrq = p->has_sysrq; uart.port.private_data = p->private_data; uart.port.type = p->type; uart.port.serial_in = p->serial_in; diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 108cd55f9c4d..91e9b070d36d 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -186,7 +186,7 @@ static int xr17v35x_startup(struct uart_port *port) static void exar_shutdown(struct uart_port *port) { unsigned char lsr; - bool tx_complete = 0; + bool tx_complete = false; struct uart_8250_port *up = up_to_u8250p(port); struct circ_buf *xmit = &port->state->xmit; int i = 0; @@ -194,9 +194,9 @@ static void exar_shutdown(struct uart_port *port) do { lsr = serial_in(up, UART_LSR); if (lsr & (UART_LSR_TEMT | UART_LSR_THRE)) - tx_complete = 1; + tx_complete = true; else - tx_complete = 0; + tx_complete = false; usleep_range(1000, 1100); } while (!uart_circ_empty(xmit) && !tx_complete && i++ < 1000); diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c index aa0e216d5ead..0d0c80905c58 100644 --- a/drivers/tty/serial/8250/8250_fsl.c +++ b/drivers/tty/serial/8250/8250_fsl.c @@ -1,8 +1,4 @@ // SPDX-License-Identifier: GPL-2.0 -#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/serial_reg.h> #include <linux/serial_8250.h> diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c index 0809ae2aa9b1..673cda3d011d 100644 --- a/drivers/tty/serial/8250/8250_gsc.c +++ b/drivers/tty/serial/8250/8250_gsc.c @@ -55,7 +55,7 @@ static int __init serial_init_chip(struct parisc_device *dev) uart.port.uartclk = (dev->id.sversion != 0xad) ? 7272727 : 1843200; uart.port.mapbase = address; - uart.port.membase = ioremap_nocache(address, 16); + uart.port.membase = ioremap(address, 16); if (!uart.port.membase) { dev_warn(&dev->dev, "Failed to map memory\n"); return -ENOMEM; diff --git a/drivers/tty/serial/8250/8250_ioc3.c b/drivers/tty/serial/8250/8250_ioc3.c new file mode 100644 index 000000000000..d5a39e105a76 --- /dev/null +++ b/drivers/tty/serial/8250/8250_ioc3.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SGI IOC3 8250 UART driver + * + * Copyright (C) 2019 Thomas Bogendoerfer <tbogendoerfer@suse.de> + * + * based on code Copyright (C) 2005 Stanislaw Skowronek <skylark@unaligned.org> + * Copyright (C) 2014 Joshua Kinard <kumba@gentoo.org> + */ + +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/platform_device.h> + +#include "8250.h" + +#define IOC3_UARTCLK (22000000 / 3) + +struct ioc3_8250_data { + int line; +}; + +static unsigned int ioc3_serial_in(struct uart_port *p, int offset) +{ + return readb(p->membase + (offset ^ 3)); +} + +static void ioc3_serial_out(struct uart_port *p, int offset, int value) +{ + writeb(value, p->membase + (offset ^ 3)); +} + +static int serial8250_ioc3_probe(struct platform_device *pdev) +{ + struct ioc3_8250_data *data; + struct uart_8250_port up; + struct resource *r; + void __iomem *membase; + int irq, line; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) + return -ENODEV; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + membase = devm_ioremap(&pdev->dev, r->start, resource_size(r)); + if (!membase) + return -ENOMEM; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + irq = 0; /* no interrupt -> use polling */ + + /* Register serial ports with 8250.c */ + memset(&up, 0, sizeof(struct uart_8250_port)); + up.port.iotype = UPIO_MEM; + up.port.uartclk = IOC3_UARTCLK; + up.port.type = PORT_16550A; + up.port.irq = irq; + up.port.flags = (UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ); + up.port.dev = &pdev->dev; + up.port.membase = membase; + up.port.mapbase = r->start; + up.port.serial_in = ioc3_serial_in; + up.port.serial_out = ioc3_serial_out; + line = serial8250_register_8250_port(&up); + if (line < 0) + return line; + + platform_set_drvdata(pdev, data); + return 0; +} + +static int serial8250_ioc3_remove(struct platform_device *pdev) +{ + struct ioc3_8250_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->line); + return 0; +} + +static struct platform_driver serial8250_ioc3_driver = { + .probe = serial8250_ioc3_probe, + .remove = serial8250_ioc3_remove, + .driver = { + .name = "ioc3-serial8250", + } +}; + +module_platform_driver(serial8250_ioc3_driver); + +MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfer@suse.de>"); +MODULE_DESCRIPTION("SGI IOC3 8250 UART driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 92fbf46ce3bd..531ad67395e0 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -222,8 +222,10 @@ static int of_platform_serial_setup(struct platform_device *ofdev, if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) && (of_device_is_compatible(np, "fsl,ns16550") || - of_device_is_compatible(np, "fsl,16550-FIFO64"))) + of_device_is_compatible(np, "fsl,16550-FIFO64"))) { port->handle_irq = fsl8250_handle_irq; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); + } return 0; err_unprepare: diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 836e736ae188..6f343ca08440 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -8,10 +8,6 @@ * */ -#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/clk.h> #include <linux/device.h> #include <linux/io.h> @@ -1147,7 +1143,7 @@ static int omap8250_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - membase = devm_ioremap_nocache(&pdev->dev, regs->start, + membase = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); if (!membase) return -ENODEV; @@ -1192,6 +1188,7 @@ static int omap8250_probe(struct platform_device *pdev) up.port.throttle = omap_8250_throttle; up.port.unthrottle = omap_8250_unthrottle; up.port.rs485_config = omap_8250_rs485_config; + up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); ret = of_alias_get_id(np, "serial"); if (ret < 0) { diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 022924d5ad54..939685fed396 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -275,7 +275,7 @@ static int pci_plx9050_init(struct pci_dev *dev) /* * enable/disable interrupts */ - p = ioremap_nocache(pci_resource_start(dev, 0), 0x80); + p = ioremap(pci_resource_start(dev, 0), 0x80); if (p == NULL) return -ENOMEM; writel(irq_config, p + 0x4c); @@ -299,7 +299,7 @@ static void pci_plx9050_exit(struct pci_dev *dev) /* * disable interrupts */ - p = ioremap_nocache(pci_resource_start(dev, 0), 0x80); + p = ioremap(pci_resource_start(dev, 0), 0x80); if (p != NULL) { writel(0, p + 0x4c); @@ -475,7 +475,7 @@ static int pci_siig10x_init(struct pci_dev *dev) break; } - p = ioremap_nocache(pci_resource_start(dev, 0), 0x80); + p = ioremap(pci_resource_start(dev, 0), 0x80); if (p == NULL) return -ENOMEM; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 90655910b0c7..430e3467aff7 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -11,10 +11,6 @@ * membase is an 'ioremapped' cookie. */ -#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/ioport.h> @@ -1001,6 +997,9 @@ static void autoconfig_16550a(struct uart_8250_port *up) up->port.type = PORT_16550A; up->capabilities |= UART_CAP_FIFO; + if (!IS_ENABLED(CONFIG_SERIAL_8250_16550A_VARIANTS)) + return; + /* * Check for presence of the EFR when DLAB is set. * Only ST16C650V1 UARTs pass this test. @@ -2766,7 +2765,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) } if (port->flags & UPF_IOREMAP) { - port->membase = ioremap_nocache(port->mapbase, size); + port->membase = ioremap(port->mapbase, size); if (!port->membase) { release_mem_region(port->mapbase, size); ret = -ENOMEM; @@ -3055,6 +3054,7 @@ void serial8250_init_port(struct uart_8250_port *up) spin_lock_init(&port->lock); port->ops = &serial8250_pops; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); up->cur_iotype = 0xFF; } diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index fab3d4f20667..f16824bbb573 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -60,6 +60,16 @@ config SERIAL_8250_PNP This builds standard PNP serial support. You may be able to disable this feature if you only need legacy serial support. +config SERIAL_8250_16550A_VARIANTS + bool "Support for variants of the 16550A serial port" + depends on SERIAL_8250 + help + The 8250 driver can probe for many variants of the venerable 16550A + serial port. Doing so takes additional time at boot. + + On modern systems, especially those using serial only for a simple + console, you can say N here. + config SERIAL_8250_FINTEK bool "Support for Fintek F81216A LPC to 4 UART RS485 API" depends on SERIAL_8250 @@ -371,6 +381,17 @@ config SERIAL_8250_EM port hardware found on the Emma Mobile line of processors. If unsure, say N. +config SERIAL_8250_IOC3 + tristate "SGI IOC3 8250 UART support" + depends on SGI_MFD_IOC3 && SERIAL_8250 + select SERIAL_8250_EXTENDED + select SERIAL_8250_SHARE_IRQ + help + Enable this if you have a SGI Origin or Octane machine. This module + provides basic serial support by directly driving the UART chip + behind the IOC3 device on those systems. Maximum baud speed is + 38400bps using this driver. + config SERIAL_8250_RT288X bool "Ralink RT288x/RT305x/RT3662/RT3883 serial port support" depends on SERIAL_8250 diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 08c1d8117506..51a6079d3f1f 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o obj-$(CONFIG_SERIAL_8250_MEN_MCB) += 8250_men_mcb.o obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o +obj-$(CONFIG_SERIAL_8250_IOC3) += 8250_ioc3.o obj-$(CONFIG_SERIAL_8250_OMAP) += 8250_omap.o obj-$(CONFIG_SERIAL_8250_LPC18XX) += 8250_lpc18xx.o obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 99f5da3bf913..52eaac21ff9f 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -237,7 +237,7 @@ config SERIAL_CLPS711X_CONSOLE config SERIAL_SAMSUNG tristate "Samsung SoC serial support" - depends on PLAT_SAMSUNG || ARCH_EXYNOS + depends on PLAT_SAMSUNG || ARCH_EXYNOS || COMPILE_TEST select SERIAL_CORE help Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, @@ -975,7 +975,7 @@ config SERIAL_QCOM_GENI config SERIAL_QCOM_GENI_CONSOLE bool "QCOM GENI Serial Console support" - depends on SERIAL_QCOM_GENI=y + depends on SERIAL_QCOM_GENI select SERIAL_CORE_CONSOLE select SERIAL_EARLYCON help diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index 2c37d11726ab..3284f34e9dfe 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -15,10 +15,6 @@ * and hooked into this driver. */ -#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/ioport.h> #include <linux/init.h> @@ -728,6 +724,7 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id) uap->port.iotype = UPIO_MEM; uap->port.irq = dev->irq[0]; uap->port.fifosize = 16; + uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL010_CONSOLE); uap->port.ops = &amba_pl010_pops; uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.line = i; diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 4b28134d596a..2296bb0f9578 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -16,11 +16,6 @@ * and hooked into this driver. */ - -#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/ioport.h> #include <linux/init.h> @@ -1452,8 +1447,6 @@ static void pl011_modem_status(struct uart_amba_port *uap) static void check_apply_cts_event_workaround(struct uart_amba_port *uap) { - unsigned int dummy_read; - if (!uap->vendor->cts_event_workaround) return; @@ -1465,8 +1458,8 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap) * single apb access will incur 2 pclk(133.12Mhz) delay, * so add 2 dummy reads */ - dummy_read = pl011_read(uap, REG_ICR); - dummy_read = pl011_read(uap, REG_ICR); + pl011_read(uap, REG_ICR); + pl011_read(uap, REG_ICR); } static irqreturn_t pl011_int(int irq, void *dev_id) @@ -2579,6 +2572,7 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, uap->port.mapbase = mmiobase->start; uap->port.membase = base; uap->port.fifosize = uap->fifosize; + uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE); uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.line = index; @@ -2769,6 +2763,7 @@ static struct platform_driver arm_sbsa_uart_platform_driver = { .remove = sbsa_uart_remove, .driver = { .name = "sbsa-uart", + .pm = &pl011_dev_pm_ops, .of_match_table = of_match_ptr(sbsa_uart_of_match), .acpi_match_table = ACPI_PTR(sbsa_uart_acpi_match), .suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_AMBA_PL011), diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c index 60cd133ffbbc..e8d56e899ec7 100644 --- a/drivers/tty/serial/apbuart.c +++ b/drivers/tty/serial/apbuart.c @@ -11,10 +11,6 @@ * Copyright (C) 2009 Kristoffer Glembo <kristoffer@gaisler.com>, Aeroflex Gaisler AB */ -#if defined(CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/tty.h> #include <linux/tty_flip.h> @@ -626,6 +622,7 @@ static int __init grlib_apbuart_configure(void) port->irq = 0; port->iotype = UPIO_MEM; port->ops = &grlib_apbuart_ops; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE); port->flags = UPF_BOOT_AUTOCONF; port->line = line; port->uartclk = *freq_hz; diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index d904a3a345e7..17c3fc398fc6 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -21,10 +21,6 @@ * -check if sysreq works */ -#if defined(CONFIG_SERIAL_ARC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/serial.h> #include <linux/console.h> @@ -625,6 +621,7 @@ static int arc_serial_probe(struct platform_device *pdev) port->flags = UPF_BOOT_AUTOCONF; port->line = dev_id; port->ops = &arc_serial_pops; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_ARC_CONSOLE); port->fifosize = ARC_UART_TX_FIFO_SIZE; diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index a8dc8af83f39..c15c398c88a9 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -51,10 +51,6 @@ #define ATMEL_RTS_HIGH_OFFSET 16 #define ATMEL_RTS_LOW_OFFSET 20 -#if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/serial_core.h> #include "serial_mctrl_gpio.h" @@ -196,10 +192,6 @@ struct atmel_uart_port { static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART); -#ifdef SUPPORT_SYSRQ -static struct console atmel_console; -#endif - #if defined(CONFIG_OF) static const struct of_device_id atmel_serial_dt_ids[] = { { .compatible = "atmel,at91rm9200-usart-serial" }, @@ -313,7 +305,11 @@ static int atmel_config_rs485(struct uart_port *port, if (rs485conf->flags & SER_RS485_ENABLED) { dev_dbg(port->dev, "Setting UART to RS485\n"); - atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; + if (port->rs485.flags & SER_RS485_RX_DURING_TX) + atmel_port->tx_done_mask = ATMEL_US_TXRDY; + else + atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; + atmel_uart_writel(port, ATMEL_US_TTGR, rs485conf->delay_rts_after_send); mode |= ATMEL_US_USMODE_RS485; @@ -831,7 +827,7 @@ static void atmel_tx_chars(struct uart_port *port) struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); if (port->x_char && - (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) { + (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY)) { atmel_uart_write_char(port, port->x_char); port->icount.tx++; port->x_char = 0; @@ -839,8 +835,7 @@ static void atmel_tx_chars(struct uart_port *port) if (uart_circ_empty(xmit) || uart_tx_stopped(port)) return; - while (atmel_uart_readl(port, ATMEL_US_CSR) & - atmel_port->tx_done_mask) { + while (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY) { atmel_uart_write_char(port, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; @@ -851,10 +846,20 @@ static void atmel_tx_chars(struct uart_port *port) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); - if (!uart_circ_empty(xmit)) + if (!uart_circ_empty(xmit)) { + /* we still have characters to transmit, so we should continue + * transmitting them when TX is ready, regardless of + * mode or duplexity + */ + atmel_port->tx_done_mask |= ATMEL_US_TXRDY; + /* Enable interrupts */ atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask); + } else { + if (atmel_uart_is_half_duplex(port)) + atmel_port->tx_done_mask &= ~ATMEL_US_TXRDY; + } } static void atmel_complete_tx_dma(void *arg) @@ -1067,7 +1072,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port) chan_err: dev_err(port->dev, "TX channel not available, switch to pio\n"); - atmel_port->use_dma_tx = 0; + atmel_port->use_dma_tx = false; if (atmel_port->chan_tx) atmel_release_tx_dma(port); return -EINVAL; @@ -1266,7 +1271,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port) chan_err: dev_err(port->dev, "RX channel not available, switch to pio\n"); - atmel_port->use_dma_rx = 0; + atmel_port->use_dma_rx = false; if (atmel_port->chan_rx) atmel_release_rx_dma(port); return -EINVAL; @@ -1693,7 +1698,7 @@ static int atmel_prepare_rx_pdc(struct uart_port *port) DMA_FROM_DEVICE); kfree(atmel_port->pdc_rx[0].buf); } - atmel_port->use_pdc_rx = 0; + atmel_port->use_pdc_rx = false; return -ENOMEM; } pdc->dma_addr = dma_map_single(port->dev, @@ -2270,27 +2275,6 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, mode |= ATMEL_US_USMODE_NORMAL; } - /* set the mode, clock divisor, parity, stop bits and data size */ - atmel_uart_writel(port, ATMEL_US_MR, mode); - - /* - * when switching the mode, set the RTS line state according to the - * new mode, otherwise keep the former state - */ - if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) { - unsigned int rts_state; - - if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) { - /* let the hardware control the RTS line */ - rts_state = ATMEL_US_RTSDIS; - } else { - /* force RTS line to low level */ - rts_state = ATMEL_US_RTSEN; - } - - atmel_uart_writel(port, ATMEL_US_CR, rts_state); - } - /* * Set the baud rate: * Fractional baudrate allows to setup output frequency more @@ -2317,6 +2301,28 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, if (!(port->iso7816.flags & SER_ISO7816_ENABLED)) atmel_uart_writel(port, ATMEL_US_BRGR, quot); + + /* set the mode, clock divisor, parity, stop bits and data size */ + atmel_uart_writel(port, ATMEL_US_MR, mode); + + /* + * when switching the mode, set the RTS line state according to the + * new mode, otherwise keep the former state + */ + if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) { + unsigned int rts_state; + + if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) { + /* let the hardware control the RTS line */ + rts_state = ATMEL_US_RTSDIS; + } else { + /* force RTS line to low level */ + rts_state = ATMEL_US_RTSEN; + } + + atmel_uart_writel(port, ATMEL_US_CR, rts_state); + } + atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN); atmel_port->tx_stopped = false; @@ -2525,8 +2531,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, * Use TXEMPTY for interrupt when rs485 or ISO7816 else TXRDY or * ENDTX|TXBUFE */ - if (port->rs485.flags & SER_RS485_ENABLED || - port->iso7816.flags & SER_ISO7816_ENABLED) + if (atmel_uart_is_half_duplex(port)) atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; else if (atmel_use_pdc_tx(port)) { port->fifosize = PDC_BUFFER_SIZE; @@ -2877,6 +2882,7 @@ static int atmel_serial_probe(struct platform_device *pdev) atmel_port = &atmel_ports[ret]; atmel_port->backup_imr = 0; atmel_port->uart.line = ret; + atmel_port->uart.has_sysrq = IS_ENABLED(CONFIG_SERIAL_ATMEL_CONSOLE); atmel_serial_probe_fifos(atmel_port, pdev); atomic_set(&atmel_port->tasklet_shutdown, 0); diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c index b7adc6127b3d..5674da2b76f0 100644 --- a/drivers/tty/serial/bcm63xx_uart.c +++ b/drivers/tty/serial/bcm63xx_uart.c @@ -10,10 +10,6 @@ * my board. */ -#if defined(CONFIG_SERIAL_BCM63XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/init.h> @@ -858,6 +854,7 @@ static int bcm_uart_probe(struct platform_device *pdev) port->fifosize = 16; port->uartclk = clk_get_rate(clk) / 2; port->line = pdev->id; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_BCM63XX_CONSOLE); clk_put(clk); ret = uart_add_one_port(&bcm_uart_driver, port); diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index 061590795680..95abc6faa3d5 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -8,10 +8,6 @@ * Copyright (C) 2000 Deep Blue Solutions Ltd. */ -#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/device.h> #include <linux/console.h> @@ -479,6 +475,7 @@ static int uart_clps711x_probe(struct platform_device *pdev) s->port.mapbase = res->start; s->port.type = PORT_CLPS711X; s->port.fifosize = 16; + s->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_CLPS711X_CONSOLE); s->port.flags = UPF_SKIP_TEST | UPF_FIXED_TYPE; s->port.uartclk = clk_get_rate(uart_clk); s->port.ops = &uart_clps711x_ops; diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index de6d02f7abe2..19d5a4cf29a6 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c @@ -40,10 +40,6 @@ #include <asm/fs_pd.h> #include <asm/udbg.h> -#if defined(CONFIG_SERIAL_CPM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/serial_core.h> #include <linux/kernel.h> @@ -347,9 +343,7 @@ static void cpm_uart_int_rx(struct uart_port *port) /* ASSUMPTION: it contains nothing valid */ i = 0; } -#ifdef SUPPORT_SYSRQ port->sysrq = 0; -#endif goto error_return; } @@ -1204,7 +1198,8 @@ static int cpm_uart_init_port(struct device_node *np, pinfo->port.uartclk = ppc_proc_freq; pinfo->port.mapbase = (unsigned long)mem; pinfo->port.type = PORT_CPM; - pinfo->port.ops = &cpm_uart_pops, + pinfo->port.ops = &cpm_uart_pops; + pinfo->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_CPM_CONSOLE); pinfo->port.iotype = UPIO_MEM; pinfo->port.fifosize = pinfo->tx_nrfifos * pinfo->tx_fifosize; spin_lock_init(&pinfo->port.lock); diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c index 7b57e840e255..4552742c3859 100644 --- a/drivers/tty/serial/dz.c +++ b/drivers/tty/serial/dz.c @@ -29,10 +29,6 @@ #undef DEBUG_DZ -#if defined(CONFIG_SERIAL_DZ_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/bitops.h> #include <linux/compiler.h> #include <linux/console.h> @@ -677,7 +673,7 @@ static void dz_release_port(struct uart_port *uport) static int dz_map_port(struct uart_port *uport) { if (!uport->membase) - uport->membase = ioremap_nocache(uport->mapbase, + uport->membase = ioremap(uport->mapbase, dec_kn_slot_size); if (!uport->membase) { printk(KERN_ERR "dz: Cannot map MMIO\n"); @@ -787,6 +783,7 @@ static void __init dz_init_ports(void) uport->ops = &dz_ops; uport->line = line; uport->mapbase = base; + uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_DZ_CONSOLE); } } diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index d6b5e5463746..2ac87128d7fd 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -1,8 +1,4 @@ // SPDX-License-Identifier: GPL-2.0 -#if defined(CONFIG_SERIAL_EFM32_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/kernel.h> #include <linux/module.h> #include <linux/io.h> @@ -748,6 +744,7 @@ static int efm32_uart_probe(struct platform_device *pdev) efm_port->port.type = PORT_EFMUART; efm_port->port.iotype = UPIO_MEM32; efm_port->port.fifosize = 2; + efm_port->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_EFM32_UART_CONSOLE); efm_port->port.ops = &efm32_uart_pops; efm_port->port.flags = UPF_BOOT_AUTOCONF; diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c index 205c31a61684..3e28be402aef 100644 --- a/drivers/tty/serial/fsl_linflexuart.c +++ b/drivers/tty/serial/fsl_linflexuart.c @@ -6,11 +6,6 @@ * Copyright 2017-2019 NXP */ -#if defined(CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE) && \ - defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/console.h> #include <linux/io.h> #include <linux/irq.h> @@ -279,10 +274,8 @@ static irqreturn_t linflex_rxint(int irq, void *dev_id) if (brk) { uart_handle_break(sport); } else { -#ifdef SUPPORT_SYSRQ if (uart_handle_sysrq_char(sport, (unsigned char)rx)) continue; -#endif tty_insert_flip_char(port, rx, flg); } } @@ -863,6 +856,7 @@ static int linflex_probe(struct platform_device *pdev) sport->irq = platform_get_irq(pdev, 0); sport->ops = &linflex_pops; sport->flags = UPF_BOOT_AUTOCONF; + sport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE); linflex_ports[sport->line] = sport; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 4e128d19e0ad..91e2805e6441 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -5,10 +5,6 @@ * Copyright 2012-2014 Freescale Semiconductor, Inc. */ -#if defined(CONFIG_SERIAL_FSL_LPUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/clk.h> #include <linux/console.h> #include <linux/dma-mapping.h> @@ -864,9 +860,7 @@ static void lpuart_rxint(struct lpuart_port *sport) if (sr & UARTSR1_OR) flg = TTY_OVERRUN; -#ifdef SUPPORT_SYSRQ sport->port.sysrq = 0; -#endif } tty_insert_flip_char(port, rx, flg); @@ -946,9 +940,7 @@ static void lpuart32_rxint(struct lpuart_port *sport) if (sr & UARTSTAT_OR) flg = TTY_OVERRUN; -#ifdef SUPPORT_SYSRQ sport->port.sysrq = 0; -#endif } tty_insert_flip_char(port, rx, flg); @@ -2376,7 +2368,9 @@ static int __init lpuart32_early_console_setup(struct earlycon_device *device, if (!device->port.membase) return -ENODEV; - device->port.iotype = UPIO_MEM32BE; + if (device->port.iotype != UPIO_MEM32) + device->port.iotype = UPIO_MEM32BE; + device->con->write = lpuart32_early_write; return 0; } @@ -2396,9 +2390,6 @@ 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,imx7ulp-lpuart", lpuart32_imx_early_console_setup); -OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup); -EARLYCON_DECLARE(lpuart, lpuart_early_console_setup); -EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup); #define LPUART_CONSOLE (&lpuart_console) #define LPUART32_CONSOLE (&lpuart32_console) @@ -2461,6 +2452,7 @@ static int lpuart_probe(struct platform_device *pdev) sport->port.ops = &lpuart32_pops; else sport->port.ops = &lpuart_pops; + sport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_FSL_LPUART_CONSOLE); sport->port.flags = UPF_BOOT_AUTOCONF; if (lpuart_is_32(sport)) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index a9e20e6c63ad..0c6c63166250 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -8,10 +8,6 @@ * Copyright (C) 2004 Pengutronix */ -#if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/ioport.h> #include <linux/init.h> @@ -700,22 +696,33 @@ static void imx_uart_start_tx(struct uart_port *port) } } -static irqreturn_t imx_uart_rtsint(int irq, void *dev_id) +static irqreturn_t __imx_uart_rtsint(int irq, void *dev_id) { struct imx_port *sport = dev_id; u32 usr1; - spin_lock(&sport->port.lock); - imx_uart_writel(sport, USR1_RTSD, USR1); usr1 = imx_uart_readl(sport, USR1) & USR1_RTSS; uart_handle_cts_change(&sport->port, !!usr1); wake_up_interruptible(&sport->port.state->port.delta_msr_wait); - spin_unlock(&sport->port.lock); return IRQ_HANDLED; } +static irqreturn_t imx_uart_rtsint(int irq, void *dev_id) +{ + struct imx_port *sport = dev_id; + irqreturn_t ret; + + spin_lock(&sport->port.lock); + + ret = __imx_uart_rtsint(irq, dev_id); + + spin_unlock(&sport->port.lock); + + return ret; +} + static irqreturn_t imx_uart_txint(int irq, void *dev_id) { struct imx_port *sport = dev_id; @@ -726,14 +733,12 @@ static irqreturn_t imx_uart_txint(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t imx_uart_rxint(int irq, void *dev_id) +static irqreturn_t __imx_uart_rxint(int irq, void *dev_id) { struct imx_port *sport = dev_id; unsigned int rx, flg, ignored = 0; struct tty_port *port = &sport->port.state->port; - spin_lock(&sport->port.lock); - while (imx_uart_readl(sport, USR2) & USR2_RDR) { u32 usr2; @@ -779,9 +784,7 @@ static irqreturn_t imx_uart_rxint(int irq, void *dev_id) if (rx & URXD_OVRRUN) flg = TTY_OVERRUN; -#ifdef SUPPORT_SYSRQ sport->port.sysrq = 0; -#endif } if (sport->port.ignore_status_mask & URXD_DUMMY_READ) @@ -792,11 +795,25 @@ static irqreturn_t imx_uart_rxint(int irq, void *dev_id) } out: - spin_unlock(&sport->port.lock); tty_flip_buffer_push(port); + return IRQ_HANDLED; } +static irqreturn_t imx_uart_rxint(int irq, void *dev_id) +{ + struct imx_port *sport = dev_id; + irqreturn_t ret; + + spin_lock(&sport->port.lock); + + ret = __imx_uart_rxint(irq, dev_id); + + spin_unlock(&sport->port.lock); + + return ret; +} + static void imx_uart_clear_rx_errors(struct imx_port *sport); /* @@ -855,6 +872,8 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id) unsigned int usr1, usr2, ucr1, ucr2, ucr3, ucr4; irqreturn_t ret = IRQ_NONE; + spin_lock(&sport->port.lock); + usr1 = imx_uart_readl(sport, USR1); usr2 = imx_uart_readl(sport, USR2); ucr1 = imx_uart_readl(sport, UCR1); @@ -888,27 +907,25 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id) usr2 &= ~USR2_ORE; if (usr1 & (USR1_RRDY | USR1_AGTIM)) { - imx_uart_rxint(irq, dev_id); + __imx_uart_rxint(irq, dev_id); ret = IRQ_HANDLED; } if ((usr1 & USR1_TRDY) || (usr2 & USR2_TXDC)) { - imx_uart_txint(irq, dev_id); + imx_uart_transmit_buffer(sport); ret = IRQ_HANDLED; } if (usr1 & USR1_DTRD) { imx_uart_writel(sport, USR1_DTRD, USR1); - spin_lock(&sport->port.lock); imx_uart_mctrl_check(sport); - spin_unlock(&sport->port.lock); ret = IRQ_HANDLED; } if (usr1 & USR1_RTSD) { - imx_uart_rtsint(irq, dev_id); + __imx_uart_rtsint(irq, dev_id); ret = IRQ_HANDLED; } @@ -923,6 +940,8 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id) ret = IRQ_HANDLED; } + spin_unlock(&sport->port.lock); + return ret; } @@ -2231,6 +2250,7 @@ static int imx_uart_probe(struct platform_device *pdev) sport->port.iotype = UPIO_MEM; sport->port.irq = rxirq; sport->port.fifosize = 32; + sport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE); sport->port.ops = &imx_uart_pops; sport->port.rs485_config = imx_uart_rs485_config; sport->port.flags = UPF_BOOT_AUTOCONF; diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c index 8c810733df3d..86fff69d7e7c 100644 --- a/drivers/tty/serial/ip22zilog.c +++ b/drivers/tty/serial/ip22zilog.c @@ -38,10 +38,6 @@ #include <asm/sgi/hpc3.h> #include <asm/sgi/ip22.h> -#if defined(CONFIG_SERIAL_IP22_ZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/serial_core.h> #include "ip22zilog.h" @@ -1080,6 +1076,7 @@ static struct uart_driver ip22zilog_reg = { static void __init ip22zilog_prepare(void) { + unsigned char sysrq_on = IS_ENABLED(CONFIG_SERIAL_IP22_ZILOG_CONSOLE); struct uart_ip22zilog_port *up; struct zilog_layout *rp; int channel, chip; @@ -1115,6 +1112,7 @@ static void __init ip22zilog_prepare(void) up[(chip * 2) + 0].port.irq = zilog_irq; up[(chip * 2) + 0].port.uartclk = ZS_CLOCK; up[(chip * 2) + 0].port.fifosize = 1; + up[(chip * 2) + 0].port.has_sysrq = sysrq_on; up[(chip * 2) + 0].port.ops = &ip22zilog_pops; up[(chip * 2) + 0].port.type = PORT_IP22ZILOG; up[(chip * 2) + 0].port.flags = 0; @@ -1126,6 +1124,7 @@ static void __init ip22zilog_prepare(void) up[(chip * 2) + 1].port.irq = zilog_irq; up[(chip * 2) + 1].port.uartclk = ZS_CLOCK; up[(chip * 2) + 1].port.fifosize = 1; + up[(chip * 2) + 1].port.has_sysrq = sysrq_on; up[(chip * 2) + 1].port.ops = &ip22zilog_pops; up[(chip * 2) + 1].port.type = PORT_IP22ZILOG; up[(chip * 2) + 1].port.line = (chip * 2) + 1; diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c index 4029272891f9..5022447afa23 100644 --- a/drivers/tty/serial/kgdb_nmi.c +++ b/drivers/tty/serial/kgdb_nmi.c @@ -118,7 +118,7 @@ static int kgdb_nmi_poll_one_knock(void) int c = -1; const char *magic = kgdb_nmi_magic; size_t m = strlen(magic); - bool printch = 0; + bool printch = false; c = dbg_io_ops->read_char(); if (c == NO_POLL_CHAR) @@ -130,7 +130,7 @@ static int kgdb_nmi_poll_one_knock(void) n = (n + 1) % m; if (!n) return 1; - printch = 1; + printch = true; } else { n = 0; } diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index fcbea43dc334..f67226df30d4 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -549,7 +549,7 @@ lqasc_request_port(struct uart_port *port) } if (port->flags & UPF_IOREMAP) { - port->membase = devm_ioremap_nocache(&pdev->dev, + port->membase = devm_ioremap(&pdev->dev, port->mapbase, size); if (port->membase == NULL) return -ENOMEM; diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index fbc5bc022a39..d2c08b760f83 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -5,15 +5,12 @@ * Copyright (C) 2014 Carlo Caione <carlo@caione.org> */ -#if defined(CONFIG_SERIAL_MESON_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/clk.h> #include <linux/console.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/of.h> @@ -76,6 +73,8 @@ #define AML_UART_PORT_OFFSET 6 #define AML_UART_DEV_NAME "ttyAML" +#define AML_UART_POLL_USEC 5 +#define AML_UART_TIMEOUT_USEC 10000 static struct uart_driver meson_uart_driver; @@ -411,7 +410,7 @@ static int meson_uart_request_port(struct uart_port *port) return -EBUSY; } - port->membase = devm_ioremap_nocache(port->dev, port->mapbase, + port->membase = devm_ioremap(port->dev, port->mapbase, port->mapsize); if (!port->membase) return -ENOMEM; @@ -427,6 +426,64 @@ static void meson_uart_config_port(struct uart_port *port, int flags) } } +#ifdef CONFIG_CONSOLE_POLL +/* + * Console polling routines for writing and reading from the uart while + * in an interrupt or debug context (i.e. kgdb). + */ + +static int meson_uart_poll_get_char(struct uart_port *port) +{ + u32 c; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + + if (readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY) + c = NO_POLL_CHAR; + else + c = readl(port->membase + AML_UART_RFIFO); + + spin_unlock_irqrestore(&port->lock, flags); + + return c; +} + +static void meson_uart_poll_put_char(struct uart_port *port, unsigned char c) +{ + unsigned long flags; + u32 reg; + int ret; + + spin_lock_irqsave(&port->lock, flags); + + /* Wait until FIFO is empty or timeout */ + ret = readl_poll_timeout_atomic(port->membase + AML_UART_STATUS, reg, + reg & AML_UART_TX_EMPTY, + AML_UART_POLL_USEC, + AML_UART_TIMEOUT_USEC); + if (ret == -ETIMEDOUT) { + dev_err(port->dev, "Timeout waiting for UART TX EMPTY\n"); + goto out; + } + + /* Write the character */ + writel(c, port->membase + AML_UART_WFIFO); + + /* Wait until FIFO is empty or timeout */ + ret = readl_poll_timeout_atomic(port->membase + AML_UART_STATUS, reg, + reg & AML_UART_TX_EMPTY, + AML_UART_POLL_USEC, + AML_UART_TIMEOUT_USEC); + if (ret == -ETIMEDOUT) + dev_err(port->dev, "Timeout waiting for UART TX EMPTY\n"); + +out: + spin_unlock_irqrestore(&port->lock, flags); +} + +#endif /* CONFIG_CONSOLE_POLL */ + static const struct uart_ops meson_uart_ops = { .set_mctrl = meson_uart_set_mctrl, .get_mctrl = meson_uart_get_mctrl, @@ -442,6 +499,10 @@ static const struct uart_ops meson_uart_ops = { .request_port = meson_uart_request_port, .release_port = meson_uart_release_port, .verify_port = meson_uart_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = meson_uart_poll_get_char, + .poll_put_char = meson_uart_poll_put_char, +#endif }; #ifdef CONFIG_SERIAL_MESON_CONSOLE @@ -703,6 +764,7 @@ static int meson_uart_probe(struct platform_device *pdev) port->mapsize = resource_size(res_mem); port->irq = res_irq->start; port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MESON_CONSOLE); port->dev = &pdev->dev; port->line = pdev->id; port->type = PORT_MESON; diff --git a/drivers/tty/serial/milbeaut_usio.c b/drivers/tty/serial/milbeaut_usio.c index 949ab7efc4fc..8f2cab7f66ad 100644 --- a/drivers/tty/serial/milbeaut_usio.c +++ b/drivers/tty/serial/milbeaut_usio.c @@ -3,10 +3,6 @@ * Copyright (C) 2018 Socionext Inc. */ -#if defined(CONFIG_SERIAL_MILBEAUT_USIO_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/clk.h> #include <linux/console.h> #include <linux/module.h> @@ -537,6 +533,7 @@ static int mlb_usio_probe(struct platform_device *pdev) port->irq = mlb_usio_irq[index][RX]; port->uartclk = clk_get_rate(clk); port->fifosize = 128; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MILBEAUT_USIO_CONSOLE); port->iotype = UPIO_MEM32; port->flags = UPF_BOOT_AUTOCONF | UPF_SPD_VHI; port->line = index; diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 3a75ee08d619..af1700445251 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c @@ -44,10 +44,6 @@ #include <asm/mpc52xx.h> #include <asm/mpc52xx_psc.h> -#if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/serial_core.h> @@ -1382,12 +1378,8 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) ch = psc_ops->read_char(port); /* Handle sysreq char */ -#ifdef SUPPORT_SYSRQ - if (uart_handle_sysrq_char(port, ch)) { - port->sysrq = 0; + if (uart_handle_sysrq_char(port, ch)) continue; - } -#endif /* Store it */ @@ -1770,6 +1762,7 @@ static int mpc52xx_uart_of_probe(struct platform_device *op) spin_lock_init(&port->lock); port->uartclk = uartclk; port->fifosize = 512; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MPC52xx_CONSOLE); port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF | (uart_console(port) ? 0 : UPF_IOREMAP); diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 1cbae0768b1f..60a9c53fa7cb 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -7,10 +7,6 @@ * Copyright (c) 2011, Code Aurora Forum. All rights reserved. */ -#if defined(CONFIG_SERIAL_MSM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -# define SUPPORT_SYSRQ -#endif - #include <linux/kernel.h> #include <linux/atomic.h> #include <linux/dma-mapping.h> @@ -610,7 +606,7 @@ static void msm_start_rx_dma(struct msm_port *msm_port) UARTDM_RX_SIZE, dma->dir); ret = dma_mapping_error(uart->dev, dma->phys); if (ret) - return; + goto sw_mode; dma->desc = dmaengine_prep_slave_single(dma->chan, dma->phys, UARTDM_RX_SIZE, DMA_DEV_TO_MEM, @@ -661,6 +657,22 @@ static void msm_start_rx_dma(struct msm_port *msm_port) return; unmap: dma_unmap_single(uart->dev, dma->phys, UARTDM_RX_SIZE, dma->dir); + +sw_mode: + /* + * Switch from DMA to SW/FIFO mode. After clearing Rx BAM (UARTDM_DMEN), + * receiver must be reset. + */ + msm_write(uart, UART_CR_CMD_RESET_RX, UART_CR); + msm_write(uart, UART_CR_RX_ENABLE, UART_CR); + + msm_write(uart, UART_CR_CMD_RESET_STALE_INT, UART_CR); + msm_write(uart, 0xFFFFFF, UARTDM_DMRX); + msm_write(uart, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); + + /* Re-enable RX interrupts */ + msm_port->imr |= (UART_IMR_RXLEV | UART_IMR_RXSTALE); + msm_write(uart, msm_port->imr, UART_IMR); } static void msm_stop_rx(struct uart_port *port) @@ -1580,6 +1592,7 @@ static void __msm_console_write(struct uart_port *port, const char *s, int num_newlines = 0; bool replaced = false; void __iomem *tf; + int locked = 1; if (is_uartdm) tf = port->membase + UARTDM_TF; @@ -1592,7 +1605,13 @@ static void __msm_console_write(struct uart_port *port, const char *s, num_newlines++; count += num_newlines; - spin_lock(&port->lock); + if (port->sysrq) + locked = 0; + else if (oops_in_progress) + locked = spin_trylock(&port->lock); + else + spin_lock(&port->lock); + if (is_uartdm) msm_reset_dm_count(port, count); @@ -1628,7 +1647,9 @@ static void __msm_console_write(struct uart_port *port, const char *s, iowrite32_rep(tf, buf, 1); i += num_chars; } - spin_unlock(&port->lock); + + if (locked) + spin_unlock(&port->lock); } static void msm_console_write(struct console *co, const char *s, @@ -1801,6 +1822,7 @@ static int msm_serial_probe(struct platform_device *pdev) if (unlikely(irq < 0)) return -ENXIO; port->irq = irq; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MSM_CONSOLE); platform_set_drvdata(pdev, port); diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c index 00ce31e8d19a..47ab280f553b 100644 --- a/drivers/tty/serial/mux.c +++ b/drivers/tty/serial/mux.c @@ -25,11 +25,7 @@ #include <asm/irq.h> #include <asm/parisc-device.h> -#if defined(CONFIG_SERIAL_MUX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #include <linux/sysrq.h> -#define SUPPORT_SYSRQ -#endif - #include <linux/serial_core.h> #define MUX_OFFSET 0x800 @@ -474,7 +470,7 @@ static int __init mux_probe(struct parisc_device *dev) port->iobase = 0; port->mapbase = dev->hpa.start + MUX_OFFSET + (i * MUX_LINE_OFFSET); - port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET); + port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); port->iotype = UPIO_MEM; port->type = PORT_MUX; port->irq = 0; @@ -483,6 +479,7 @@ static int __init mux_probe(struct parisc_device *dev) port->ops = &mux_pops; port->flags = UPF_BOOT_AUTOCONF; port->line = port_cnt; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MUX_CONSOLE); /* The port->timeout needs to match what is present in * uart_wait_until_sent in serial_core.c. Otherwise diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index e34525970682..b4f835e7de23 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -12,10 +12,6 @@ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. */ -#if defined(CONFIG_SERIAL_MXS_AUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/kernel.h> #include <linux/errno.h> #include <linux/init.h> @@ -1693,6 +1689,7 @@ static int mxs_auart_probe(struct platform_device *pdev) s->port.fifosize = MXS_AUART_FIFO_SIZE; s->port.uartclk = clk_get_rate(s->clk); s->port.type = PORT_IMX; + s->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_MXS_AUART_CONSOLE); mxs_init_regs(s); diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 6420ae581a80..48017cec7f2f 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -16,10 +16,6 @@ * this driver as required for the omap-platform. */ -#if defined(CONFIG_SERIAL_OMAP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/init.h> #include <linux/console.h> @@ -493,10 +489,13 @@ static unsigned int check_modem_status(struct uart_omap_port *up) static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr) { unsigned int flag; - unsigned char ch = 0; + /* + * Read one data character out to avoid stalling the receiver according + * to the table 23-246 of the omap4 TRM. + */ if (likely(lsr & UART_LSR_DR)) - ch = serial_in(up, UART_RX); + serial_in(up, UART_RX); up->port.icount.rx++; flag = TTY_NORMAL; @@ -1680,6 +1679,7 @@ static int serial_omap_probe(struct platform_device *pdev) up->port.regshift = 2; up->port.fifosize = 64; up->port.ops = &serial_omap_pops; + up->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_OMAP_CONSOLE); if (pdev->dev.of_node) ret = of_alias_get_id(pdev->dev.of_node, "serial"); diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c index d2d8b3494685..42c8cc93b603 100644 --- a/drivers/tty/serial/owl-uart.c +++ b/drivers/tty/serial/owl-uart.c @@ -427,7 +427,7 @@ static int owl_uart_request_port(struct uart_port *port) return -EBUSY; if (port->flags & UPF_IOREMAP) { - port->membase = devm_ioremap_nocache(port->dev, port->mapbase, + port->membase = devm_ioremap(port->dev, port->mapbase, resource_size(res)); if (!port->membase) return -EBUSY; diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index c16234bca78f..0a96217dba67 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -2,9 +2,6 @@ /* *Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. */ -#if defined(CONFIG_SERIAL_PCH_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif #include <linux/kernel.h> #include <linux/serial_reg.h> #include <linux/slab.h> @@ -587,12 +584,8 @@ static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf, if (uart_handle_break(port)) continue; } -#ifdef SUPPORT_SYSRQ - if (port->sysrq) { - if (uart_handle_sysrq_char(port, rbr)) - continue; - } -#endif + if (uart_handle_sysrq_char(port, rbr)) + continue; buf[i++] = rbr; } @@ -1796,6 +1789,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, priv->port.flags = UPF_BOOT_AUTOCONF; priv->port.fifosize = fifosize; priv->port.line = board->line_no; + priv->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_PCH_UART_CONSOLE); priv->trigger = PCH_UART_HAL_TRIGGER_M; snprintf(priv->irq_name, IRQ_NAME_SIZE, diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c index 0bdf1687983f..484b7e8d5381 100644 --- a/drivers/tty/serial/pic32_uart.c +++ b/drivers/tty/serial/pic32_uart.c @@ -618,7 +618,7 @@ static int pic32_uart_request_port(struct uart_port *port) "pic32_uart_mem")) return -EBUSY; - port->membase = devm_ioremap_nocache(port->dev, port->mapbase, + port->membase = devm_ioremap(port->dev, port->mapbase, resource_size(res_mem)); if (!port->membase) { dev_err(port->dev, "Unable to map registers\n"); diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index bcb5bf70534e..ba65a3bbd72a 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -61,10 +61,6 @@ #define of_machine_is_compatible(x) (0) #endif -#if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/serial.h> #include <linux/serial_core.h> @@ -1721,6 +1717,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap) uap->control_reg = uap->port.membase; uap->data_reg = uap->control_reg + 4; uap->port_type = 0; + uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_PMACZILOG_CONSOLE); pmz_convert_to_zs(uap, CS8, 0, 9600); diff --git a/drivers/tty/serial/pnx8xxx_uart.c b/drivers/tty/serial/pnx8xxx_uart.c index 223a9499104e..972d94e8d32b 100644 --- a/drivers/tty/serial/pnx8xxx_uart.c +++ b/drivers/tty/serial/pnx8xxx_uart.c @@ -10,10 +10,6 @@ * Copyright (C) 2000 Deep Blue Solutions Ltd. */ -#if defined(CONFIG_SERIAL_PNX8XXX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/ioport.h> #include <linux/init.h> @@ -220,9 +216,7 @@ static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport) else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE)) flg = TTY_FRAME; -#ifdef SUPPORT_SYSRQ sport->port.sysrq = 0; -#endif } if (uart_handle_sysrq_char(&sport->port, ch)) @@ -800,6 +794,7 @@ static int pnx8xxx_serial_probe(struct platform_device *pdev) if (pnx8xxx_ports[i].port.mapbase != res->start) continue; + pnx8xxx_ports[i].port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_PNX8XXX_CONSOLE); pnx8xxx_ports[i].port.dev = &pdev->dev; uart_add_one_port(&pnx8xxx_reg, &pnx8xxx_ports[i].port); platform_set_drvdata(pdev, &pnx8xxx_ports[i]); diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index 4932b674f7ef..41319ef96fa6 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -19,10 +19,6 @@ */ -#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/ioport.h> #include <linux/init.h> #include <linux/console.h> @@ -879,6 +875,7 @@ static int serial_pxa_probe(struct platform_device *dev) sport->port.dev = &dev->dev; sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; sport->port.uartclk = clk_get_rate(sport->clk); + sport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_PXA_CONSOLE); ret = serial_pxa_probe_dt(dev, sport); if (ret > 0) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index ff63728a95f4..191abb18fc2a 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1,10 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2017-2018, The Linux foundation. All rights reserved. -#if defined(CONFIG_SERIAL_QCOM_GENI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -# define SUPPORT_SYSRQ -#endif - #include <linux/clk.h> #include <linux/console.h> #include <linux/io.h> @@ -14,6 +10,7 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/pm_wakeirq.h> #include <linux/qcom-geni-se.h> #include <linux/serial.h> @@ -92,7 +89,11 @@ #define DEF_TX_WM 2 #define DEF_FIFO_WIDTH_BITS 32 #define UART_RX_WM 2 -#define MAX_LOOPBACK_CFG 3 + +/* SE_UART_LOOPBACK_CFG */ +#define RX_TX_SORTED BIT(0) +#define CTS_RTS_SORTED BIT(1) +#define RX_TX_CTS_RTS_SORTED (RX_TX_SORTED | CTS_RTS_SORTED) #ifdef CONFIG_CONSOLE_POLL #define CONSOLE_RX_BYTES_PW 1 @@ -103,7 +104,7 @@ struct qcom_geni_serial_port { struct uart_port uport; struct geni_se se; - char name[20]; + const char *name; u32 tx_fifo_depth; u32 tx_fifo_width; u32 rx_fifo_depth; @@ -164,30 +165,6 @@ static struct qcom_geni_serial_port qcom_geni_uart_ports[GENI_UART_PORTS] = { }, }; -static ssize_t loopback_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct qcom_geni_serial_port *port = dev_get_drvdata(dev); - - return snprintf(buf, sizeof(u32), "%d\n", port->loopback); -} - -static ssize_t loopback_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t size) -{ - struct qcom_geni_serial_port *port = dev_get_drvdata(dev); - u32 loopback; - - if (kstrtoint(buf, 0, &loopback) || loopback > MAX_LOOPBACK_CFG) { - dev_err(dev, "Invalid input\n"); - return -EINVAL; - } - port->loopback = loopback; - return size; -} -static DEVICE_ATTR_RW(loopback); - static struct qcom_geni_serial_port qcom_geni_console_port = { .uport = { .iotype = UPIO_MEM, @@ -237,10 +214,14 @@ static void qcom_geni_serial_set_mctrl(struct uart_port *uport, unsigned int mctrl) { u32 uart_manual_rfr = 0; + struct qcom_geni_serial_port *port = to_dev_port(uport, uport); if (uart_console(uport)) return; + if (mctrl & TIOCM_LOOP) + port->loopback = RX_TX_CTS_RTS_SORTED; + if (!(mctrl & TIOCM_RTS)) uart_manual_rfr = UART_MANUAL_RFR_EN | UART_RFR_NOT_READY; writel(uart_manual_rfr, uport->membase + SE_UART_MANUAL_RFR); @@ -757,15 +738,6 @@ out_write_wakeup: uart_write_wakeup(uport); } -static irqreturn_t qcom_geni_serial_wakeup_isr(int isr, void *dev) -{ - struct uart_port *uport = dev; - - pm_wakeup_event(uport->dev, 2000); - - return IRQ_HANDLED; -} - static irqreturn_t qcom_geni_serial_isr(int isr, void *dev) { u32 m_irq_en; @@ -1302,50 +1274,57 @@ 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; - scnprintf(port->name, sizeof(port->name), "qcom_geni_serial_%s%d", - (uart_console(uport) ? "console" : "uart"), uport->line); + port->name = devm_kasprintf(uport->dev, GFP_KERNEL, + "qcom_geni_serial_%s%d", + uart_console(uport) ? "console" : "uart", uport->line); + if (!port->name) + return -ENOMEM; + irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; uport->irq = irq; + uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_QCOM_GENI_CONSOLE); + + if (!console) + port->wakeup_irq = platform_get_irq_optional(pdev, 1); + + uport->private_data = drv; + platform_set_drvdata(pdev, port); + port->handle_rx = console ? handle_rx_console : handle_rx_uart; + + ret = uart_add_one_port(drv, uport); + if (ret) + return ret; irq_set_status_flags(uport->irq, IRQ_NOAUTOEN); ret = devm_request_irq(uport->dev, uport->irq, qcom_geni_serial_isr, IRQF_TRIGGER_HIGH, port->name, uport); if (ret) { dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret); + uart_remove_one_port(drv, uport); return ret; } - if (!console) { - port->wakeup_irq = platform_get_irq(pdev, 1); - if (port->wakeup_irq < 0) { - dev_err(&pdev->dev, "Failed to get wakeup IRQ %d\n", - port->wakeup_irq); - } else { - irq_set_status_flags(port->wakeup_irq, IRQ_NOAUTOEN); - ret = devm_request_irq(uport->dev, port->wakeup_irq, - qcom_geni_serial_wakeup_isr, - IRQF_TRIGGER_FALLING, "uart_wakeup", uport); - if (ret) { - dev_err(uport->dev, "Failed to register wakeup IRQ ret %d\n", - ret); - return ret; - } - - device_init_wakeup(&pdev->dev, true); - ret = dev_pm_set_wake_irq(&pdev->dev, port->wakeup_irq); - if (unlikely(ret)) - dev_err(uport->dev, "%s:Failed to set IRQ wake:%d\n", - __func__, ret); + /* + * Set pm_runtime status as ACTIVE so that wakeup_irq gets + * enabled/disabled from dev_pm_arm_wake_irq during system + * suspend/resume respectively. + */ + pm_runtime_set_active(&pdev->dev); + + if (port->wakeup_irq > 0) { + device_init_wakeup(&pdev->dev, true); + ret = dev_pm_set_dedicated_wake_irq(&pdev->dev, + port->wakeup_irq); + if (ret) { + device_init_wakeup(&pdev->dev, false); + uart_remove_one_port(drv, uport); + return ret; } } - uport->private_data = drv; - platform_set_drvdata(pdev, port); - port->handle_rx = console ? handle_rx_console : handle_rx_uart; - if (!console) - device_create_file(uport->dev, &dev_attr_loopback); - return uart_add_one_port(drv, uport); + + return 0; } static int qcom_geni_serial_remove(struct platform_device *pdev) @@ -1353,7 +1332,10 @@ static int qcom_geni_serial_remove(struct platform_device *pdev) struct qcom_geni_serial_port *port = platform_get_drvdata(pdev); struct uart_driver *drv = port->uport.private_data; + dev_pm_clear_wake_irq(&pdev->dev); + device_init_wakeup(&pdev->dev, false); uart_remove_one_port(drv, &port->uport); + return 0; } @@ -1362,12 +1344,7 @@ static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev) struct qcom_geni_serial_port *port = dev_get_drvdata(dev); struct uart_port *uport = &port->uport; - uart_suspend_port(uport->private_data, uport); - - if (port->wakeup_irq > 0) - enable_irq(port->wakeup_irq); - - return 0; + return uart_suspend_port(uport->private_data, uport); } static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev) @@ -1375,9 +1352,6 @@ static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev) struct qcom_geni_serial_port *port = dev_get_drvdata(dev); struct uart_port *uport = &port->uport; - if (port->wakeup_irq > 0) - disable_irq(port->wakeup_irq); - return uart_resume_port(uport->private_data, uport); } diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c index ff9a27d48bca..b5ef86ae2746 100644 --- a/drivers/tty/serial/rda-uart.c +++ b/drivers/tty/serial/rda-uart.c @@ -498,7 +498,7 @@ static int rda_uart_request_port(struct uart_port *port) return -EBUSY; if (port->flags & UPF_IOREMAP) { - port->membase = devm_ioremap_nocache(port->dev, port->mapbase, + port->membase = devm_ioremap(port->dev, port->mapbase, resource_size(res)); if (!port->membase) return -EBUSY; diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c index 8e618129e65c..75c2a22895f9 100644 --- a/drivers/tty/serial/sa1100.c +++ b/drivers/tty/serial/sa1100.c @@ -7,10 +7,6 @@ * Copyright (C) 2000 Deep Blue Solutions Ltd. */ -#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/ioport.h> #include <linux/init.h> @@ -214,9 +210,7 @@ sa1100_rx_chars(struct sa1100_port *sport) else if (status & UTSR1_TO_SM(UTSR1_FRE)) flg = TTY_FRAME; -#ifdef SUPPORT_SYSRQ sport->port.sysrq = 0; -#endif } if (uart_handle_sysrq_char(&sport->port, ch)) @@ -860,6 +854,7 @@ static int sa1100_serial_resume(struct platform_device *dev) static int sa1100_serial_add_one_port(struct sa1100_port *sport, struct platform_device *dev) { sport->port.dev = &dev->dev; + sport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SA1100_CONSOLE); // mctrl_gpio_init() requires that the GPIO driver supports interrupts, // but we need to support GPIO drivers for hardware that has no such diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h deleted file mode 100644 index f93022113f59..000000000000 --- a/drivers/tty/serial/samsung.h +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#ifndef __SAMSUNG_H -#define __SAMSUNG_H - -/* - * Driver for Samsung SoC onboard UARTs. - * - * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ -*/ - -#include <linux/dmaengine.h> - -struct s3c24xx_uart_info { - char *name; - unsigned int type; - unsigned int fifosize; - unsigned long rx_fifomask; - unsigned long rx_fifoshift; - unsigned long rx_fifofull; - unsigned long tx_fifomask; - unsigned long tx_fifoshift; - unsigned long tx_fifofull; - unsigned int def_clk_sel; - unsigned long num_clks; - unsigned long clksel_mask; - unsigned long clksel_shift; - - /* uart port features */ - - unsigned int has_divslot:1; - - /* uart controls */ - int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *); -}; - -struct s3c24xx_serial_drv_data { - struct s3c24xx_uart_info *info; - struct s3c2410_uartcfg *def_cfg; - unsigned int fifosize[CONFIG_SERIAL_SAMSUNG_UARTS]; -}; - -struct s3c24xx_uart_dma { - unsigned int rx_chan_id; - unsigned int tx_chan_id; - - struct dma_slave_config rx_conf; - struct dma_slave_config tx_conf; - - struct dma_chan *rx_chan; - struct dma_chan *tx_chan; - - dma_addr_t rx_addr; - dma_addr_t tx_addr; - - dma_cookie_t rx_cookie; - dma_cookie_t tx_cookie; - - char *rx_buf; - - dma_addr_t tx_transfer_addr; - - size_t rx_size; - size_t tx_size; - - struct dma_async_tx_descriptor *tx_desc; - struct dma_async_tx_descriptor *rx_desc; - - int tx_bytes_requested; - int rx_bytes_requested; -}; - -struct s3c24xx_uart_port { - unsigned char rx_claimed; - unsigned char tx_claimed; - unsigned int pm_level; - unsigned long baudclk_rate; - unsigned int min_dma_size; - - unsigned int rx_irq; - unsigned int tx_irq; - - unsigned int tx_in_progress; - unsigned int tx_mode; - unsigned int rx_mode; - - struct s3c24xx_uart_info *info; - struct clk *clk; - struct clk *baudclk; - struct uart_port port; - struct s3c24xx_serial_drv_data *drv_data; - - /* reference to platform data */ - struct s3c2410_uartcfg *cfg; - - struct s3c24xx_uart_dma *dma; - -#ifdef CONFIG_ARM_S3C24XX_CPUFREQ - struct notifier_block freq_transition; -#endif -}; - -/* conversion functions */ - -#define s3c24xx_dev_to_port(__dev) dev_get_drvdata(__dev) - -/* register access controls */ - -#define portaddr(port, reg) ((port)->membase + (reg)) -#define portaddrl(port, reg) \ - ((unsigned long *)(unsigned long)((port)->membase + (reg))) - -#define rd_regb(port, reg) (readb_relaxed(portaddr(port, reg))) -#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg))) - -#define wr_regb(port, reg, val) writeb_relaxed(val, portaddr(port, reg)) -#define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg)) - -/* Byte-order aware bit setting/clearing functions. */ - -static inline void s3c24xx_set_bit(struct uart_port *port, int idx, - unsigned int reg) -{ - unsigned long flags; - u32 val; - - local_irq_save(flags); - val = rd_regl(port, reg); - val |= (1 << idx); - wr_regl(port, reg, val); - local_irq_restore(flags); -} - -static inline void s3c24xx_clear_bit(struct uart_port *port, int idx, - unsigned int reg) -{ - unsigned long flags; - u32 val; - - local_irq_save(flags); - val = rd_regl(port, reg); - val &= ~(1 << idx); - wr_regl(port, reg, val); - local_irq_restore(flags); -} - -#endif diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index 83fd51607741..73f951d65b93 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -4,7 +4,7 @@ * * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics * http://armlinux.simtec.co.uk/ -*/ + */ /* Hote on 2410 error handling * @@ -19,11 +19,7 @@ * and change the policy on BREAK * * BJD, 04-Nov-2004 -*/ - -#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif + */ #include <linux/dmaengine.h> #include <linux/dma-mapping.h> @@ -44,33 +40,8 @@ #include <linux/clk.h> #include <linux/cpufreq.h> #include <linux/of.h> - #include <asm/irq.h> -#include "samsung.h" - -#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \ - !defined(MODULE) - -extern void printascii(const char *); - -__printf(1, 2) -static void dbg(const char *fmt, ...) -{ - va_list va; - char buff[256]; - - va_start(va, fmt); - vscnprintf(buff, sizeof(buff), fmt, va); - va_end(va); - - printascii(buff); -} - -#else -#define dbg(fmt, ...) do { if (0) no_printk(fmt, ##__VA_ARGS__); } while (0) -#endif - /* UART name and device definitions */ #define S3C24XX_SERIAL_NAME "ttySAC" @@ -81,14 +52,142 @@ static void dbg(const char *fmt, ...) #define S3C24XX_TX_DMA 2 #define S3C24XX_RX_PIO 1 #define S3C24XX_RX_DMA 2 -/* macros to change one thing to another */ - -#define tx_enabled(port) ((port)->unused[0]) -#define rx_enabled(port) ((port)->unused[1]) /* flag to ignore all characters coming in */ #define RXSTAT_DUMMY_READ (0x10000000) +struct s3c24xx_uart_info { + char *name; + unsigned int type; + unsigned int fifosize; + unsigned long rx_fifomask; + unsigned long rx_fifoshift; + unsigned long rx_fifofull; + unsigned long tx_fifomask; + unsigned long tx_fifoshift; + unsigned long tx_fifofull; + unsigned int def_clk_sel; + unsigned long num_clks; + unsigned long clksel_mask; + unsigned long clksel_shift; + + /* uart port features */ + + unsigned int has_divslot:1; +}; + +struct s3c24xx_serial_drv_data { + struct s3c24xx_uart_info *info; + struct s3c2410_uartcfg *def_cfg; + unsigned int fifosize[CONFIG_SERIAL_SAMSUNG_UARTS]; +}; + +struct s3c24xx_uart_dma { + unsigned int rx_chan_id; + unsigned int tx_chan_id; + + struct dma_slave_config rx_conf; + struct dma_slave_config tx_conf; + + struct dma_chan *rx_chan; + struct dma_chan *tx_chan; + + dma_addr_t rx_addr; + dma_addr_t tx_addr; + + dma_cookie_t rx_cookie; + dma_cookie_t tx_cookie; + + char *rx_buf; + + dma_addr_t tx_transfer_addr; + + size_t rx_size; + size_t tx_size; + + struct dma_async_tx_descriptor *tx_desc; + struct dma_async_tx_descriptor *rx_desc; + + int tx_bytes_requested; + int rx_bytes_requested; +}; + +struct s3c24xx_uart_port { + unsigned char rx_claimed; + unsigned char tx_claimed; + unsigned char rx_enabled; + unsigned char tx_enabled; + unsigned int pm_level; + unsigned long baudclk_rate; + unsigned int min_dma_size; + + unsigned int rx_irq; + unsigned int tx_irq; + + unsigned int tx_in_progress; + unsigned int tx_mode; + unsigned int rx_mode; + + struct s3c24xx_uart_info *info; + struct clk *clk; + struct clk *baudclk; + struct uart_port port; + struct s3c24xx_serial_drv_data *drv_data; + + /* reference to platform data */ + struct s3c2410_uartcfg *cfg; + + struct s3c24xx_uart_dma *dma; + +#ifdef CONFIG_ARM_S3C24XX_CPUFREQ + struct notifier_block freq_transition; +#endif +}; + +/* conversion functions */ + +#define s3c24xx_dev_to_port(__dev) dev_get_drvdata(__dev) + +/* register access controls */ + +#define portaddr(port, reg) ((port)->membase + (reg)) +#define portaddrl(port, reg) \ + ((unsigned long *)(unsigned long)((port)->membase + (reg))) + +#define rd_regb(port, reg) (readb_relaxed(portaddr(port, reg))) +#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg))) + +#define wr_regb(port, reg, val) writeb_relaxed(val, portaddr(port, reg)) +#define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg)) + +/* Byte-order aware bit setting/clearing functions. */ + +static inline void s3c24xx_set_bit(struct uart_port *port, int idx, + unsigned int reg) +{ + unsigned long flags; + u32 val; + + local_irq_save(flags); + val = rd_regl(port, reg); + val |= (1 << idx); + wr_regl(port, reg, val); + local_irq_restore(flags); +} + +static inline void s3c24xx_clear_bit(struct uart_port *port, int idx, + unsigned int reg) +{ + unsigned long flags; + u32 val; + + local_irq_save(flags); + val = rd_regl(port, reg); + val &= ~(1 << idx); + wr_regl(port, reg, val); + local_irq_restore(flags); +} + static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port) { return container_of(port, struct s3c24xx_uart_port, port); @@ -118,6 +217,7 @@ static int s3c24xx_serial_has_interrupt_mask(struct uart_port *port) static void s3c24xx_serial_rx_enable(struct uart_port *port) { + struct s3c24xx_uart_port *ourport = to_ourport(port); unsigned long flags; unsigned int ucon, ufcon; int count = 10000; @@ -135,12 +235,13 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port) ucon |= S3C2410_UCON_RXIRQMODE; wr_regl(port, S3C2410_UCON, ucon); - rx_enabled(port) = 1; + ourport->rx_enabled = 1; spin_unlock_irqrestore(&port->lock, flags); } static void s3c24xx_serial_rx_disable(struct uart_port *port) { + struct s3c24xx_uart_port *ourport = to_ourport(port); unsigned long flags; unsigned int ucon; @@ -150,7 +251,7 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port) ucon &= ~S3C2410_UCON_RXIRQMODE; wr_regl(port, S3C2410_UCON, ucon); - rx_enabled(port) = 0; + ourport->rx_enabled = 0; spin_unlock_irqrestore(&port->lock, flags); } @@ -162,7 +263,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) struct dma_tx_state state; int count; - if (!tx_enabled(port)) + if (!ourport->tx_enabled) return; if (s3c24xx_serial_has_interrupt_mask(port)) @@ -182,7 +283,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) port->icount.tx += count; } - tx_enabled(port) = 0; + ourport->tx_enabled = 0; ourport->tx_in_progress = 0; if (port->flags & UPF_CONS_FLOW) @@ -340,11 +441,11 @@ static void s3c24xx_serial_start_tx(struct uart_port *port) struct s3c24xx_uart_port *ourport = to_ourport(port); struct circ_buf *xmit = &port->state->xmit; - if (!tx_enabled(port)) { + if (!ourport->tx_enabled) { if (port->flags & UPF_CONS_FLOW) s3c24xx_serial_rx_disable(port); - tx_enabled(port) = 1; + ourport->tx_enabled = 1; if (!ourport->dma || !ourport->dma->tx_chan) s3c24xx_serial_start_tx_pio(ourport); } @@ -389,14 +490,14 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port) enum dma_status dma_status; unsigned int received; - if (rx_enabled(port)) { - dbg("s3c24xx_serial_stop_rx: port=%p\n", port); + if (ourport->rx_enabled) { + dev_dbg(port->dev, "stopping rx\n"); if (s3c24xx_serial_has_interrupt_mask(port)) s3c24xx_set_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM); else disable_irq_nosync(ourport->rx_irq); - rx_enabled(port) = 0; + ourport->rx_enabled = 0; } if (dma && dma->rx_chan) { dmaengine_pause(dma->tx_chan); @@ -546,7 +647,7 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport); static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id) { - unsigned int utrstat, ufstat, received; + unsigned int utrstat, received; struct s3c24xx_uart_port *ourport = dev_id; struct uart_port *port = &ourport->port; struct s3c24xx_uart_dma *dma = ourport->dma; @@ -556,7 +657,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id) struct dma_tx_state state; utrstat = rd_regl(port, S3C2410_UTRSTAT); - ufstat = rd_regl(port, S3C2410_UFSTAT); + rd_regl(port, S3C2410_UFSTAT); spin_lock_irqsave(&port->lock, flags); @@ -618,9 +719,9 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport) if (port->flags & UPF_CONS_FLOW) { int txe = s3c24xx_serial_txempty_nofifo(port); - if (rx_enabled(port)) { + if (ourport->rx_enabled) { if (!txe) { - rx_enabled(port) = 0; + ourport->rx_enabled = 0; continue; } } else { @@ -628,7 +729,7 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport) ufcon = rd_regl(port, S3C2410_UFCON); ufcon |= S3C2410_UFCON_RESETRX; wr_regl(port, S3C2410_UFCON, ufcon); - rx_enabled(port) = 1; + ourport->rx_enabled = 1; return; } continue; @@ -641,12 +742,13 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport) port->icount.rx++; if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) { - dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n", - ch, uerstat); + dev_dbg(port->dev, + "rxerr: port ch=0x%02x, rxs=0x%08x\n", + ch, uerstat); /* check for break */ if (uerstat & S3C2410_UERSTAT_BREAK) { - dbg("break!\n"); + dev_dbg(port->dev, "break!\n"); port->icount.brk++; if (uart_handle_break(port)) continue; /* Ignore character */ @@ -732,7 +834,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) /* if there isn't anything more to transmit, or the uart is now * stopped, disable the uart and exit - */ + */ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { s3c24xx_serial_stop_tx(port); @@ -978,7 +1080,7 @@ static void s3c24xx_serial_shutdown(struct uart_port *port) if (ourport->tx_claimed) { if (!s3c24xx_serial_has_interrupt_mask(port)) free_irq(ourport->tx_irq, ourport); - tx_enabled(port) = 0; + ourport->tx_enabled = 0; ourport->tx_claimed = 0; ourport->tx_mode = 0; } @@ -987,7 +1089,7 @@ static void s3c24xx_serial_shutdown(struct uart_port *port) if (!s3c24xx_serial_has_interrupt_mask(port)) free_irq(ourport->rx_irq, ourport); ourport->rx_claimed = 0; - rx_enabled(port) = 0; + ourport->rx_enabled = 0; } /* Clear pending interrupts and mask all interrupts */ @@ -1009,10 +1111,7 @@ static int s3c24xx_serial_startup(struct uart_port *port) struct s3c24xx_uart_port *ourport = to_ourport(port); int ret; - dbg("s3c24xx_serial_startup: port=%p (%08llx,%p)\n", - port, (unsigned long long)port->mapbase, port->membase); - - rx_enabled(port) = 1; + ourport->rx_enabled = 1; ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0, s3c24xx_serial_portname(port), ourport); @@ -1024,9 +1123,9 @@ static int s3c24xx_serial_startup(struct uart_port *port) ourport->rx_claimed = 1; - dbg("requesting tx irq...\n"); + dev_dbg(port->dev, "requesting tx irq...\n"); - tx_enabled(port) = 1; + ourport->tx_enabled = 1; ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0, s3c24xx_serial_portname(port), ourport); @@ -1038,10 +1137,9 @@ static int s3c24xx_serial_startup(struct uart_port *port) ourport->tx_claimed = 1; - dbg("s3c24xx_serial_startup ok\n"); - /* the port reset code should have done the correct - * register setup for the port controls */ + * register setup for the port controls + */ return ret; @@ -1057,9 +1155,6 @@ static int s3c64xx_serial_startup(struct uart_port *port) unsigned int ufcon; int ret; - dbg("s3c64xx_serial_startup: port=%p (%08llx,%p)\n", - port, (unsigned long long)port->mapbase, port->membase); - wr_regl(port, S3C64XX_UINTM, 0xf); if (ourport->dma) { ret = s3c24xx_serial_request_dma(ourport); @@ -1077,9 +1172,9 @@ static int s3c64xx_serial_startup(struct uart_port *port) } /* For compatibility with s3c24xx Soc's */ - rx_enabled(port) = 1; + ourport->rx_enabled = 1; ourport->rx_claimed = 1; - tx_enabled(port) = 0; + ourport->tx_enabled = 0; ourport->tx_claimed = 1; spin_lock_irqsave(&port->lock, flags); @@ -1097,7 +1192,6 @@ static int s3c64xx_serial_startup(struct uart_port *port) /* Enable Rx Interrupt */ s3c24xx_clear_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM); - dbg("s3c64xx_serial_startup ok\n"); return ret; } @@ -1145,7 +1239,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, * baud clocks (and the resultant actual baud rates) and then tries to * pick the closest one and select that. * -*/ + */ #define MAX_CLK_NAME_LENGTH 15 @@ -1315,29 +1409,30 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, if (cfg->has_fracval) { udivslot = (div & 15); - dbg("fracval = %04x\n", udivslot); + dev_dbg(port->dev, "fracval = %04x\n", udivslot); } else { udivslot = udivslot_table[div & 15]; - dbg("udivslot = %04x (div %d)\n", udivslot, div & 15); + dev_dbg(port->dev, "udivslot = %04x (div %d)\n", + udivslot, div & 15); } } switch (termios->c_cflag & CSIZE) { case CS5: - dbg("config: 5bits/char\n"); + dev_dbg(port->dev, "config: 5bits/char\n"); ulcon = S3C2410_LCON_CS5; break; case CS6: - dbg("config: 6bits/char\n"); + dev_dbg(port->dev, "config: 6bits/char\n"); ulcon = S3C2410_LCON_CS6; break; case CS7: - dbg("config: 7bits/char\n"); + dev_dbg(port->dev, "config: 7bits/char\n"); ulcon = S3C2410_LCON_CS7; break; case CS8: default: - dbg("config: 8bits/char\n"); + dev_dbg(port->dev, "config: 8bits/char\n"); ulcon = S3C2410_LCON_CS8; break; } @@ -1359,8 +1454,9 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, spin_lock_irqsave(&port->lock, flags); - dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n", - ulcon, quot, udivslot); + dev_dbg(port->dev, + "setting ulcon to %08x, brddiv to %d, udivslot %08x\n", + ulcon, quot, udivslot); wr_regl(port, S3C2410_ULCON, ulcon); wr_regl(port, S3C2410_UBRDIV, quot); @@ -1381,10 +1477,11 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, if (ourport->info->has_divslot) wr_regl(port, S3C2443_DIVSLOT, udivslot); - dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n", - rd_regl(port, S3C2410_ULCON), - rd_regl(port, S3C2410_UCON), - rd_regl(port, S3C2410_UFCON)); + dev_dbg(port->dev, + "uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n", + rd_regl(port, S3C2410_ULCON), + rd_regl(port, S3C2410_UCON), + rd_regl(port, S3C2410_UFCON)); /* * Update the per-port timeout. @@ -1442,6 +1539,7 @@ static void s3c24xx_serial_release_port(struct uart_port *port) static int s3c24xx_serial_request_port(struct uart_port *port) { const char *name = s3c24xx_serial_portname(port); + return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY; } @@ -1583,7 +1681,7 @@ s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = { /* s3c24xx_serial_resetport * * reset the fifos and other the settings. -*/ + */ static void s3c24xx_serial_resetport(struct uart_port *port, struct s3c2410_uartcfg *cfg) @@ -1637,7 +1735,8 @@ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb, if (val == CPUFREQ_PRECHANGE) { /* we should really shut the port down whilst the - * frequency change is in progress. */ + * frequency change is in progress. + */ } else if (val == CPUFREQ_POSTCHANGE) { struct ktermios *termios; @@ -1743,8 +1842,6 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, struct resource *res; int ret; - dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev); - if (platdev == NULL) return -ENODEV; @@ -1761,7 +1858,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, port->uartclk = 1; if (cfg->uart_flags & UPF_CONS_FLOW) { - dbg("s3c24xx_serial_init_port: enabling flow control\n"); + dev_dbg(port->dev, "enabling flow control\n"); port->flags |= UPF_CONS_FLOW; } @@ -1773,7 +1870,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, return -EINVAL; } - dbg("resource %pR)\n", res); + dev_dbg(port->dev, "resource %pR)\n", res); port->membase = devm_ioremap(port->dev, res->start, resource_size(res)); if (!port->membase) { @@ -1835,9 +1932,9 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, wr_regl(port, S3C64XX_UINTSP, 0xf); } - dbg("port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n", - &port->mapbase, port->membase, port->irq, - ourport->rx_irq, ourport->tx_irq, port->uartclk); + dev_dbg(port->dev, "port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n", + &port->mapbase, port->membase, port->irq, + ourport->rx_irq, ourport->tx_irq, port->uartclk); /* reset the fifos (and setup the uart) */ s3c24xx_serial_resetport(port, cfg); @@ -1851,7 +1948,10 @@ err: /* Device driver serial port probe */ +#ifdef CONFIG_OF static const struct of_device_id s3c24xx_uart_dt_match[]; +#endif + static int probe_index; static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data( @@ -1860,6 +1960,7 @@ static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data( #ifdef CONFIG_OF if (pdev->dev.of_node) { const struct of_device_id *match; + match = of_match_node(s3c24xx_uart_dt_match, pdev->dev.of_node); return (struct s3c24xx_serial_drv_data *)match->data; } @@ -1881,8 +1982,6 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) index = ret; } - dbg("s3c24xx_serial_probe(%p) %d\n", pdev, index); - if (index >= ARRAY_SIZE(s3c24xx_serial_ports)) { dev_err(&pdev->dev, "serial%d out of range\n", index); return -EINVAL; @@ -1909,6 +2008,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) ourport->port.fifosize = ourport->drv_data->fifosize[index]; else if (ourport->info->fifosize) ourport->port.fifosize = ourport->info->fifosize; + ourport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SAMSUNG_CONSOLE); /* * DMA transfers must be aligned at least to cache line size, @@ -1917,7 +2017,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) ourport->min_dma_size = max_t(int, ourport->port.fifosize, dma_get_cache_alignment()); - dbg("%s: initialising port %p...\n", __func__, ourport); + dev_dbg(&pdev->dev, "%s: initialising port %p...\n", __func__, ourport); ret = s3c24xx_serial_init_port(ourport, pdev); if (ret < 0) @@ -1931,7 +2031,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) } } - dbg("%s: adding port\n", __func__); + dev_dbg(&pdev->dev, "%s: adding port\n", __func__); uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); platform_set_drvdata(pdev, &ourport->port); @@ -2008,9 +2108,10 @@ static int s3c24xx_serial_resume_noirq(struct device *dev) /* restore IRQ mask */ if (s3c24xx_serial_has_interrupt_mask(port)) { unsigned int uintm = 0xf; - if (tx_enabled(port)) + + if (ourport->tx_enabled) uintm &= ~S3C64XX_UINTM_TXD_MSK; - if (rx_enabled(port)) + if (ourport->rx_enabled) uintm &= ~S3C64XX_UINTM_RXD_MSK; clk_prepare_enable(ourport->clk); if (!IS_ERR(ourport->baudclk)) @@ -2143,10 +2244,6 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, ucon = rd_regl(port, S3C2410_UCON); ubrdiv = rd_regl(port, S3C2410_UBRDIV); - dbg("s3c24xx_serial_get_options: port=%p\n" - "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n", - port, ulcon, ucon, ubrdiv); - if (s3c24xx_port_configured(ucon)) { switch (ulcon & S3C2410_LCON_CSMASK) { case S3C2410_LCON_CS5: @@ -2190,7 +2287,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, rate = 1; *baud = rate / (16 * (ubrdiv + 1)); - dbg("calculated baud %d\n", *baud); + dev_dbg(port->dev, "calculated baud %d\n", *baud); } } @@ -2204,9 +2301,6 @@ s3c24xx_serial_console_setup(struct console *co, char *options) int parity = 'n'; int flow = 'n'; - dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n", - co, co->index, options); - /* is this a valid port */ if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS) @@ -2221,8 +2315,6 @@ s3c24xx_serial_console_setup(struct console *co, char *options) cons_uart = port; - dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index); - /* * Check whether an invalid uart number has been specified, and * if so, search for the first available port that does have @@ -2233,7 +2325,7 @@ s3c24xx_serial_console_setup(struct console *co, char *options) else s3c24xx_serial_get_options(port, &baud, &parity, &bits); - dbg("s3c24xx_serial_console_setup: baud %d\n", baud); + dev_dbg(port->dev, "baud %d\n", baud); return uart_set_options(port, co, baud, parity, bits, flow); } @@ -2523,7 +2615,8 @@ static void samsung_early_putc(struct uart_port *port, int c) writeb(c, port->membase + S3C2410_UTXH); } -static void samsung_early_write(struct console *con, const char *s, unsigned n) +static void samsung_early_write(struct console *con, const char *s, + unsigned int n) { struct earlycon_device *dev = con->data; @@ -2572,7 +2665,7 @@ OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart", OF_EARLYCON_DECLARE(s3c6400, "samsung,s3c6400-uart", s3c2440_early_console_setup); -/* S5PV210, EXYNOS */ +/* S5PV210, Exynos */ static struct samsung_early_console_data s5pv210_early_console_data = { .txfull_mask = S5PV210_UFSTAT_TXFULL, }; diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c index 329aced26bd8..bd5e7e9938ce 100644 --- a/drivers/tty/serial/sb1250-duart.c +++ b/drivers/tty/serial/sb1250-duart.c @@ -15,10 +15,6 @@ * "BCM1250/BCM1125/BCM1125H User Manual", Broadcom Corporation */ -#if defined(CONFIG_SERIAL_SB1250_DUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/compiler.h> #include <linux/console.h> #include <linux/delay.h> @@ -668,7 +664,7 @@ static int sbd_map_port(struct uart_port *uport) struct sbd_duart *duart = sport->duart; if (!uport->membase) - uport->membase = ioremap_nocache(uport->mapbase, + uport->membase = ioremap(uport->mapbase, DUART_CHANREG_SPACING); if (!uport->membase) { printk(err); @@ -676,7 +672,7 @@ static int sbd_map_port(struct uart_port *uport) } if (!sport->memctrl) - sport->memctrl = ioremap_nocache(duart->mapctrl, + sport->memctrl = ioremap(duart->mapctrl, DUART_CHANREG_SPACING); if (!sport->memctrl) { printk(err); @@ -813,6 +809,7 @@ static void __init sbd_probe_duarts(void) uport->ops = &sbd_ops; uport->line = line; uport->mapbase = SBD_CHANREGS(line); + uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_SB1250_DUART_CONSOLE); } } } diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index d2b77aae42ae..10cc16a71f26 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -7,10 +7,6 @@ * Based on sc26xx.c, by Thomas Bogendörfer (tsbogend@alpha.franken.de) */ -#if defined(CONFIG_SERIAL_SCCNXP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/clk.h> #include <linux/delay.h> #include <linux/err.h> @@ -1000,6 +996,7 @@ static int sccnxp_probe(struct platform_device *pdev) s->port[i].regshift = s->pdata.reg_shift; s->port[i].uartclk = uartclk; s->port[i].ops = &sccnxp_ops; + s->port[i].has_sysrq = IS_ENABLED(CONFIG_SERIAL_SCCNXP_CONSOLE); uart_add_one_port(&s->uart, &s->port[i]); /* Set direction to input */ if (s->chip->flags & SCCNXP_HAVE_IO) diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index b6ace6290e23..33034b852a51 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -141,6 +141,7 @@ struct tegra_uart_port { int configured_rate; bool use_rx_pio; bool use_tx_pio; + bool rx_dma_active; }; static void tegra_uart_start_next_tx(struct tegra_uart_port *tup); @@ -533,11 +534,12 @@ static int tegra_uart_start_tx_dma(struct tegra_uart_port *tup, struct circ_buf *xmit = &tup->uport.state->xmit; dma_addr_t tx_phys_addr; - dma_sync_single_for_device(tup->uport.dev, tup->tx_dma_buf_phys, - UART_XMIT_SIZE, DMA_TO_DEVICE); - tup->tx_bytes = count & ~(0xF); tx_phys_addr = tup->tx_dma_buf_phys + xmit->tail; + + dma_sync_single_for_device(tup->uport.dev, tx_phys_addr, + tup->tx_bytes, DMA_TO_DEVICE); + tup->tx_dma_desc = dmaengine_prep_slave_single(tup->tx_dma_chan, tx_phys_addr, tup->tx_bytes, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); @@ -679,7 +681,7 @@ static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup, return; dma_sync_single_for_cpu(tup->uport.dev, tup->rx_dma_buf_phys, - TEGRA_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE); + count, DMA_FROM_DEVICE); copied = tty_insert_flip_string(tty, ((unsigned char *)(tup->rx_dma_buf_virt)), count); if (copied != count) { @@ -687,7 +689,7 @@ static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup, dev_err(tup->uport.dev, "RxData copy to tty layer failed\n"); } dma_sync_single_for_device(tup->uport.dev, tup->rx_dma_buf_phys, - TEGRA_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE); + count, DMA_TO_DEVICE); } static void tegra_uart_rx_buffer_push(struct tegra_uart_port *tup, @@ -731,6 +733,7 @@ static void tegra_uart_rx_dma_complete(void *args) if (tup->rts_active) set_rts(tup, false); + tup->rx_dma_active = false; tegra_uart_rx_buffer_push(tup, 0); tegra_uart_start_rx_dma(tup); @@ -742,18 +745,27 @@ done: spin_unlock_irqrestore(&u->lock, flags); } -static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup) +static void tegra_uart_terminate_rx_dma(struct tegra_uart_port *tup) { struct dma_tx_state state; - /* Deactivate flow control to stop sender */ - if (tup->rts_active) - set_rts(tup, false); + if (!tup->rx_dma_active) + return; dmaengine_terminate_all(tup->rx_dma_chan); dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state); + tegra_uart_rx_buffer_push(tup, state.residue); - tegra_uart_start_rx_dma(tup); + tup->rx_dma_active = false; +} + +static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup) +{ + /* Deactivate flow control to stop sender */ + if (tup->rts_active) + set_rts(tup, false); + + tegra_uart_terminate_rx_dma(tup); if (tup->rts_active) set_rts(tup, true); @@ -763,6 +775,9 @@ static int tegra_uart_start_rx_dma(struct tegra_uart_port *tup) { unsigned int count = TEGRA_UART_RX_DMA_BUFFER_SIZE; + if (tup->rx_dma_active) + return 0; + tup->rx_dma_desc = dmaengine_prep_slave_single(tup->rx_dma_chan, tup->rx_dma_buf_phys, count, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); @@ -771,10 +786,9 @@ static int tegra_uart_start_rx_dma(struct tegra_uart_port *tup) return -EIO; } + tup->rx_dma_active = true; tup->rx_dma_desc->callback = tegra_uart_rx_dma_complete; tup->rx_dma_desc->callback_param = tup; - dma_sync_single_for_device(tup->uport.dev, tup->rx_dma_buf_phys, - count, DMA_TO_DEVICE); tup->rx_bytes_requested = count; tup->rx_cookie = dmaengine_submit(tup->rx_dma_desc); dma_async_issue_pending(tup->rx_dma_chan); @@ -820,6 +834,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data) struct uart_port *u = &tup->uport; unsigned long iir; unsigned long ier; + bool is_rx_start = false; bool is_rx_int = false; unsigned long flags; @@ -832,10 +847,12 @@ static irqreturn_t tegra_uart_isr(int irq, void *data) if (tup->rx_in_progress) { ier = tup->ier_shadow; ier |= (UART_IER_RLSI | UART_IER_RTOIE | - TEGRA_UART_IER_EORD); + TEGRA_UART_IER_EORD | UART_IER_RDI); tup->ier_shadow = ier; tegra_uart_write(tup, ier, UART_IER); } + } else if (is_rx_start) { + tegra_uart_start_rx_dma(tup); } spin_unlock_irqrestore(&u->lock, flags); return IRQ_HANDLED; @@ -854,17 +871,23 @@ static irqreturn_t tegra_uart_isr(int irq, void *data) case 4: /* End of data */ case 6: /* Rx timeout */ - case 2: /* Receive */ - if (!tup->use_rx_pio && !is_rx_int) { - is_rx_int = true; + if (!tup->use_rx_pio) { + is_rx_int = tup->rx_in_progress; /* Disable Rx interrupts */ ier = tup->ier_shadow; - ier |= UART_IER_RDI; - tegra_uart_write(tup, ier, UART_IER); ier &= ~(UART_IER_RDI | UART_IER_RLSI | UART_IER_RTOIE | TEGRA_UART_IER_EORD); tup->ier_shadow = ier; tegra_uart_write(tup, ier, UART_IER); + break; + } + /* Fall through */ + case 2: /* Receive */ + if (!tup->use_rx_pio) { + is_rx_start = tup->rx_in_progress; + tup->ier_shadow &= ~UART_IER_RDI; + tegra_uart_write(tup, tup->ier_shadow, + UART_IER); } else { do_handle_rx_pio(tup); } @@ -886,7 +909,6 @@ static void tegra_uart_stop_rx(struct uart_port *u) { struct tegra_uart_port *tup = to_tegra_uport(u); struct tty_port *port = &tup->uport.state->port; - struct dma_tx_state state; unsigned long ier; if (tup->rts_active) @@ -903,13 +925,11 @@ static void tegra_uart_stop_rx(struct uart_port *u) tup->ier_shadow = ier; tegra_uart_write(tup, ier, UART_IER); tup->rx_in_progress = 0; - if (tup->rx_dma_chan && !tup->use_rx_pio) { - dmaengine_terminate_all(tup->rx_dma_chan); - dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state); - tegra_uart_rx_buffer_push(tup, state.residue); - } else { + + if (!tup->use_rx_pio) + tegra_uart_terminate_rx_dma(tup); + else tegra_uart_handle_rx_pio(tup, port); - } } static void tegra_uart_hw_deinit(struct tegra_uart_port *tup) @@ -1052,12 +1072,6 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup) tup->lcr_shadow = TEGRA_UART_DEFAULT_LSR; tup->fcr_shadow |= UART_FCR_DMA_SELECT; tegra_uart_write(tup, tup->fcr_shadow, UART_FCR); - - ret = tegra_uart_start_rx_dma(tup); - if (ret < 0) { - dev_err(tup->uport.dev, "Not able to start Rx DMA\n"); - return ret; - } } else { tegra_uart_write(tup, tup->fcr_shadow, UART_FCR); } @@ -1067,10 +1081,6 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup) * Enable IE_RXS for the receive status interrupts like line errros. * Enable IE_RX_TIMEOUT to get the bytes which cannot be DMA'd. * - * If using DMA mode, enable EORD instead of receive interrupt which - * will interrupt after the UART is done with the receive instead of - * the interrupt when the FIFO "threshold" is reached. - * * EORD is different interrupt than RX_TIMEOUT - RX_TIMEOUT occurs when * the DATA is sitting in the FIFO and couldn't be transferred to the * DMA as the DMA size alignment (4 bytes) is not met. EORD will be @@ -1081,11 +1091,14 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup) * both the EORD as well as RX_TIMEOUT - SW sees RX_TIMEOUT first * then the EORD. */ + tup->ier_shadow = UART_IER_RLSI | UART_IER_RTOIE | UART_IER_RDI; + + /* + * If using DMA mode, enable EORD interrupt to notify about RX + * completion. + */ if (!tup->use_rx_pio) - tup->ier_shadow = UART_IER_RLSI | UART_IER_RTOIE | - TEGRA_UART_IER_EORD; - else - tup->ier_shadow = UART_IER_RLSI | UART_IER_RTOIE | UART_IER_RDI; + tup->ier_shadow |= TEGRA_UART_IER_EORD; tegra_uart_write(tup, tup->ier_shadow, UART_IER); return 0; @@ -1140,6 +1153,9 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup, dma_release_channel(dma_chan); return -ENOMEM; } + dma_sync_single_for_device(tup->uport.dev, dma_phys, + TEGRA_UART_RX_DMA_BUFFER_SIZE, + DMA_TO_DEVICE); dma_sconfig.src_addr = tup->uport.mapbase; dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; dma_sconfig.src_maxburst = tup->cdata->max_dma_burst_bytes; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index b0a6eb106edb..76e506ee335c 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2603,6 +2603,7 @@ struct tty_driver *uart_console_device(struct console *co, int *index) *index = co->index; return p->tty_driver; } +EXPORT_SYMBOL_GPL(uart_console_device); static ssize_t uart_get_attr_uartclk(struct device *dev, struct device_attribute *attr, char *buf) @@ -2834,6 +2835,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) if (uport->cons && uport->dev) of_console_check(uport->dev->of_node, uport->cons->name, uport->line); + tty_port_link_device(port, drv->tty_driver, uport->line); uart_configure_port(drv, state, uport); port->console = uart_console(uport); @@ -3080,6 +3082,89 @@ void uart_insert_char(struct uart_port *port, unsigned int status, } EXPORT_SYMBOL_GPL(uart_insert_char); +int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) +{ + if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) + return 0; + + if (!port->has_sysrq || !port->sysrq) + return 0; + + if (ch && time_before(jiffies, port->sysrq)) { + handle_sysrq(ch); + port->sysrq = 0; + return 1; + } + port->sysrq = 0; + + return 0; +} +EXPORT_SYMBOL_GPL(uart_handle_sysrq_char); + +int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch) +{ + if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) + return 0; + + if (!port->has_sysrq || !port->sysrq) + return 0; + + if (ch && time_before(jiffies, port->sysrq)) { + port->sysrq_ch = ch; + port->sysrq = 0; + return 1; + } + port->sysrq = 0; + + return 0; +} +EXPORT_SYMBOL_GPL(uart_prepare_sysrq_char); + +void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) +{ + int sysrq_ch; + + if (!port->has_sysrq) { + spin_unlock_irqrestore(&port->lock, irqflags); + return; + } + + 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); + +/* + * We do the SysRQ and SAK checking like this... + */ +int uart_handle_break(struct uart_port *port) +{ + struct uart_state *state = port->state; + + 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->flags & UPF_SAK) + do_SAK(state->port.tty); + return 0; +} +EXPORT_SYMBOL_GPL(uart_handle_break); + EXPORT_SYMBOL(uart_write_wakeup); EXPORT_SYMBOL(uart_register_driver); EXPORT_SYMBOL(uart_unregister_driver); diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c index d22ccb32aa9b..b4d89e31730e 100644 --- a/drivers/tty/serial/serial_txx9.c +++ b/drivers/tty/serial/serial_txx9.c @@ -12,10 +12,6 @@ * Serial driver for TX3927/TX4927/TX4925/TX4938 internal SIO controller */ -#if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/ioport.h> #include <linux/init.h> @@ -1095,6 +1091,7 @@ static int serial_txx9_probe(struct platform_device *dev) port.flags = p->flags; port.mapbase = p->mapbase; port.dev = &dev->dev; + port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_TXX9_CONSOLE); ret = serial_txx9_register_port(&port); if (ret < 0) { dev_err(&dev->dev, "unable to register port at index %d " diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 58bf9d496ba5..c073aa7001c4 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -15,10 +15,6 @@ * Modified to support SH7300 SCIF. Takashi Kusuda (Jun 2003). * Removed SH7300 support (Jul 2007). */ -#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #undef DEBUG #include <linux/clk.h> @@ -2680,7 +2676,7 @@ static int sci_remap_port(struct uart_port *port) return 0; if (port->dev->of_node || (port->flags & UPF_IOREMAP)) { - port->membase = ioremap_nocache(port->mapbase, sport->reg_size); + port->membase = ioremap(port->mapbase, sport->reg_size); if (unlikely(!port->membase)) { dev_err(port->dev, "can't remap port#%d\n", port->line); return -ENXIO; @@ -2887,6 +2883,7 @@ static int sci_init_single(struct platform_device *dev, port->ops = &sci_uart_ops; port->iotype = UPIO_MEM; port->line = index; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_SH_SCI_CONSOLE); res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (res == NULL) @@ -3015,12 +3012,9 @@ static void serial_console_write(struct console *co, const char *s, unsigned long flags; int locked = 1; -#if defined(SUPPORT_SYSRQ) if (port->sysrq) locked = 0; - else -#endif - if (oops_in_progress) + else if (oops_in_progress) locked = spin_trylock_irqsave(&port->lock, flags); else spin_lock_irqsave(&port->lock, flags); diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index 31df23502562..3d3c70634589 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -3,10 +3,6 @@ * Copyright (C) 2012-2015 Spreadtrum Communications Inc. */ -#if defined(CONFIG_SERIAL_SPRD_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/clk.h> #include <linux/console.h> #include <linux/delay.h> @@ -679,6 +675,9 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id) if (ims & SPRD_IMSR_TIMEOUT) serial_out(port, SPRD_ICLR, SPRD_ICLR_TIMEOUT); + if (ims & SPRD_IMSR_BREAK_DETECT) + serial_out(port, SPRD_ICLR, SPRD_IMSR_BREAK_DETECT); + if (ims & (SPRD_IMSR_RX_FIFO_FULL | SPRD_IMSR_BREAK_DETECT | SPRD_IMSR_TIMEOUT)) sprd_rx(port); @@ -1227,6 +1226,7 @@ static int sprd_probe(struct platform_device *pdev) up->fifosize = SPRD_FIFO_SIZE; up->ops = &serial_sprd_ops; up->flags = UPF_BOOT_AUTOCONF; + up->has_sysrq = IS_ENABLED(CONFIG_SERIAL_SPRD_CONSOLE); ret = sprd_clk_init(up); if (ret) diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index 7971997cdead..e7048515a79c 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -5,10 +5,6 @@ * Copyright (C) 2003-2013 STMicroelectronics (R&D) Limited */ -#if defined(CONFIG_SERIAL_ST_ASC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/serial.h> #include <linux/console.h> @@ -508,7 +504,6 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct asc_port *ascport = to_asc_port(port); - struct device_node *np = port->dev->of_node; struct gpio_desc *gpiod; unsigned int baud; u32 ctrl_val; @@ -570,13 +565,12 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios, pinctrl_select_state(ascport->pinctrl, ascport->states[NO_HW_FLOWCTRL]); - gpiod = devm_fwnode_get_gpiod_from_child(port->dev, - "rts", - &np->fwnode, - GPIOD_OUT_LOW, - np->name); - if (!IS_ERR(gpiod)) + gpiod = devm_gpiod_get(port->dev, "rts", GPIOD_OUT_LOW); + if (!IS_ERR(gpiod)) { + gpiod_set_consumer_name(gpiod, + port->dev->of_node->name); ascport->rts = gpiod; + } } } @@ -730,6 +724,7 @@ static int asc_init_port(struct asc_port *ascport, port->fifosize = ASC_FIFO_SIZE; port->dev = &pdev->dev; port->irq = platform_get_irq(pdev, 0); + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_ST_ASC_CONSOLE); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); port->membase = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 2f72514d63ed..5e93e8d40f59 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -8,10 +8,6 @@ * Inspired by st-asc.c from STMicroelectronics (c) */ -#if defined(CONFIG_SERIAL_STM32_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/clk.h> #include <linux/console.h> #include <linux/delay.h> @@ -926,6 +922,7 @@ static int stm32_init_port(struct stm32_port *stm32port, port->ops = &stm32_uart_ops; port->dev = &pdev->dev; port->fifosize = stm32port->info->cfg.fifosize; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_STM32_CONSOLE); ret = platform_get_irq(pdev, 0); if (ret <= 0) diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index f8503f8fc44e..eafada8fb6fa 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c @@ -25,10 +25,6 @@ #include <asm/irq.h> #include <asm/setup.h> -#if defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/serial_core.h> #include <linux/sunserialcore.h> @@ -552,6 +548,7 @@ static int hv_probe(struct platform_device *op) sunhv_port = port; + port->has_sysrq = 1; port->line = 0; port->ops = &sunhv_pops; port->type = PORT_SUNHV; diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index 72131b5e132e..1eb703c980e0 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c @@ -40,10 +40,6 @@ #include <asm/prom.h> #include <asm/setup.h> -#if defined(CONFIG_SERIAL_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/serial_core.h> #include <linux/sunserialcore.h> @@ -985,6 +981,7 @@ static int sunsab_init_one(struct uart_sunsab_port *up, up->port.fifosize = SAB82532_XMIT_FIFO_SIZE; up->port.iotype = UPIO_MEM; + up->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SUNSAB_CONSOLE); writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc); diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 4db6aaa330b2..8ce9a7a256e5 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -44,10 +44,6 @@ #include <asm/prom.h> #include <asm/setup.h> -#if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/serial_core.h> #include <linux/sunserialcore.h> @@ -1475,6 +1471,7 @@ static int su_probe(struct platform_device *op) up->port.type = PORT_UNKNOWN; up->port.uartclk = (SU_BASE_BAUD * 16); + up->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SUNSU_CONSOLE); err = 0; if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) { diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index bc7af8b08a72..103ab8c556e7 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -40,10 +40,6 @@ #include <asm/prom.h> #include <asm/setup.h> -#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/serial_core.h> #include <linux/sunserialcore.h> @@ -1444,6 +1440,7 @@ static int zs_probe(struct platform_device *op) up[0].port.line = (inst * 2) + 0; up[0].port.dev = &op->dev; up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A; + up[0].port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SUNZILOG_CONSOLE); if (keyboard_mouse) up[0].flags |= SUNZILOG_FLAG_CONS_KEYB; sunzilog_init_hw(&up[0]); @@ -1461,6 +1458,7 @@ static int zs_probe(struct platform_device *op) up[1].port.line = (inst * 2) + 1; up[1].port.dev = &op->dev; up[1].flags |= 0; + up[1].port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SUNZILOG_CONSOLE); if (keyboard_mouse) up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE; sunzilog_init_hw(&up[1]); diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index a0555ae2b1ef..3c8c662c69e2 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c @@ -32,7 +32,11 @@ #include <soc/fsl/qe/ucc_slow.h> #include <linux/firmware.h> -#include <asm/reg.h> +#include <soc/fsl/cpm.h> + +#ifdef CONFIG_PPC32 +#include <asm/reg.h> /* mfspr, SPRN_SVR */ +#endif /* * The GUMR flag for Soft UART. This would normally be defined in qe.h, @@ -257,11 +261,11 @@ static unsigned int qe_uart_tx_empty(struct uart_port *port) struct qe_bd *bdp = qe_port->tx_bd_base; while (1) { - if (in_be16(&bdp->status) & BD_SC_READY) + if (qe_ioread16be(&bdp->status) & BD_SC_READY) /* This BD is not done, so return "not done" */ return 0; - if (in_be16(&bdp->status) & BD_SC_WRAP) + if (qe_ioread16be(&bdp->status) & BD_SC_WRAP) /* * This BD is done and it's the last one, so return * "done" @@ -307,7 +311,7 @@ static void qe_uart_stop_tx(struct uart_port *port) struct uart_qe_port *qe_port = container_of(port, struct uart_qe_port, port); - clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_TX); + qe_clrbits_be16(&qe_port->uccp->uccm, UCC_UART_UCCE_TX); } /* @@ -332,20 +336,18 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port) struct uart_port *port = &qe_port->port; struct circ_buf *xmit = &port->state->xmit; - bdp = qe_port->rx_cur; - /* Handle xon/xoff */ if (port->x_char) { /* Pick next descriptor and fill from buffer */ bdp = qe_port->tx_cur; - p = qe2cpu_addr(bdp->buf, qe_port); + p = qe2cpu_addr(be32_to_cpu(bdp->buf), qe_port); *p++ = port->x_char; - out_be16(&bdp->length, 1); - setbits16(&bdp->status, BD_SC_READY); + qe_iowrite16be(1, &bdp->length); + qe_setbits_be16(&bdp->status, BD_SC_READY); /* Get next BD. */ - if (in_be16(&bdp->status) & BD_SC_WRAP) + if (qe_ioread16be(&bdp->status) & BD_SC_WRAP) bdp = qe_port->tx_bd_base; else bdp++; @@ -364,10 +366,10 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port) /* Pick next descriptor and fill from buffer */ bdp = qe_port->tx_cur; - while (!(in_be16(&bdp->status) & BD_SC_READY) && + while (!(qe_ioread16be(&bdp->status) & BD_SC_READY) && (xmit->tail != xmit->head)) { count = 0; - p = qe2cpu_addr(bdp->buf, qe_port); + p = qe2cpu_addr(be32_to_cpu(bdp->buf), qe_port); while (count < qe_port->tx_fifosize) { *p++ = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); @@ -377,11 +379,11 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port) break; } - out_be16(&bdp->length, count); - setbits16(&bdp->status, BD_SC_READY); + qe_iowrite16be(count, &bdp->length); + qe_setbits_be16(&bdp->status, BD_SC_READY); /* Get next BD. */ - if (in_be16(&bdp->status) & BD_SC_WRAP) + if (qe_ioread16be(&bdp->status) & BD_SC_WRAP) bdp = qe_port->tx_bd_base; else bdp++; @@ -414,12 +416,12 @@ static void qe_uart_start_tx(struct uart_port *port) container_of(port, struct uart_qe_port, port); /* If we currently are transmitting, then just return */ - if (in_be16(&qe_port->uccp->uccm) & UCC_UART_UCCE_TX) + if (qe_ioread16be(&qe_port->uccp->uccm) & UCC_UART_UCCE_TX) return; /* Otherwise, pump the port and start transmission */ if (qe_uart_tx_pump(qe_port)) - setbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_TX); + qe_setbits_be16(&qe_port->uccp->uccm, UCC_UART_UCCE_TX); } /* @@ -430,7 +432,7 @@ static void qe_uart_stop_rx(struct uart_port *port) struct uart_qe_port *qe_port = container_of(port, struct uart_qe_port, port); - clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX); + qe_clrbits_be16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX); } /* Start or stop sending break signal @@ -469,14 +471,14 @@ static void qe_uart_int_rx(struct uart_qe_port *qe_port) */ bdp = qe_port->rx_cur; while (1) { - status = in_be16(&bdp->status); + status = qe_ioread16be(&bdp->status); /* If this one is empty, then we assume we've read them all */ if (status & BD_SC_EMPTY) break; /* get number of characters, and check space in RX buffer */ - i = in_be16(&bdp->length); + i = qe_ioread16be(&bdp->length); /* If we don't have enough room in RX buffer for the entire BD, * then we try later, which will be the next RX interrupt. @@ -487,7 +489,7 @@ static void qe_uart_int_rx(struct uart_qe_port *qe_port) } /* get pointer */ - cp = qe2cpu_addr(bdp->buf, qe_port); + cp = qe2cpu_addr(be32_to_cpu(bdp->buf), qe_port); /* loop through the buffer */ while (i-- > 0) { @@ -507,9 +509,10 @@ error_return: } /* This BD is ready to be used again. Clear status. get next */ - clrsetbits_be16(&bdp->status, BD_SC_BR | BD_SC_FR | BD_SC_PR | - BD_SC_OV | BD_SC_ID, BD_SC_EMPTY); - if (in_be16(&bdp->status) & BD_SC_WRAP) + qe_clrsetbits_be16(&bdp->status, + BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID, + BD_SC_EMPTY); + if (qe_ioread16be(&bdp->status) & BD_SC_WRAP) bdp = qe_port->rx_bd_base; else bdp++; @@ -551,9 +554,7 @@ handle_error: /* Overrun does not affect the current character ! */ if (status & BD_SC_OV) tty_insert_flip_char(tport, 0, TTY_OVERRUN); -#ifdef SUPPORT_SYSRQ port->sysrq = 0; -#endif goto error_return; } @@ -568,8 +569,8 @@ static irqreturn_t qe_uart_int(int irq, void *data) u16 events; /* Clear the interrupts */ - events = in_be16(&uccp->ucce); - out_be16(&uccp->ucce, events); + events = qe_ioread16be(&uccp->ucce); + qe_iowrite16be(events, &uccp->ucce); if (events & UCC_UART_UCCE_BRKE) uart_handle_break(&qe_port->port); @@ -600,17 +601,17 @@ static void qe_uart_initbd(struct uart_qe_port *qe_port) bdp = qe_port->rx_bd_base; qe_port->rx_cur = qe_port->rx_bd_base; for (i = 0; i < (qe_port->rx_nrfifos - 1); i++) { - out_be16(&bdp->status, BD_SC_EMPTY | BD_SC_INTRPT); - out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port)); - out_be16(&bdp->length, 0); + qe_iowrite16be(BD_SC_EMPTY | BD_SC_INTRPT, &bdp->status); + qe_iowrite32be(cpu2qe_addr(bd_virt, qe_port), &bdp->buf); + qe_iowrite16be(0, &bdp->length); bd_virt += qe_port->rx_fifosize; bdp++; } /* */ - out_be16(&bdp->status, BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT); - out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port)); - out_be16(&bdp->length, 0); + qe_iowrite16be(BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT, &bdp->status); + qe_iowrite32be(cpu2qe_addr(bd_virt, qe_port), &bdp->buf); + qe_iowrite16be(0, &bdp->length); /* Set the physical address of the host memory * buffers in the buffer descriptors, and the @@ -621,21 +622,21 @@ static void qe_uart_initbd(struct uart_qe_port *qe_port) qe_port->tx_cur = qe_port->tx_bd_base; bdp = qe_port->tx_bd_base; for (i = 0; i < (qe_port->tx_nrfifos - 1); i++) { - out_be16(&bdp->status, BD_SC_INTRPT); - out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port)); - out_be16(&bdp->length, 0); + qe_iowrite16be(BD_SC_INTRPT, &bdp->status); + qe_iowrite32be(cpu2qe_addr(bd_virt, qe_port), &bdp->buf); + qe_iowrite16be(0, &bdp->length); bd_virt += qe_port->tx_fifosize; bdp++; } /* Loopback requires the preamble bit to be set on the first TX BD */ #ifdef LOOPBACK - setbits16(&qe_port->tx_cur->status, BD_SC_P); + qe_setbits_be16(&qe_port->tx_cur->status, BD_SC_P); #endif - out_be16(&bdp->status, BD_SC_WRAP | BD_SC_INTRPT); - out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port)); - out_be16(&bdp->length, 0); + qe_iowrite16be(BD_SC_WRAP | BD_SC_INTRPT, &bdp->status); + qe_iowrite32be(cpu2qe_addr(bd_virt, qe_port), &bdp->buf); + qe_iowrite16be(0, &bdp->length); } /* @@ -657,78 +658,74 @@ static void qe_uart_init_ucc(struct uart_qe_port *qe_port) ucc_slow_disable(qe_port->us_private, COMM_DIR_RX_AND_TX); /* Program the UCC UART parameter RAM */ - out_8(&uccup->common.rbmr, UCC_BMR_GBL | UCC_BMR_BO_BE); - out_8(&uccup->common.tbmr, UCC_BMR_GBL | UCC_BMR_BO_BE); - out_be16(&uccup->common.mrblr, qe_port->rx_fifosize); - out_be16(&uccup->maxidl, 0x10); - out_be16(&uccup->brkcr, 1); - out_be16(&uccup->parec, 0); - out_be16(&uccup->frmec, 0); - out_be16(&uccup->nosec, 0); - out_be16(&uccup->brkec, 0); - out_be16(&uccup->uaddr[0], 0); - out_be16(&uccup->uaddr[1], 0); - out_be16(&uccup->toseq, 0); + qe_iowrite8(UCC_BMR_GBL | UCC_BMR_BO_BE, &uccup->common.rbmr); + qe_iowrite8(UCC_BMR_GBL | UCC_BMR_BO_BE, &uccup->common.tbmr); + qe_iowrite16be(qe_port->rx_fifosize, &uccup->common.mrblr); + qe_iowrite16be(0x10, &uccup->maxidl); + qe_iowrite16be(1, &uccup->brkcr); + qe_iowrite16be(0, &uccup->parec); + qe_iowrite16be(0, &uccup->frmec); + qe_iowrite16be(0, &uccup->nosec); + qe_iowrite16be(0, &uccup->brkec); + qe_iowrite16be(0, &uccup->uaddr[0]); + qe_iowrite16be(0, &uccup->uaddr[1]); + qe_iowrite16be(0, &uccup->toseq); for (i = 0; i < 8; i++) - out_be16(&uccup->cchars[i], 0xC000); - out_be16(&uccup->rccm, 0xc0ff); + qe_iowrite16be(0xC000, &uccup->cchars[i]); + qe_iowrite16be(0xc0ff, &uccup->rccm); /* Configure the GUMR registers for UART */ if (soft_uart) { /* Soft-UART requires a 1X multiplier for TX */ - clrsetbits_be32(&uccp->gumr_l, - UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK | - UCC_SLOW_GUMR_L_RDCR_MASK, - UCC_SLOW_GUMR_L_MODE_UART | UCC_SLOW_GUMR_L_TDCR_1 | - UCC_SLOW_GUMR_L_RDCR_16); - - clrsetbits_be32(&uccp->gumr_h, UCC_SLOW_GUMR_H_RFW, - UCC_SLOW_GUMR_H_TRX | UCC_SLOW_GUMR_H_TTX); + qe_clrsetbits_be32(&uccp->gumr_l, + UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK | UCC_SLOW_GUMR_L_RDCR_MASK, + UCC_SLOW_GUMR_L_MODE_UART | UCC_SLOW_GUMR_L_TDCR_1 | UCC_SLOW_GUMR_L_RDCR_16); + + qe_clrsetbits_be32(&uccp->gumr_h, UCC_SLOW_GUMR_H_RFW, + UCC_SLOW_GUMR_H_TRX | UCC_SLOW_GUMR_H_TTX); } else { - clrsetbits_be32(&uccp->gumr_l, - UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK | - UCC_SLOW_GUMR_L_RDCR_MASK, - UCC_SLOW_GUMR_L_MODE_UART | UCC_SLOW_GUMR_L_TDCR_16 | - UCC_SLOW_GUMR_L_RDCR_16); - - clrsetbits_be32(&uccp->gumr_h, - UCC_SLOW_GUMR_H_TRX | UCC_SLOW_GUMR_H_TTX, - UCC_SLOW_GUMR_H_RFW); + qe_clrsetbits_be32(&uccp->gumr_l, + UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK | UCC_SLOW_GUMR_L_RDCR_MASK, + UCC_SLOW_GUMR_L_MODE_UART | UCC_SLOW_GUMR_L_TDCR_16 | UCC_SLOW_GUMR_L_RDCR_16); + + qe_clrsetbits_be32(&uccp->gumr_h, + UCC_SLOW_GUMR_H_TRX | UCC_SLOW_GUMR_H_TTX, + UCC_SLOW_GUMR_H_RFW); } #ifdef LOOPBACK - clrsetbits_be32(&uccp->gumr_l, UCC_SLOW_GUMR_L_DIAG_MASK, - UCC_SLOW_GUMR_L_DIAG_LOOP); - clrsetbits_be32(&uccp->gumr_h, - UCC_SLOW_GUMR_H_CTSP | UCC_SLOW_GUMR_H_RSYN, - UCC_SLOW_GUMR_H_CDS); + qe_clrsetbits_be32(&uccp->gumr_l, UCC_SLOW_GUMR_L_DIAG_MASK, + UCC_SLOW_GUMR_L_DIAG_LOOP); + qe_clrsetbits_be32(&uccp->gumr_h, + UCC_SLOW_GUMR_H_CTSP | UCC_SLOW_GUMR_H_RSYN, + UCC_SLOW_GUMR_H_CDS); #endif /* Disable rx interrupts and clear all pending events. */ - out_be16(&uccp->uccm, 0); - out_be16(&uccp->ucce, 0xffff); - out_be16(&uccp->udsr, 0x7e7e); + qe_iowrite16be(0, &uccp->uccm); + qe_iowrite16be(0xffff, &uccp->ucce); + qe_iowrite16be(0x7e7e, &uccp->udsr); /* Initialize UPSMR */ - out_be16(&uccp->upsmr, 0); + qe_iowrite16be(0, &uccp->upsmr); if (soft_uart) { - out_be16(&uccup->supsmr, 0x30); - out_be16(&uccup->res92, 0); - out_be32(&uccup->rx_state, 0); - out_be32(&uccup->rx_cnt, 0); - out_8(&uccup->rx_bitmark, 0); - out_8(&uccup->rx_length, 10); - out_be32(&uccup->dump_ptr, 0x4000); - out_8(&uccup->rx_temp_dlst_qe, 0); - out_be32(&uccup->rx_frame_rem, 0); - out_8(&uccup->rx_frame_rem_size, 0); + qe_iowrite16be(0x30, &uccup->supsmr); + qe_iowrite16be(0, &uccup->res92); + qe_iowrite32be(0, &uccup->rx_state); + qe_iowrite32be(0, &uccup->rx_cnt); + qe_iowrite8(0, &uccup->rx_bitmark); + qe_iowrite8(10, &uccup->rx_length); + qe_iowrite32be(0x4000, &uccup->dump_ptr); + qe_iowrite8(0, &uccup->rx_temp_dlst_qe); + qe_iowrite32be(0, &uccup->rx_frame_rem); + qe_iowrite8(0, &uccup->rx_frame_rem_size); /* Soft-UART requires TX to be 1X */ - out_8(&uccup->tx_mode, - UCC_UART_TX_STATE_UART | UCC_UART_TX_STATE_X1); - out_be16(&uccup->tx_state, 0); - out_8(&uccup->resD4, 0); - out_be16(&uccup->resD5, 0); + qe_iowrite8(UCC_UART_TX_STATE_UART | UCC_UART_TX_STATE_X1, + &uccup->tx_mode); + qe_iowrite16be(0, &uccup->tx_state); + qe_iowrite8(0, &uccup->resD4); + qe_iowrite16be(0, &uccup->resD5); /* Set UART mode. * Enable receive and transmit. @@ -742,22 +739,19 @@ static void qe_uart_init_ucc(struct uart_qe_port *qe_port) * ... * 6.Receiver must use 16x over sampling */ - clrsetbits_be32(&uccp->gumr_l, - UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK | - UCC_SLOW_GUMR_L_RDCR_MASK, - UCC_SLOW_GUMR_L_MODE_QMC | UCC_SLOW_GUMR_L_TDCR_16 | - UCC_SLOW_GUMR_L_RDCR_16); + qe_clrsetbits_be32(&uccp->gumr_l, + UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK | UCC_SLOW_GUMR_L_RDCR_MASK, + UCC_SLOW_GUMR_L_MODE_QMC | UCC_SLOW_GUMR_L_TDCR_16 | UCC_SLOW_GUMR_L_RDCR_16); - clrsetbits_be32(&uccp->gumr_h, - UCC_SLOW_GUMR_H_RFW | UCC_SLOW_GUMR_H_RSYN, - UCC_SLOW_GUMR_H_SUART | UCC_SLOW_GUMR_H_TRX | - UCC_SLOW_GUMR_H_TTX | UCC_SLOW_GUMR_H_TFL); + qe_clrsetbits_be32(&uccp->gumr_h, + UCC_SLOW_GUMR_H_RFW | UCC_SLOW_GUMR_H_RSYN, + UCC_SLOW_GUMR_H_SUART | UCC_SLOW_GUMR_H_TRX | UCC_SLOW_GUMR_H_TTX | UCC_SLOW_GUMR_H_TFL); #ifdef LOOPBACK - clrsetbits_be32(&uccp->gumr_l, UCC_SLOW_GUMR_L_DIAG_MASK, - UCC_SLOW_GUMR_L_DIAG_LOOP); - clrbits32(&uccp->gumr_h, UCC_SLOW_GUMR_H_CTSP | - UCC_SLOW_GUMR_H_CDS); + qe_clrsetbits_be32(&uccp->gumr_l, UCC_SLOW_GUMR_L_DIAG_MASK, + UCC_SLOW_GUMR_L_DIAG_LOOP); + qe_clrbits_be32(&uccp->gumr_h, + UCC_SLOW_GUMR_H_CTSP | UCC_SLOW_GUMR_H_CDS); #endif cecr_subblock = ucc_slow_get_qe_cr_subblock(qe_port->ucc_num); @@ -800,7 +794,7 @@ static int qe_uart_startup(struct uart_port *port) } /* Startup rx-int */ - setbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX); + qe_setbits_be16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX); ucc_slow_enable(qe_port->us_private, COMM_DIR_RX_AND_TX); return 0; @@ -836,7 +830,7 @@ static void qe_uart_shutdown(struct uart_port *port) /* Stop uarts */ ucc_slow_disable(qe_port->us_private, COMM_DIR_RX_AND_TX); - clrbits16(&uccp->uccm, UCC_UART_UCCE_TX | UCC_UART_UCCE_RX); + qe_clrbits_be16(&uccp->uccm, UCC_UART_UCCE_TX | UCC_UART_UCCE_RX); /* Shut them really down and reinit buffer descriptors */ ucc_slow_graceful_stop_tx(qe_port->us_private); @@ -856,9 +850,9 @@ static void qe_uart_set_termios(struct uart_port *port, struct ucc_slow __iomem *uccp = qe_port->uccp; unsigned int baud; unsigned long flags; - u16 upsmr = in_be16(&uccp->upsmr); + u16 upsmr = qe_ioread16be(&uccp->upsmr); struct ucc_uart_pram __iomem *uccup = qe_port->uccup; - u16 supsmr = in_be16(&uccup->supsmr); + u16 supsmr = qe_ioread16be(&uccup->supsmr); u8 char_length = 2; /* 1 + CL + PEN + 1 + SL */ /* Character length programmed into the mode register is the @@ -956,10 +950,10 @@ static void qe_uart_set_termios(struct uart_port *port, /* Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); - out_be16(&uccp->upsmr, upsmr); + qe_iowrite16be(upsmr, &uccp->upsmr); if (soft_uart) { - out_be16(&uccup->supsmr, supsmr); - out_8(&uccup->rx_length, char_length); + qe_iowrite16be(supsmr, &uccup->supsmr); + qe_iowrite8(char_length, &uccup->rx_length); /* Soft-UART requires a 1X multiplier for TX */ qe_setbrg(qe_port->us_info.rx_clock, baud, 16); @@ -1101,6 +1095,8 @@ static const struct uart_ops qe_uart_pops = { .verify_port = qe_uart_verify_port, }; + +#ifdef CONFIG_PPC32 /* * Obtain the SOC model number and revision level * @@ -1188,70 +1184,86 @@ static void uart_firmware_cont(const struct firmware *fw, void *context) release_firmware(fw); } -static int ucc_uart_probe(struct platform_device *ofdev) +static int soft_uart_init(struct platform_device *ofdev) { struct device_node *np = ofdev->dev.of_node; - const unsigned int *iprop; /* Integer OF properties */ - const char *sprop; /* String OF properties */ - struct uart_qe_port *qe_port = NULL; - struct resource res; + struct qe_firmware_info *qe_fw_info; int ret; - /* - * Determine if we need Soft-UART mode - */ if (of_find_property(np, "soft-uart", NULL)) { dev_dbg(&ofdev->dev, "using Soft-UART mode\n"); soft_uart = 1; + } else { + return 0; } - /* - * If we are using Soft-UART, determine if we need to upload the - * firmware, too. - */ - if (soft_uart) { - struct qe_firmware_info *qe_fw_info; - - qe_fw_info = qe_get_firmware_info(); - - /* Check if the firmware has been uploaded. */ - if (qe_fw_info && strstr(qe_fw_info->id, "Soft-UART")) { - firmware_loaded = 1; - } else { - char filename[32]; - unsigned int soc; - unsigned int rev_h; - unsigned int rev_l; - - soc = soc_info(&rev_h, &rev_l); - if (!soc) { - dev_err(&ofdev->dev, "unknown CPU model\n"); - return -ENXIO; - } - sprintf(filename, "fsl_qe_ucode_uart_%u_%u%u.bin", - soc, rev_h, rev_l); - - dev_info(&ofdev->dev, "waiting for firmware %s\n", - filename); + qe_fw_info = qe_get_firmware_info(); - /* - * We call request_firmware_nowait instead of - * request_firmware so that the driver can load and - * initialize the ports without holding up the rest of - * the kernel. If hotplug support is enabled in the - * kernel, then we use it. - */ - ret = request_firmware_nowait(THIS_MODULE, - FW_ACTION_HOTPLUG, filename, &ofdev->dev, - GFP_KERNEL, &ofdev->dev, uart_firmware_cont); - if (ret) { - dev_err(&ofdev->dev, - "could not load firmware %s\n", - filename); - return ret; - } + /* Check if the firmware has been uploaded. */ + if (qe_fw_info && strstr(qe_fw_info->id, "Soft-UART")) { + firmware_loaded = 1; + } else { + char filename[32]; + unsigned int soc; + unsigned int rev_h; + unsigned int rev_l; + + soc = soc_info(&rev_h, &rev_l); + if (!soc) { + dev_err(&ofdev->dev, "unknown CPU model\n"); + return -ENXIO; + } + sprintf(filename, "fsl_qe_ucode_uart_%u_%u%u.bin", + soc, rev_h, rev_l); + + dev_info(&ofdev->dev, "waiting for firmware %s\n", + filename); + + /* + * We call request_firmware_nowait instead of + * request_firmware so that the driver can load and + * initialize the ports without holding up the rest of + * the kernel. If hotplug support is enabled in the + * kernel, then we use it. + */ + ret = request_firmware_nowait(THIS_MODULE, + FW_ACTION_HOTPLUG, filename, &ofdev->dev, + GFP_KERNEL, &ofdev->dev, uart_firmware_cont); + if (ret) { + dev_err(&ofdev->dev, + "could not load firmware %s\n", + filename); + return ret; } } + return 0; +} + +#else /* !CONFIG_PPC32 */ + +static int soft_uart_init(struct platform_device *ofdev) +{ + return 0; +} + +#endif + + +static int ucc_uart_probe(struct platform_device *ofdev) +{ + struct device_node *np = ofdev->dev.of_node; + const char *sprop; /* String OF properties */ + struct uart_qe_port *qe_port = NULL; + struct resource res; + u32 val; + int ret; + + /* + * Determine if we need Soft-UART mode + */ + ret = soft_uart_init(ofdev); + if (ret) + return ret; qe_port = kzalloc(sizeof(struct uart_qe_port), GFP_KERNEL); if (!qe_port) { @@ -1274,23 +1286,20 @@ static int ucc_uart_probe(struct platform_device *ofdev) /* Get the UCC number (device ID) */ /* UCCs are numbered 1-7 */ - iprop = of_get_property(np, "cell-index", NULL); - if (!iprop) { - iprop = of_get_property(np, "device-id", NULL); - if (!iprop) { - dev_err(&ofdev->dev, "UCC is unspecified in " - "device tree\n"); + if (of_property_read_u32(np, "cell-index", &val)) { + if (of_property_read_u32(np, "device-id", &val)) { + dev_err(&ofdev->dev, "UCC is unspecified in device tree\n"); ret = -EINVAL; goto out_free; } } - if ((*iprop < 1) || (*iprop > UCC_MAX_NUM)) { - dev_err(&ofdev->dev, "no support for UCC%u\n", *iprop); + if (val < 1 || val > UCC_MAX_NUM) { + dev_err(&ofdev->dev, "no support for UCC%u\n", val); ret = -ENODEV; goto out_free; } - qe_port->ucc_num = *iprop - 1; + qe_port->ucc_num = val - 1; /* * In the future, we should not require the BRG to be specified in the @@ -1334,13 +1343,12 @@ static int ucc_uart_probe(struct platform_device *ofdev) } /* Get the port number, numbered 0-3 */ - iprop = of_get_property(np, "port-number", NULL); - if (!iprop) { + if (of_property_read_u32(np, "port-number", &val)) { dev_err(&ofdev->dev, "missing port-number in device tree\n"); ret = -EINVAL; goto out_free; } - qe_port->port.line = *iprop; + qe_port->port.line = val; if (qe_port->port.line >= UCC_MAX_UART) { dev_err(&ofdev->dev, "port-number must be 0-%u\n", UCC_MAX_UART - 1); @@ -1370,31 +1378,36 @@ static int ucc_uart_probe(struct platform_device *ofdev) } } - iprop = of_get_property(np, "brg-frequency", NULL); - if (!iprop) { + if (of_property_read_u32(np, "brg-frequency", &val)) { dev_err(&ofdev->dev, "missing brg-frequency in device tree\n"); ret = -EINVAL; goto out_np; } - if (*iprop) - qe_port->port.uartclk = *iprop; + if (val) + qe_port->port.uartclk = val; else { + if (!IS_ENABLED(CONFIG_PPC32)) { + dev_err(&ofdev->dev, + "invalid brg-frequency in device tree\n"); + ret = -EINVAL; + goto out_np; + } + /* * Older versions of U-Boot do not initialize the brg-frequency * property, so in this case we assume the BRG frequency is * half the QE bus frequency. */ - iprop = of_get_property(np, "bus-frequency", NULL); - if (!iprop) { + if (of_property_read_u32(np, "bus-frequency", &val)) { dev_err(&ofdev->dev, "missing QE bus-frequency in device tree\n"); ret = -EINVAL; goto out_np; } - if (*iprop) - qe_port->port.uartclk = *iprop / 2; + if (val) + qe_port->port.uartclk = val / 2; else { dev_err(&ofdev->dev, "invalid QE bus-frequency in device tree\n"); diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c index 6d106e33f842..eeb4b6568776 100644 --- a/drivers/tty/serial/vr41xx_siu.c +++ b/drivers/tty/serial/vr41xx_siu.c @@ -7,10 +7,6 @@ * Based on drivers/serial/8250.c, by Russell King. */ -#if defined(CONFIG_SERIAL_VR41XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/console.h> #include <linux/errno.h> #include <linux/init.h> @@ -869,6 +865,7 @@ static int siu_probe(struct platform_device *dev) port = &siu_uart_ports[i]; port->ops = &siu_uart_ops; port->dev = &dev->dev; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_VR41XX_CONSOLE); retval = uart_add_one_port(&siu_uart_driver, port); if (retval < 0) { diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 3d58e9b34553..764e992438b2 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -7,10 +7,6 @@ * Author: Robert Love <rlove@google.com> */ -#if defined(CONFIG_SERIAL_VT8500_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -# define SUPPORT_SYSRQ -#endif - #include <linux/hrtimer.h> #include <linux/delay.h> #include <linux/io.h> @@ -703,6 +699,7 @@ static int vt8500_serial_probe(struct platform_device *pdev) vt8500_port->uart.line = port; vt8500_port->uart.dev = &pdev->dev; vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; + vt8500_port->uart.has_sysrq = IS_ENABLED(CONFIG_SERIAL_VT8500_CONSOLE); /* Serial core uses the magic "16" everywhere - adjust for it */ vt8500_port->uart.uartclk = 16 * clk_get_rate(vt8500_port->clk) / diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 4e55bc327a54..98db9dc168ff 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -9,10 +9,6 @@ * in the code. */ -#if defined(CONFIG_SERIAL_XILINX_PS_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/platform_device.h> #include <linux/serial.h> #include <linux/console.h> @@ -158,6 +154,16 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); #define CDNS_UART_MODEMCR_DTR 0x00000001 /* Data Terminal Ready */ /* + * Modem Status register: + * The read/write Modem Status register reports the interface with the modem + * or data set, or a peripheral device emulating a modem. + */ +#define CDNS_UART_MODEMSR_DCD BIT(7) /* Data Carrier Detect */ +#define CDNS_UART_MODEMSR_RI BIT(6) /* Ting Indicator */ +#define CDNS_UART_MODEMSR_DSR BIT(5) /* Data Set Ready */ +#define CDNS_UART_MODEMSR_CTS BIT(4) /* Clear To Send */ + +/* * Channel Status Register: * The channel status register (CSR) is provided to enable the control logic * to monitor the status of bits in the channel interrupt status register, @@ -684,7 +690,7 @@ static void cdns_uart_break_ctl(struct uart_port *port, int ctl) static void cdns_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - unsigned int cval = 0; + u32 cval = 0; unsigned int baud, minbaud, maxbaud; unsigned long flags; unsigned int ctrl_reg, mode_reg, val; @@ -805,6 +811,13 @@ static void cdns_uart_set_termios(struct uart_port *port, cval |= mode_reg & 1; writel(cval, port->membase + CDNS_UART_MR); + cval = readl(port->membase + CDNS_UART_MODEMCR); + if (termios->c_cflag & CRTSCTS) + cval |= CDNS_UART_MODEMCR_FCM; + else + cval &= ~CDNS_UART_MODEMCR_FCM; + writel(cval, port->membase + CDNS_UART_MODEMCR); + spin_unlock_irqrestore(&port->lock, flags); } @@ -1007,12 +1020,24 @@ static void cdns_uart_config_port(struct uart_port *port, int flags) */ static unsigned int cdns_uart_get_mctrl(struct uart_port *port) { + u32 val; + unsigned int mctrl = 0; struct cdns_uart *cdns_uart_data = port->private_data; if (cdns_uart_data->cts_override) - return 0; - - return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + + val = readl(port->membase + CDNS_UART_MODEMSR); + if (val & CDNS_UART_MODEMSR_CTS) + mctrl |= TIOCM_CTS; + if (val & CDNS_UART_MODEMSR_DSR) + mctrl |= TIOCM_DSR; + if (val & CDNS_UART_MODEMSR_RI) + mctrl |= TIOCM_RNG; + if (val & CDNS_UART_MODEMSR_DCD) + mctrl |= TIOCM_CAR; + + return mctrl; } static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) @@ -1027,12 +1052,13 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) val = readl(port->membase + CDNS_UART_MODEMCR); mode_reg = readl(port->membase + CDNS_UART_MR); - val &= ~(CDNS_UART_MODEMCR_RTS | CDNS_UART_MODEMCR_DTR | - CDNS_UART_MODEMCR_FCM); + val &= ~(CDNS_UART_MODEMCR_RTS | CDNS_UART_MODEMCR_DTR); mode_reg &= ~CDNS_UART_MR_CHMODE_MASK; - if (mctrl & TIOCM_RTS || mctrl & TIOCM_DTR) - val |= CDNS_UART_MODEMCR_FCM; + if (mctrl & TIOCM_RTS) + val |= CDNS_UART_MODEMCR_RTS; + if (mctrl & TIOCM_DTR) + val |= CDNS_UART_MODEMCR_DTR; if (mctrl & TIOCM_LOOP) mode_reg |= CDNS_UART_MR_CHMODE_L_LOOP; else @@ -1634,6 +1660,7 @@ static int cdns_uart_probe(struct platform_device *pdev) port->flags = UPF_BOOT_AUTOCONF; port->ops = &cdns_uart_ops; port->fifosize = CDNS_UART_FIFO_SIZE; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_XILINX_PS_UART_CONSOLE); /* * Register the port. diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c index b03d3e458ea2..4b4f604646a7 100644 --- a/drivers/tty/serial/zs.c +++ b/drivers/tty/serial/zs.c @@ -44,10 +44,6 @@ * complicated and prevents the use of some automatic modes of operation. */ -#if defined(CONFIG_SERIAL_ZS_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/bug.h> #include <linux/console.h> #include <linux/delay.h> @@ -992,7 +988,7 @@ static void zs_release_port(struct uart_port *uport) static int zs_map_port(struct uart_port *uport) { if (!uport->membase) - uport->membase = ioremap_nocache(uport->mapbase, + uport->membase = ioremap(uport->mapbase, ZS_CHAN_IO_SIZE); if (!uport->membase) { printk(KERN_ERR "zs: Cannot map MMIO\n"); @@ -1106,6 +1102,7 @@ static int __init zs_probe_sccs(void) zport->scc = &zs_sccs[chip]; zport->clk_mode = 16; + uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_ZS_CONSOLE); uport->irq = zs_parms.irq[chip]; uport->uartclk = ZS_CLOCK; uport->fifosize = 1; |