diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-12-03 14:09:14 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-12-03 14:09:14 -0800 |
commit | 537bd0a159a041fad72d257d755205cef77582e1 (patch) | |
tree | f7e226de10589b8dfd162b80d4859dd5c00ac62e /drivers/tty | |
parent | c3bed3b20e40ab44b98ac5f0471a5bd92a802f5a (diff) | |
parent | 27ed14d0ecb38516b6f3c6fdcd62c25c9454f979 (diff) | |
download | blackbird-op-linux-537bd0a159a041fad72d257d755205cef77582e1.tar.gz blackbird-op-linux-537bd0a159a041fad72d257d755205cef77582e1.zip |
Merge tag 'tty-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial updates from Greg KH:
"Here is the "big" tty and serial driver patches for 5.5-rc1.
It's a bit later in the merge window than normal as I wanted to make
sure some last-minute patches applied to it were all sane. They seem
to be :)
There's a lot of little stuff in here, for the tty core, and for lots
of serial drivers:
- reverts of uartlite serial driver patches that were wrong
- msm-serial driver fixes
- serial core updates and fixes
- tty core fixes
- serial driver dma mapping api changes
- lots of other tiny fixes and updates for serial drivers
All of these have been in linux-next for a while with no reported
issues"
* tag 'tty-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (58 commits)
Revert "serial/8250: Add support for NI-Serial PXI/PXIe+485 devices"
vcs: prevent write access to vcsu devices
tty: vt: keyboard: reject invalid keycodes
tty: don't crash in tty_init_dev when missing tty_port
serial: stm32: fix clearing interrupt error flags
tty: Fix Kconfig indentation, continued
serial: serial_core: Perform NULL checks for break_ctl ops
tty: remove unused argument from tty_open_by_driver()
tty: Fix Kconfig indentation
{tty: serial, nand: onenand}: samsung: rename to fix build warning
serial: ifx6x60: add missed pm_runtime_disable
serial: pl011: Fix DMA ->flush_buffer()
Revert "serial-uartlite: Move the uart register"
Revert "serial-uartlite: Add get serial id if not provided"
Revert "serial-uartlite: Do not use static struct uart_driver out of probe()"
Revert "serial-uartlite: Add runtime support"
Revert "serial-uartlite: Change logic how console_port is setup"
Revert "serial-uartlite: Use allocated structure instead of static ones"
tty: serial: msm_serial: Use dma_request_chan() directly for channel request
tty: serial: tegra: Use dma_request_chan() directly for channel request
...
Diffstat (limited to 'drivers/tty')
36 files changed, 641 insertions, 702 deletions
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index c7623f99ac0f..a312cb33a99b 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -82,20 +82,20 @@ config HW_CONSOLE default y config VT_HW_CONSOLE_BINDING - bool "Support for binding and unbinding console drivers" - depends on HW_CONSOLE - ---help--- - The virtual terminal is the device that interacts with the physical - terminal through console drivers. On these systems, at least one - console driver is loaded. In other configurations, additional console - drivers may be enabled, such as the framebuffer console. If more than - 1 console driver is enabled, setting this to 'y' will allow you to - select the console driver that will serve as the backend for the - virtual terminals. - - See <file:Documentation/driver-api/console.rst> for more - information. For framebuffer console users, please refer to - <file:Documentation/fb/fbcon.rst>. + bool "Support for binding and unbinding console drivers" + depends on HW_CONSOLE + ---help--- + The virtual terminal is the device that interacts with the physical + terminal through console drivers. On these systems, at least one + console driver is loaded. In other configurations, additional console + drivers may be enabled, such as the framebuffer console. If more than + 1 console driver is enabled, setting this to 'y' will allow you to + select the console driver that will serve as the backend for the + virtual terminals. + + See <file:Documentation/driver-api/console.rst> for more + information. For framebuffer console users, please refer to + <file:Documentation/fb/fbcon.rst>. config UNIX98_PTYS bool "Unix98 PTY support" if EXPERT @@ -173,15 +173,15 @@ config ROCKETPORT depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) help This driver supports Comtrol RocketPort and RocketModem PCI boards. - These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or - modems. For information about the RocketPort/RocketModem boards - and this driver read <file:Documentation/driver-api/serial/rocket.rst>. + These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or + modems. For information about the RocketPort/RocketModem boards + and this driver read <file:Documentation/driver-api/serial/rocket.rst>. To compile this driver as a module, choose M here: the module will be called rocket. If you want to compile this driver into the kernel, say Y here. If - you don't have a Comtrol RocketPort/RocketModem card installed, say N. + you don't have a Comtrol RocketPort/RocketModem card installed, say N. config CYCLADES tristate "Cyclades async mux support" @@ -437,8 +437,8 @@ config MIPS_EJTAG_FDC_KGDB depends on MIPS_EJTAG_FDC_TTY && KGDB default y help - This enables the use of KGDB over an FDC channel, allowing KGDB to be - used remotely or when a serial port isn't available. + This enables the use of KGDB over an FDC channel, allowing KGDB to be + used remotely or when a serial port isn't available. config MIPS_EJTAG_FDC_KGDB_CHAN int "KGDB FDC channel" diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 8330fd809a05..13f63c01c589 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -22,18 +22,8 @@ * */ -/* - * Serial driver configuration section. Here are the various options: - * - * SERIAL_PARANOIA_CHECK - * Check the magic number for the async_structure where - * ever possible. - */ - #include <linux/delay.h> -#undef SERIAL_PARANOIA_CHECK - /* Set of debugging defines */ #undef SERIAL_DEBUG_INTR @@ -132,28 +122,6 @@ static struct serial_state rs_table[1]; #define serial_isroot() (capable(CAP_SYS_ADMIN)) - -static inline int serial_paranoia_check(struct serial_state *info, - char *name, const char *routine) -{ -#ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = - "Warning: bad magic number for serial struct (%s) in %s\n"; - static const char *badinfo = - "Warning: null async_struct for (%s) in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - if (info->magic != SERIAL_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#endif - return 0; -} - /* some serial hardware definitions */ #define SDR_OVRUN (1<<15) #define SDR_RBF (1<<14) @@ -189,9 +157,6 @@ static void rs_stop(struct tty_struct *tty) struct serial_state *info = tty->driver_data; unsigned long flags; - if (serial_paranoia_check(info, tty->name, "rs_stop")) - return; - local_irq_save(flags); if (info->IER & UART_IER_THRI) { info->IER &= ~UART_IER_THRI; @@ -209,9 +174,6 @@ static void rs_start(struct tty_struct *tty) struct serial_state *info = tty->driver_data; unsigned long flags; - if (serial_paranoia_check(info, tty->name, "rs_start")) - return; - local_irq_save(flags); if (info->xmit.head != info->xmit.tail && info->xmit.buf @@ -783,9 +745,6 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch) info = tty->driver_data; - if (serial_paranoia_check(info, tty->name, "rs_put_char")) - return 0; - if (!info->xmit.buf) return 0; @@ -808,9 +767,6 @@ static void rs_flush_chars(struct tty_struct *tty) struct serial_state *info = tty->driver_data; unsigned long flags; - if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) - return; - if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped @@ -833,9 +789,6 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count struct serial_state *info = tty->driver_data; unsigned long flags; - if (serial_paranoia_check(info, tty->name, "rs_write")) - return 0; - if (!info->xmit.buf) return 0; @@ -878,8 +831,6 @@ static int rs_write_room(struct tty_struct *tty) { struct serial_state *info = tty->driver_data; - if (serial_paranoia_check(info, tty->name, "rs_write_room")) - return 0; return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); } @@ -887,8 +838,6 @@ static int rs_chars_in_buffer(struct tty_struct *tty) { struct serial_state *info = tty->driver_data; - if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) - return 0; return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); } @@ -897,8 +846,6 @@ static void rs_flush_buffer(struct tty_struct *tty) struct serial_state *info = tty->driver_data; unsigned long flags; - if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) - return; local_irq_save(flags); info->xmit.head = info->xmit.tail = 0; local_irq_restore(flags); @@ -914,9 +861,6 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) struct serial_state *info = tty->driver_data; unsigned long flags; - if (serial_paranoia_check(info, tty->name, "rs_send_xchar")) - return; - info->x_char = ch; if (ch) { /* Make sure transmit interrupts are on */ @@ -952,9 +896,6 @@ static void rs_throttle(struct tty_struct * tty) printk("throttle %s ....\n", tty_name(tty)); #endif - if (serial_paranoia_check(info, tty->name, "rs_throttle")) - return; - if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty)); @@ -974,9 +915,6 @@ static void rs_unthrottle(struct tty_struct * tty) printk("unthrottle %s ....\n", tty_name(tty)); #endif - if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) - return; - if (I_IXOFF(tty)) { if (info->x_char) info->x_char = 0; @@ -1109,8 +1047,6 @@ static int rs_tiocmget(struct tty_struct *tty) unsigned char control, status; unsigned long flags; - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) - return -ENODEV; if (tty_io_error(tty)) return -EIO; @@ -1131,8 +1067,6 @@ static int rs_tiocmset(struct tty_struct *tty, unsigned int set, struct serial_state *info = tty->driver_data; unsigned long flags; - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) - return -ENODEV; if (tty_io_error(tty)) return -EIO; @@ -1155,12 +1089,8 @@ static int rs_tiocmset(struct tty_struct *tty, unsigned int set, */ static int rs_break(struct tty_struct *tty, int break_state) { - struct serial_state *info = tty->driver_data; unsigned long flags; - if (serial_paranoia_check(info, tty->name, "rs_break")) - return -EINVAL; - local_irq_save(flags); if (break_state == -1) custom.adkcon = AC_SETCLR | AC_UARTBRK; @@ -1212,9 +1142,6 @@ static int rs_ioctl(struct tty_struct *tty, DEFINE_WAIT(wait); int ret; - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) - return -ENODEV; - if ((cmd != TIOCSERCONFIG) && (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { if (tty_io_error(tty)) @@ -1333,9 +1260,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp) struct serial_state *state = tty->driver_data; struct tty_port *port = &state->tport; - if (serial_paranoia_check(state, tty->name, "rs_close")) - return; - if (tty_port_close_start(port, tty, filp) == 0) return; @@ -1379,9 +1303,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) unsigned long orig_jiffies, char_time; int lsr; - if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) - return; - if (info->xmit_fifo_size == 0) return; /* Just in case.... */ @@ -1440,9 +1361,6 @@ static void rs_hangup(struct tty_struct *tty) { struct serial_state *info = tty->driver_data; - if (serial_paranoia_check(info, tty->name, "rs_hangup")) - return; - rs_flush_buffer(tty); shutdown(tty, info); info->tport.count = 0; @@ -1467,8 +1385,6 @@ static int rs_open(struct tty_struct *tty, struct file * filp) port->tty = tty; tty->driver_data = info; tty->port = port; - if (serial_paranoia_check(info, tty->name, "rs_open")) - return -ENODEV; port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig index 4487a6b9acc8..6a3c97d345a0 100644 --- a/drivers/tty/hvc/Kconfig +++ b/drivers/tty/hvc/Kconfig @@ -70,22 +70,22 @@ config HVC_XEN_FRONTEND Xen driver for secondary virtual consoles config HVC_UDBG - bool "udbg based fake hypervisor console" - depends on PPC - select HVC_DRIVER - help - This is meant to be used during HW bring up or debugging when - no other console mechanism exist but udbg, to get you a quick - console for userspace. Do NOT enable in production kernels. + bool "udbg based fake hypervisor console" + depends on PPC + select HVC_DRIVER + help + This is meant to be used during HW bring up or debugging when + no other console mechanism exist but udbg, to get you a quick + console for userspace. Do NOT enable in production kernels. config HVC_DCC - bool "ARM JTAG DCC console" - depends on ARM || ARM64 - select HVC_DRIVER - help - This console uses the JTAG DCC on ARM to create a console under the HVC - driver. This console is used through a JTAG only on ARM. If you don't have - a JTAG then you probably don't want this option. + bool "ARM JTAG DCC console" + depends on ARM || ARM64 + select HVC_DRIVER + help + This console uses the JTAG DCC on ARM to create a console under the HVC + driver. This console is used through a JTAG only on ARM. If you don't have + a JTAG then you probably don't want this option. config HVC_RISCV_SBI bool "RISC-V SBI console support" diff --git a/drivers/tty/hvc/hvc_dcc.c b/drivers/tty/hvc/hvc_dcc.c index 02629a1f193d..8e0edb7d93fd 100644 --- a/drivers/tty/hvc/hvc_dcc.c +++ b/drivers/tty/hvc/hvc_dcc.c @@ -1,7 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved. */ +#include <linux/console.h> #include <linux/init.h> +#include <linux/serial.h> +#include <linux/serial_core.h> #include <asm/dcc.h> #include <asm/processor.h> @@ -12,6 +15,31 @@ #define DCC_STATUS_RX (1 << 30) #define DCC_STATUS_TX (1 << 29) +static void dcc_uart_console_putchar(struct uart_port *port, int ch) +{ + while (__dcc_getstatus() & DCC_STATUS_TX) + cpu_relax(); + + __dcc_putchar(ch); +} + +static void dcc_early_write(struct console *con, const char *s, unsigned n) +{ + struct earlycon_device *dev = con->data; + + uart_console_write(&dev->port, s, n, dcc_uart_console_putchar); +} + +static int __init dcc_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + device->con->write = dcc_early_write; + + return 0; +} + +EARLYCON_DECLARE(dcc, dcc_early_console_setup); + static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count) { int i; diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 5ba6816ebf81..fbaa4ec85560 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1222,22 +1222,28 @@ static int set_config(struct tty_struct *tty, struct r_port *info, */ static int get_ports(struct r_port *info, struct rocket_ports __user *retports) { - struct rocket_ports tmp; - int board; + struct rocket_ports *tmp; + int board, ret = 0; - memset(&tmp, 0, sizeof (tmp)); - tmp.tty_major = rocket_driver->major; + tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + tmp->tty_major = rocket_driver->major; for (board = 0; board < 4; board++) { - tmp.rocketModel[board].model = rocketModel[board].model; - strcpy(tmp.rocketModel[board].modelString, rocketModel[board].modelString); - tmp.rocketModel[board].numPorts = rocketModel[board].numPorts; - tmp.rocketModel[board].loadrm2 = rocketModel[board].loadrm2; - tmp.rocketModel[board].startingPortNumber = rocketModel[board].startingPortNumber; - } - if (copy_to_user(retports, &tmp, sizeof (*retports))) - return -EFAULT; - return 0; + tmp->rocketModel[board].model = rocketModel[board].model; + strcpy(tmp->rocketModel[board].modelString, + rocketModel[board].modelString); + tmp->rocketModel[board].numPorts = rocketModel[board].numPorts; + tmp->rocketModel[board].loadrm2 = rocketModel[board].loadrm2; + tmp->rocketModel[board].startingPortNumber = + rocketModel[board].startingPortNumber; + } + if (copy_to_user(retports, tmp, sizeof(*retports))) + ret = -EFAULT; + kfree(tmp); + return ret; } static int reset_rm2(struct r_port *info, void __user *arg) diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index a0ac16ee6575..226adeec2aed 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -552,16 +552,97 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl) } #ifdef CONFIG_ACPI + +#define SERDEV_ACPI_MAX_SCAN_DEPTH 32 + +struct acpi_serdev_lookup { + acpi_handle device_handle; + acpi_handle controller_handle; + int n; + int index; +}; + +static int acpi_serdev_parse_resource(struct acpi_resource *ares, void *data) +{ + struct acpi_serdev_lookup *lookup = data; + struct acpi_resource_uart_serialbus *sb; + acpi_status status; + + if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) + return 1; + + if (ares->data.common_serial_bus.type != ACPI_RESOURCE_SERIAL_TYPE_UART) + return 1; + + if (lookup->index != -1 && lookup->n++ != lookup->index) + return 1; + + sb = &ares->data.uart_serial_bus; + + status = acpi_get_handle(lookup->device_handle, + sb->resource_source.string_ptr, + &lookup->controller_handle); + if (ACPI_FAILURE(status)) + return 1; + + /* + * NOTE: Ideally, we would also want to retreive other properties here, + * once setting them before opening the device is supported by serdev. + */ + + return 1; +} + +static int acpi_serdev_do_lookup(struct acpi_device *adev, + struct acpi_serdev_lookup *lookup) +{ + struct list_head resource_list; + int ret; + + lookup->device_handle = acpi_device_handle(adev); + lookup->controller_handle = NULL; + lookup->n = 0; + + INIT_LIST_HEAD(&resource_list); + ret = acpi_dev_get_resources(adev, &resource_list, + acpi_serdev_parse_resource, lookup); + acpi_dev_free_resource_list(&resource_list); + + if (ret < 0) + return -EINVAL; + + return 0; +} + +static int acpi_serdev_check_resources(struct serdev_controller *ctrl, + struct acpi_device *adev) +{ + struct acpi_serdev_lookup lookup; + int ret; + + if (acpi_bus_get_status(adev) || !adev->status.present) + return -EINVAL; + + /* Look for UARTSerialBusV2 resource */ + lookup.index = -1; // we only care for the last device + + ret = acpi_serdev_do_lookup(adev, &lookup); + if (ret) + return ret; + + /* Make sure controller and ResourceSource handle match */ + if (ACPI_HANDLE(ctrl->dev.parent) != lookup.controller_handle) + return -ENODEV; + + return 0; +} + static acpi_status acpi_serdev_register_device(struct serdev_controller *ctrl, - struct acpi_device *adev) + struct acpi_device *adev) { - struct serdev_device *serdev = NULL; + struct serdev_device *serdev; int err; - if (acpi_bus_get_status(adev) || !adev->status.present || - acpi_device_enumerated(adev)) - return AE_OK; - serdev = serdev_device_alloc(ctrl); if (!serdev) { dev_err(&ctrl->dev, "failed to allocate serdev device for %s\n", @@ -583,7 +664,7 @@ static acpi_status acpi_serdev_register_device(struct serdev_controller *ctrl, } static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level, - void *data, void **return_value) + void *data, void **return_value) { struct serdev_controller *ctrl = data; struct acpi_device *adev; @@ -591,22 +672,28 @@ static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level, if (acpi_bus_get_device(handle, &adev)) return AE_OK; + if (acpi_device_enumerated(adev)) + return AE_OK; + + if (acpi_serdev_check_resources(ctrl, adev)) + return AE_OK; + return acpi_serdev_register_device(ctrl, adev); } + static int acpi_serdev_register_devices(struct serdev_controller *ctrl) { acpi_status status; - acpi_handle handle; - handle = ACPI_HANDLE(ctrl->dev.parent); - if (!handle) + if (!has_acpi_companion(ctrl->dev.parent)) return -ENODEV; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + SERDEV_ACPI_MAX_SCAN_DEPTH, acpi_serdev_add_device, NULL, ctrl, NULL); if (ACPI_FAILURE(status)) - dev_dbg(&ctrl->dev, "failed to enumerate serdev slaves\n"); + dev_warn(&ctrl->dev, "failed to enumerate serdev slaves\n"); if (!ctrl->serdev) return -ENODEV; diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c index 0438d9a905ce..6e67fd89445a 100644 --- a/drivers/tty/serial/8250/8250_aspeed_vuart.c +++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c @@ -14,6 +14,8 @@ #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_platform.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/clk.h> @@ -22,6 +24,7 @@ #define ASPEED_VUART_GCRA 0x20 #define ASPEED_VUART_GCRA_VUART_EN BIT(0) +#define ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY BIT(1) #define ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5) #define ASPEED_VUART_GCRB 0x24 #define ASPEED_VUART_GCRB_HOST_SIRQ_MASK GENMASK(7, 4) @@ -131,8 +134,53 @@ static ssize_t sirq_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR_RW(sirq); +static ssize_t sirq_polarity_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct aspeed_vuart *vuart = dev_get_drvdata(dev); + u8 reg; + + reg = readb(vuart->regs + ASPEED_VUART_GCRA); + reg &= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY; + + return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg ? 1 : 0); +} + +static void aspeed_vuart_set_sirq_polarity(struct aspeed_vuart *vuart, + bool polarity) +{ + u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA); + + if (polarity) + reg |= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY; + else + reg &= ~ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY; + + writeb(reg, vuart->regs + ASPEED_VUART_GCRA); +} + +static ssize_t sirq_polarity_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aspeed_vuart *vuart = dev_get_drvdata(dev); + unsigned long val; + int err; + + err = kstrtoul(buf, 0, &val); + if (err) + return err; + + aspeed_vuart_set_sirq_polarity(vuart, val != 0); + + return count; +} + +static DEVICE_ATTR_RW(sirq_polarity); + static struct attribute *aspeed_vuart_attrs[] = { &dev_attr_sirq.attr, + &dev_attr_sirq_polarity.attr, &dev_attr_lpc_address.attr, NULL, }; @@ -302,8 +350,30 @@ static int aspeed_vuart_handle_irq(struct uart_port *port) return 1; } +static void aspeed_vuart_auto_configure_sirq_polarity( + struct aspeed_vuart *vuart, struct device_node *syscon_np, + u32 reg_offset, u32 reg_mask) +{ + struct regmap *regmap; + u32 value; + + regmap = syscon_node_to_regmap(syscon_np); + if (IS_ERR(regmap)) { + dev_warn(vuart->dev, + "could not get regmap for aspeed,sirq-polarity-sense\n"); + return; + } + if (regmap_read(regmap, reg_offset, &value)) { + dev_warn(vuart->dev, "could not read hw strap table\n"); + return; + } + + aspeed_vuart_set_sirq_polarity(vuart, (value & reg_mask) == 0); +} + static int aspeed_vuart_probe(struct platform_device *pdev) { + struct of_phandle_args sirq_polarity_sense_args; struct uart_8250_port port; struct aspeed_vuart *vuart; struct device_node *np; @@ -402,6 +472,20 @@ static int aspeed_vuart_probe(struct platform_device *pdev) vuart->line = rc; + rc = of_parse_phandle_with_fixed_args( + np, "aspeed,sirq-polarity-sense", 2, 0, + &sirq_polarity_sense_args); + if (rc < 0) { + dev_dbg(&pdev->dev, + "aspeed,sirq-polarity-sense property not found\n"); + } else { + aspeed_vuart_auto_configure_sirq_polarity( + vuart, sirq_polarity_sense_args.np, + sirq_polarity_sense_args.args[0], + BIT(sirq_polarity_sense_args.args[1])); + of_node_put(sirq_polarity_sense_args.np); + } + aspeed_vuart_set_enabled(vuart, true); aspeed_vuart_set_host_tx_discard(vuart, true); platform_set_drvdata(pdev, vuart); diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 1c72fdc2dd37..aab3cccc6789 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -280,9 +280,6 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, long rate; int ret; - if (IS_ERR(d->clk)) - goto out; - clk_disable_unprepare(d->clk); rate = clk_round_rate(d->clk, baud * 16); if (rate < 0) @@ -293,8 +290,10 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, ret = clk_set_rate(d->clk, rate); clk_prepare_enable(d->clk); - if (!ret) - p->uartclk = rate; + if (ret) + goto out; + + p->uartclk = rate; out: p->status &= ~UPSTAT_AUTOCTS; @@ -386,10 +385,10 @@ static int dw8250_probe(struct platform_device *pdev) { struct uart_8250_port uart = {}, *up = &uart; struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - int irq = platform_get_irq(pdev, 0); struct uart_port *p = &up->port; struct device *dev = &pdev->dev; struct dw8250_data *data; + int irq; int err; u32 val; @@ -398,11 +397,9 @@ static int dw8250_probe(struct platform_device *pdev) return -EINVAL; } - if (irq < 0) { - if (irq != -EPROBE_DEFER) - dev_err(dev, "cannot get irq\n"); + irq = platform_get_irq(pdev, 0); + if (irq < 0) return irq; - } spin_lock_init(&p->lock); p->mapbase = regs->start; @@ -472,19 +469,18 @@ static int dw8250_probe(struct platform_device *pdev) device_property_read_u32(dev, "clock-frequency", &p->uartclk); /* If there is separate baudclk, get the rate from it. */ - data->clk = devm_clk_get(dev, "baudclk"); - if (IS_ERR(data->clk) && PTR_ERR(data->clk) != -EPROBE_DEFER) - data->clk = devm_clk_get(dev, NULL); - if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; - if (!IS_ERR_OR_NULL(data->clk)) { - err = clk_prepare_enable(data->clk); - if (err) - dev_warn(dev, "could not enable optional baudclk: %d\n", - err); - else - p->uartclk = clk_get_rate(data->clk); - } + data->clk = devm_clk_get_optional(dev, "baudclk"); + if (data->clk == NULL) + data->clk = devm_clk_get_optional(dev, NULL); + if (IS_ERR(data->clk)) + return PTR_ERR(data->clk); + + err = clk_prepare_enable(data->clk); + if (err) + dev_warn(dev, "could not enable optional baudclk: %d\n", err); + + if (data->clk) + p->uartclk = clk_get_rate(data->clk); /* If no clock rate is defined, fail. */ if (!p->uartclk) { @@ -493,17 +489,16 @@ static int dw8250_probe(struct platform_device *pdev) goto err_clk; } - data->pclk = devm_clk_get(dev, "apb_pclk"); - if (IS_ERR(data->pclk) && PTR_ERR(data->pclk) == -EPROBE_DEFER) { - err = -EPROBE_DEFER; + data->pclk = devm_clk_get_optional(dev, "apb_pclk"); + if (IS_ERR(data->pclk)) { + err = PTR_ERR(data->pclk); goto err_clk; } - if (!IS_ERR(data->pclk)) { - err = clk_prepare_enable(data->pclk); - if (err) { - dev_err(dev, "could not enable apb_pclk\n"); - goto err_clk; - } + + err = clk_prepare_enable(data->pclk); + if (err) { + dev_err(dev, "could not enable apb_pclk\n"); + goto err_clk; } data->rst = devm_reset_control_get_optional_exclusive(dev, NULL); @@ -546,12 +541,10 @@ err_reset: reset_control_assert(data->rst); err_pclk: - if (!IS_ERR(data->pclk)) - clk_disable_unprepare(data->pclk); + clk_disable_unprepare(data->pclk); err_clk: - if (!IS_ERR(data->clk)) - clk_disable_unprepare(data->clk); + clk_disable_unprepare(data->clk); return err; } @@ -567,11 +560,9 @@ static int dw8250_remove(struct platform_device *pdev) reset_control_assert(data->rst); - if (!IS_ERR(data->pclk)) - clk_disable_unprepare(data->pclk); + clk_disable_unprepare(data->pclk); - if (!IS_ERR(data->clk)) - clk_disable_unprepare(data->clk); + clk_disable_unprepare(data->clk); pm_runtime_disable(dev); pm_runtime_put_noidle(dev); @@ -604,11 +595,9 @@ static int dw8250_runtime_suspend(struct device *dev) { struct dw8250_data *data = dev_get_drvdata(dev); - if (!IS_ERR(data->clk)) - clk_disable_unprepare(data->clk); + clk_disable_unprepare(data->clk); - if (!IS_ERR(data->pclk)) - clk_disable_unprepare(data->pclk); + clk_disable_unprepare(data->pclk); return 0; } @@ -617,11 +606,9 @@ static int dw8250_runtime_resume(struct device *dev) { struct dw8250_data *data = dev_get_drvdata(dev); - if (!IS_ERR(data->pclk)) - clk_prepare_enable(data->pclk); + clk_prepare_enable(data->pclk); - if (!IS_ERR(data->clk)) - clk_prepare_enable(data->clk); + clk_prepare_enable(data->clk); return 0; } diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 597eb9d16f21..108cd55f9c4d 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -166,6 +166,23 @@ static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud, serial_port_out(p, 0x2, quot_frac); } +static int xr17v35x_startup(struct uart_port *port) +{ + /* + * First enable access to IER [7:5], ISR [5:4], FCR [5:4], + * MCR [7:5] and MSR [7:0] + */ + serial_port_out(port, UART_XR_EFR, UART_EFR_ECB); + + /* + * Make sure all interrups are masked until initialization is + * complete and the FIFOs are cleared + */ + serial_port_out(port, UART_IER, 0); + + return serial8250_do_startup(port); +} + static void exar_shutdown(struct uart_port *port) { unsigned char lsr; @@ -212,6 +229,8 @@ static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev, port->port.get_divisor = xr17v35x_get_divisor; port->port.set_divisor = xr17v35x_set_divisor; + + port->port.startup = xr17v35x_startup; } else { port->port.type = PORT_XR17D15X; } diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 5f72ef3ea574..60eff3240c8a 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -221,17 +221,6 @@ static void qrk_serial_exit_dma(struct lpss8250 *lpss) {} static int qrk_serial_setup(struct lpss8250 *lpss, struct uart_port *port) { - struct pci_dev *pdev = to_pci_dev(port->dev); - int ret; - - pci_set_master(pdev); - - ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); - if (ret < 0) - return ret; - - port->irq = pci_irq_vector(pdev, 0); - qrk_serial_setup_dma(lpss, port); return 0; } @@ -293,16 +282,22 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) return ret; + pci_set_master(pdev); + lpss = devm_kzalloc(&pdev->dev, sizeof(*lpss), GFP_KERNEL); if (!lpss) return -ENOMEM; + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) + return ret; + lpss->board = (struct lpss8250_board *)id->driver_data; memset(&uart, 0, sizeof(struct uart_8250_port)); uart.port.dev = &pdev->dev; - uart.port.irq = pdev->irq; + uart.port.irq = pci_irq_vector(pdev, 0); uart.port.private_data = &lpss->data; uart.port.type = PORT_16550A; uart.port.iotype = UPIO_MEM; @@ -337,6 +332,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) err_exit: if (lpss->board->exit) lpss->board->exit(lpss); + pci_free_irq_vectors(pdev); return ret; } @@ -348,6 +344,7 @@ static void lpss8250_remove(struct pci_dev *pdev) if (lpss->board->exit) lpss->board->exit(lpss); + pci_free_irq_vectors(pdev); } static const struct lpss8250_board byt_board = { diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index b411ba4eb5e9..4d067f515f74 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -544,7 +544,7 @@ static int mtk8250_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - data->rx_wakeup_irq = platform_get_irq(pdev, 1); + data->rx_wakeup_irq = platform_get_irq_optional(pdev, 1); return 0; } diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 0826cfdbd406..92fbf46ce3bd 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -48,6 +48,36 @@ static inline void tegra_serial_handle_break(struct uart_port *port) } #endif +static int of_8250_rs485_config(struct uart_port *port, + struct serial_rs485 *rs485) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* Clamp the delays to [0, 100ms] */ + rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); + rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); + + port->rs485 = *rs485; + + /* + * Both serial8250_em485_init and serial8250_em485_destroy + * are idempotent + */ + if (rs485->flags & SER_RS485_ENABLED) { + int ret = serial8250_em485_init(up); + + if (ret) { + rs485->flags &= ~SER_RS485_ENABLED; + port->rs485.flags &= ~SER_RS485_ENABLED; + } + return ret; + } + + serial8250_em485_destroy(up); + + return 0; +} + /* * Fill a struct uart_port for a given device node */ @@ -178,6 +208,7 @@ static int of_platform_serial_setup(struct platform_device *ofdev, port->flags |= UPF_SKIP_TEST; port->dev = &ofdev->dev; + port->rs485_config = of_8250_rs485_config; switch (type) { case PORT_TEGRA: diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 0b8784cd6d71..022924d5ad54 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -743,16 +743,8 @@ static int pci_ni8430_init(struct pci_dev *dev) } /* UART Port Control Register */ -#define NI16550_PCR_OFFSET 0x0f -#define NI16550_PCR_RS422 0x00 -#define NI16550_PCR_ECHO_RS485 0x01 -#define NI16550_PCR_DTR_RS485 0x02 -#define NI16550_PCR_AUTO_RS485 0x03 -#define NI16550_PCR_WIRE_MODE_MASK 0x03 -#define NI16550_PCR_TXVR_ENABLE_BIT BIT(3) -#define NI16550_PCR_RS485_TERMINATION_BIT BIT(6) -#define NI16550_ACR_DTR_AUTO_DTR (0x2 << 3) -#define NI16550_ACR_DTR_MANUAL_DTR (0x0 << 3) +#define NI8430_PORTCON 0x0f +#define NI8430_PORTCON_TXVR_ENABLE (1 << 3) static int pci_ni8430_setup(struct serial_private *priv, @@ -774,117 +766,14 @@ pci_ni8430_setup(struct serial_private *priv, return -ENOMEM; /* enable the transceiver */ - writeb(readb(p + offset + NI16550_PCR_OFFSET) | NI16550_PCR_TXVR_ENABLE_BIT, - p + offset + NI16550_PCR_OFFSET); + writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE, + p + offset + NI8430_PORTCON); iounmap(p); return setup_port(priv, port, bar, offset, board->reg_shift); } -static int pci_ni8431_config_rs485(struct uart_port *port, - struct serial_rs485 *rs485) -{ - u8 pcr, acr; - struct uart_8250_port *up; - - up = container_of(port, struct uart_8250_port, port); - acr = up->acr; - pcr = port->serial_in(port, NI16550_PCR_OFFSET); - pcr &= ~NI16550_PCR_WIRE_MODE_MASK; - - if (rs485->flags & SER_RS485_ENABLED) { - /* RS-485 */ - if ((rs485->flags & SER_RS485_RX_DURING_TX) && - (rs485->flags & SER_RS485_RTS_ON_SEND)) { - dev_dbg(port->dev, "Invalid 2-wire mode\n"); - return -EINVAL; - } - - if (rs485->flags & SER_RS485_RX_DURING_TX) { - /* Echo */ - dev_vdbg(port->dev, "2-wire DTR with echo\n"); - pcr |= NI16550_PCR_ECHO_RS485; - acr |= NI16550_ACR_DTR_MANUAL_DTR; - } else { - /* Auto or DTR */ - if (rs485->flags & SER_RS485_RTS_ON_SEND) { - /* Auto */ - dev_vdbg(port->dev, "2-wire Auto\n"); - pcr |= NI16550_PCR_AUTO_RS485; - acr |= NI16550_ACR_DTR_AUTO_DTR; - } else { - /* DTR-controlled */ - /* No Echo */ - dev_vdbg(port->dev, "2-wire DTR no echo\n"); - pcr |= NI16550_PCR_DTR_RS485; - acr |= NI16550_ACR_DTR_MANUAL_DTR; - } - } - } else { - /* RS-422 */ - dev_vdbg(port->dev, "4-wire\n"); - pcr |= NI16550_PCR_RS422; - acr |= NI16550_ACR_DTR_MANUAL_DTR; - } - - dev_dbg(port->dev, "write pcr: 0x%08x\n", pcr); - port->serial_out(port, NI16550_PCR_OFFSET, pcr); - - up->acr = acr; - port->serial_out(port, UART_SCR, UART_ACR); - port->serial_out(port, UART_ICR, up->acr); - - /* Update the cache. */ - port->rs485 = *rs485; - - return 0; -} - -static int pci_ni8431_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *uart, int idx) -{ - u8 pcr, acr; - struct pci_dev *dev = priv->dev; - void __iomem *addr; - unsigned int bar, offset = board->first_offset; - - if (idx >= board->num_ports) - return 1; - - bar = FL_GET_BASE(board->flags); - offset += idx * board->uart_offset; - - addr = pci_ioremap_bar(dev, bar); - if (!addr) - return -ENOMEM; - - /* enable the transceiver */ - writeb(readb(addr + NI16550_PCR_OFFSET) | NI16550_PCR_TXVR_ENABLE_BIT, - addr + NI16550_PCR_OFFSET); - - pcr = readb(addr + NI16550_PCR_OFFSET); - pcr &= ~NI16550_PCR_WIRE_MODE_MASK; - - /* set wire mode to default RS-422 */ - pcr |= NI16550_PCR_RS422; - acr = NI16550_ACR_DTR_MANUAL_DTR; - - /* write port configuration to register */ - writeb(pcr, addr + NI16550_PCR_OFFSET); - - /* access and write to UART acr register */ - writeb(UART_ACR, addr + UART_SCR); - writeb(acr, addr + UART_ICR); - - uart->port.rs485_config = &pci_ni8431_config_rs485; - - iounmap(addr); - - return setup_port(priv, uart, bar, offset, board->reg_shift); -} - static int pci_netmos_9900_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) @@ -2021,15 +1910,6 @@ pci_moxa_setup(struct serial_private *priv, #define PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM 0x10E9 #define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM 0x11D8 -#define PCIE_DEVICE_ID_NI_PXIE8430_2328 0x74C2 -#define PCIE_DEVICE_ID_NI_PXIE8430_23216 0x74C1 -#define PCI_DEVICE_ID_NI_PXI8431_4852 0x7081 -#define PCI_DEVICE_ID_NI_PXI8431_4854 0x70DE -#define PCI_DEVICE_ID_NI_PXI8431_4858 0x70E3 -#define PCI_DEVICE_ID_NI_PXI8433_4852 0x70E9 -#define PCI_DEVICE_ID_NI_PXI8433_4854 0x70ED -#define PCIE_DEVICE_ID_NI_PXIE8431_4858 0x74C4 -#define PCIE_DEVICE_ID_NI_PXIE8431_48516 0x74C3 #define PCI_DEVICE_ID_MOXA_CP102E 0x1024 #define PCI_DEVICE_ID_MOXA_CP102EL 0x1025 @@ -2267,87 +2147,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_ni8430_setup, .exit = pci_ni8430_exit, }, - { - .vendor = PCI_VENDOR_ID_NI, - .device = PCIE_DEVICE_ID_NI_PXIE8430_2328, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_ni8430_init, - .setup = pci_ni8430_setup, - .exit = pci_ni8430_exit, - }, - { - .vendor = PCI_VENDOR_ID_NI, - .device = PCIE_DEVICE_ID_NI_PXIE8430_23216, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_ni8430_init, - .setup = pci_ni8430_setup, - .exit = pci_ni8430_exit, - }, - { - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PXI8431_4852, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_ni8430_init, - .setup = pci_ni8431_setup, - .exit = pci_ni8430_exit, - }, - { - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PXI8431_4854, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_ni8430_init, - .setup = pci_ni8431_setup, - .exit = pci_ni8430_exit, - }, - { - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PXI8431_4858, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_ni8430_init, - .setup = pci_ni8431_setup, - .exit = pci_ni8430_exit, - }, - { - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PXI8433_4852, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_ni8430_init, - .setup = pci_ni8431_setup, - .exit = pci_ni8430_exit, - }, - { - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PXI8433_4854, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_ni8430_init, - .setup = pci_ni8431_setup, - .exit = pci_ni8430_exit, - }, - { - .vendor = PCI_VENDOR_ID_NI, - .device = PCIE_DEVICE_ID_NI_PXIE8431_4858, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_ni8430_init, - .setup = pci_ni8431_setup, - .exit = pci_ni8430_exit, - }, - { - .vendor = PCI_VENDOR_ID_NI, - .device = PCIE_DEVICE_ID_NI_PXIE8431_48516, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_ni8430_init, - .setup = pci_ni8431_setup, - .exit = pci_ni8430_exit, - }, /* Quatech */ { .vendor = PCI_VENDOR_ID_QUATECH, @@ -3104,13 +2903,6 @@ enum pci_board_num_t { pbn_ni8430_4, pbn_ni8430_8, pbn_ni8430_16, - pbn_ni8430_pxie_8, - pbn_ni8430_pxie_16, - pbn_ni8431_2, - pbn_ni8431_4, - pbn_ni8431_8, - pbn_ni8431_pxie_8, - pbn_ni8431_pxie_16, pbn_ADDIDATA_PCIe_1_3906250, pbn_ADDIDATA_PCIe_2_3906250, pbn_ADDIDATA_PCIe_4_3906250, @@ -3763,55 +3555,6 @@ static struct pciserial_board pci_boards[] = { .uart_offset = 0x10, .first_offset = 0x800, }, - [pbn_ni8430_pxie_16] = { - .flags = FL_BASE0, - .num_ports = 16, - .base_baud = 3125000, - .uart_offset = 0x10, - .first_offset = 0x800, - }, - [pbn_ni8430_pxie_8] = { - .flags = FL_BASE0, - .num_ports = 8, - .base_baud = 3125000, - .uart_offset = 0x10, - .first_offset = 0x800, - }, - [pbn_ni8431_8] = { - .flags = FL_BASE0, - .num_ports = 8, - .base_baud = 3686400, - .uart_offset = 0x10, - .first_offset = 0x800, - }, - [pbn_ni8431_4] = { - .flags = FL_BASE0, - .num_ports = 4, - .base_baud = 3686400, - .uart_offset = 0x10, - .first_offset = 0x800, - }, - [pbn_ni8431_2] = { - .flags = FL_BASE0, - .num_ports = 2, - .base_baud = 3686400, - .uart_offset = 0x10, - .first_offset = 0x800, - }, - [pbn_ni8431_pxie_16] = { - .flags = FL_BASE0, - .num_ports = 16, - .base_baud = 3125000, - .uart_offset = 0x10, - .first_offset = 0x800, - }, - [pbn_ni8431_pxie_8] = { - .flags = FL_BASE0, - .num_ports = 8, - .base_baud = 3125000, - .uart_offset = 0x10, - .first_offset = 0x800, - }, /* * ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com> */ @@ -5565,33 +5308,6 @@ static const struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_ni8430_4 }, - { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_2328, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_ni8430_pxie_8 }, - { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_23216, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_ni8430_pxie_16 }, - { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4852, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_ni8431_2 }, - { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4854, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_ni8431_4 }, - { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4858, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_ni8431_8 }, - { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_4858, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_ni8431_pxie_8 }, - { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_48516, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_ni8431_pxie_16 }, - { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4852, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_ni8431_2 }, - { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4854, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_ni8431_4 }, /* * MOXA diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 8407166610ce..90655910b0c7 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2114,20 +2114,6 @@ int serial8250_do_startup(struct uart_port *port) enable_rsa(up); #endif - if (port->type == PORT_XR17V35X) { - /* - * First enable access to IER [7:5], ISR [5:4], FCR [5:4], - * MCR [7:5] and MSR [7:0] - */ - serial_port_out(port, UART_XR_EFR, UART_EFR_ECB); - - /* - * Make sure all interrups are masked until initialization is - * complete and the FIFOs are cleared - */ - serial_port_out(port, UART_IER, 0); - } - /* * Clear the FIFO buffers and disable them. * (they will be reenabled in set_termios()) diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 7ef60f8b6e2c..fab3d4f20667 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -243,6 +243,7 @@ config SERIAL_8250_ASPEED_VUART tristate "Aspeed Virtual UART" depends on SERIAL_8250 depends on OF + depends on REGMAP && MFD_SYSCON help If you want to use the virtual UART (VUART) device on Aspeed BMC platforms, enable this option. This enables the 16550A- @@ -334,7 +335,7 @@ config SERIAL_8250_BCM2835AUX Features and limitations of the UART are Registers are similar to 16650 registers, - set bits in the control registers that are unsupported + set bits in the control registers that are unsupported are ignored and read back as 0 7/8 bit operation with 1 start and 1 stop bit 8 symbols deep fifo for rx and tx diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 540142c5b7b3..99f5da3bf913 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -287,26 +287,26 @@ config SERIAL_SAMSUNG_CONSOLE boot time.) config SERIAL_SIRFSOC - tristate "SiRF SoC Platform Serial port support" - depends on ARCH_SIRF - select SERIAL_CORE - help - Support for the on-chip UART on the CSR SiRFprimaII series, - providing /dev/ttySiRF0, 1 and 2 (note, some machines may not - provide all of these ports, depending on how the serial port - pins are configured). + tristate "SiRF SoC Platform Serial port support" + depends on ARCH_SIRF + select SERIAL_CORE + help + Support for the on-chip UART on the CSR SiRFprimaII series, + providing /dev/ttySiRF0, 1 and 2 (note, some machines may not + provide all of these ports, depending on how the serial port + pins are configured). config SERIAL_SIRFSOC_CONSOLE - bool "Support for console on SiRF SoC serial port" - depends on SERIAL_SIRFSOC=y - select SERIAL_CORE_CONSOLE - help - Even if you say Y here, the currently visible virtual console - (/dev/tty0) will still be used as the system console by default, but - you can alter that using a kernel command line option such as - "console=ttySiRFx". (Try "man bootparam" or see the documentation of - your boot loader about how to pass options to the kernel at - boot time.) + bool "Support for console on SiRF SoC serial port" + depends on SERIAL_SIRFSOC=y + select SERIAL_CORE_CONSOLE + help + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttySiRFx". (Try "man bootparam" or see the documentation of + your boot loader about how to pass options to the kernel at + boot time.) config SERIAL_TEGRA tristate "NVIDIA Tegra20/30 SoC serial controller" @@ -1078,41 +1078,41 @@ config SERIAL_SCCNXP_CONSOLE Support for console on SCCNXP serial ports. config SERIAL_SC16IS7XX_CORE - tristate + tristate config SERIAL_SC16IS7XX - tristate "SC16IS7xx serial support" - select SERIAL_CORE - depends on (SPI_MASTER && !I2C) || I2C - help - This selects support for SC16IS7xx serial ports. - Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752, - SC16IS760 and SC16IS762. Select supported buses using options below. + tristate "SC16IS7xx serial support" + select SERIAL_CORE + depends on (SPI_MASTER && !I2C) || I2C + help + This selects support for SC16IS7xx serial ports. + Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752, + SC16IS760 and SC16IS762. Select supported buses using options below. config SERIAL_SC16IS7XX_I2C - bool "SC16IS7xx for I2C interface" - depends on SERIAL_SC16IS7XX - depends on I2C - select SERIAL_SC16IS7XX_CORE if SERIAL_SC16IS7XX - select REGMAP_I2C if I2C - default y - help - Enable SC16IS7xx driver on I2C bus, - If required say y, and say n to i2c if not required, - Enabled by default to support oldconfig. - You must select at least one bus for the driver to be built. + bool "SC16IS7xx for I2C interface" + depends on SERIAL_SC16IS7XX + depends on I2C + select SERIAL_SC16IS7XX_CORE if SERIAL_SC16IS7XX + select REGMAP_I2C if I2C + default y + help + Enable SC16IS7xx driver on I2C bus, + If required say y, and say n to i2c if not required, + Enabled by default to support oldconfig. + You must select at least one bus for the driver to be built. config SERIAL_SC16IS7XX_SPI - bool "SC16IS7xx for spi interface" - depends on SERIAL_SC16IS7XX - depends on SPI_MASTER - select SERIAL_SC16IS7XX_CORE if SERIAL_SC16IS7XX - select REGMAP_SPI if SPI_MASTER - help - Enable SC16IS7xx driver on SPI bus, - If required say y, and say n to spi if not required, - This is additional support to exsisting driver. - You must select at least one bus for the driver to be built. + bool "SC16IS7xx for spi interface" + depends on SERIAL_SC16IS7XX + depends on SPI_MASTER + select SERIAL_SC16IS7XX_CORE if SERIAL_SC16IS7XX + select REGMAP_SPI if SPI_MASTER + help + Enable SC16IS7xx driver on SPI bus, + If required say y, and say n to spi if not required, + This is additional support to exsisting driver. + You must select at least one bus for the driver to be built. config SERIAL_TIMBERDALE tristate "Support for timberdale UART" @@ -1212,7 +1212,7 @@ config SERIAL_ALTERA_UART_CONSOLE Enable a Altera UART port to be the system console. config SERIAL_IFX6X60 - tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)" + tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)" depends on GPIOLIB || COMPILE_TEST depends on SPI && HAS_DMA help @@ -1392,19 +1392,19 @@ config SERIAL_FSL_LPUART_CONSOLE you can make it the console by answering Y to this option. config SERIAL_FSL_LINFLEXUART - tristate "Freescale linflexuart serial port support" + tristate "Freescale LINFlexD UART serial port support" depends on PRINTK select SERIAL_CORE help - Support for the on-chip linflexuart on some Freescale SOCs. + Support for the on-chip LINFlexD UART on some Freescale SOCs. config SERIAL_FSL_LINFLEXUART_CONSOLE - bool "Console on Freescale linflexuart serial port" + bool "Console on Freescale LINFlexD UART serial port" depends on SERIAL_FSL_LINFLEXUART=y select SERIAL_CORE_CONSOLE select SERIAL_EARLYCON help - If you have enabled the linflexuart serial port on the Freescale + If you have enabled the LINFlexD UART serial port on the Freescale SoCs, you can make it the console by answering Y to this option. config SERIAL_CONEXANT_DIGICOLOR diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 863f47056539..d056ee6cca33 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -30,7 +30,7 @@ obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o obj-$(CONFIG_SERIAL_SA1100) += sa1100.o obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o -obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o +obj-$(CONFIG_SERIAL_SAMSUNG) += samsung_tty.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_MAX310X) += max310x.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 3a7d1a66f79c..4b28134d596a 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -414,7 +414,7 @@ static void pl011_dma_probe(struct uart_amba_port *uap) dma_cap_mask_t mask; uap->dma_probed = true; - chan = dma_request_slave_channel_reason(dev, "tx"); + chan = dma_request_chan(dev, "tx"); if (IS_ERR(chan)) { if (PTR_ERR(chan) == -EPROBE_DEFER) { uap->dma_probed = false; @@ -813,10 +813,8 @@ __acquires(&uap->port.lock) if (!uap->using_tx_dma) return; - /* Avoid deadlock with the DMA engine callback */ - spin_unlock(&uap->port.lock); - dmaengine_terminate_all(uap->dmatx.chan); - spin_lock(&uap->port.lock); + dmaengine_terminate_async(uap->dmatx.chan); + if (uap->dmatx.queued) { dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1, DMA_TO_DEVICE); @@ -1236,10 +1234,6 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap) #else /* Blank functions if the DMA engine is not available */ -static inline void pl011_dma_probe(struct uart_amba_port *uap) -{ -} - static inline void pl011_dma_remove(struct uart_amba_port *uap) { } diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c index a32f0d2afd59..205c31a61684 100644 --- a/drivers/tty/serial/fsl_linflexuart.c +++ b/drivers/tty/serial/fsl_linflexuart.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Freescale linflexuart serial port driver + * Freescale LINFlexD UART serial port driver * * Copyright 2012-2016 Freescale Semiconductor, Inc. * Copyright 2017-2019 NXP @@ -940,5 +940,5 @@ static void __exit linflex_serial_exit(void) module_init(linflex_serial_init); module_exit(linflex_serial_exit); -MODULE_DESCRIPTION("Freescale linflex serial port driver"); +MODULE_DESCRIPTION("Freescale LINFlexD serial port driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 537896c4d887..4e128d19e0ad 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -437,8 +437,8 @@ static void lpuart_dma_tx(struct lpuart_port *sport) } sport->dma_tx_desc = dmaengine_prep_slave_sg(sport->dma_tx_chan, sgl, - sport->dma_tx_nents, - DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); + ret, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT); if (!sport->dma_tx_desc) { dma_unmap_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); dev_err(dev, "Cannot prepare TX slave DMA!\n"); @@ -1280,6 +1280,57 @@ static int lpuart_config_rs485(struct uart_port *port, return 0; } +static int lpuart32_config_rs485(struct uart_port *port, + struct serial_rs485 *rs485) +{ + struct lpuart_port *sport = container_of(port, + struct lpuart_port, port); + + unsigned long modem = lpuart32_read(&sport->port, UARTMODIR) + & ~(UARTMODEM_TXRTSPOL | UARTMODEM_TXRTSE); + lpuart32_write(&sport->port, modem, UARTMODIR); + + /* clear unsupported configurations */ + rs485->delay_rts_before_send = 0; + rs485->delay_rts_after_send = 0; + rs485->flags &= ~SER_RS485_RX_DURING_TX; + + if (rs485->flags & SER_RS485_ENABLED) { + /* Enable auto RS-485 RTS mode */ + modem |= UARTMODEM_TXRTSE; + + /* + * RTS needs to be logic HIGH either during transer _or_ after + * transfer, other variants are not supported by the hardware. + */ + + if (!(rs485->flags & (SER_RS485_RTS_ON_SEND | + SER_RS485_RTS_AFTER_SEND))) + rs485->flags |= SER_RS485_RTS_ON_SEND; + + if (rs485->flags & SER_RS485_RTS_ON_SEND && + rs485->flags & SER_RS485_RTS_AFTER_SEND) + rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; + + /* + * The hardware defaults to RTS logic HIGH while transfer. + * Switch polarity in case RTS shall be logic HIGH + * after transfer. + * Note: UART is assumed to be active high. + */ + if (rs485->flags & SER_RS485_RTS_ON_SEND) + modem &= ~UARTMODEM_TXRTSPOL; + else if (rs485->flags & SER_RS485_RTS_AFTER_SEND) + modem |= UARTMODEM_TXRTSPOL; + } + + /* Store the new configuration */ + sport->port.rs485 = *rs485; + + lpuart32_write(&sport->port, modem, UARTMODIR); + return 0; +} + static unsigned int lpuart_get_mctrl(struct uart_port *port) { unsigned int temp = 0; @@ -1333,18 +1384,7 @@ static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl) static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl) { - unsigned long temp; - - temp = lpuart32_read(port, UARTMODIR) & - ~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE); - - if (mctrl & TIOCM_RTS) - temp |= UARTMODIR_RXRTSE; - - if (mctrl & TIOCM_CTS) - temp |= UARTMODIR_TXCTSE; - lpuart32_write(port, temp, UARTMODIR); } static void lpuart_break_ctl(struct uart_port *port, int break_state) @@ -1889,11 +1929,18 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, ctrl |= UARTCTRL_M; } + /* + * When auto RS-485 RTS mode is enabled, + * hardware flow control need to be disabled. + */ + if (sport->port.rs485.flags & SER_RS485_ENABLED) + termios->c_cflag &= ~CRTSCTS; + if (termios->c_cflag & CRTSCTS) { - modem |= UARTMODEM_RXRTSE | UARTMODEM_TXCTSE; + modem |= (UARTMODIR_RXRTSE | UARTMODIR_TXCTSE); } else { termios->c_cflag &= ~CRTSCTS; - modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE); + modem &= ~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE); } if (termios->c_cflag & CSTOPB) @@ -2416,7 +2463,10 @@ static int lpuart_probe(struct platform_device *pdev) sport->port.ops = &lpuart_pops; sport->port.flags = UPF_BOOT_AUTOCONF; - sport->port.rs485_config = lpuart_config_rs485; + if (lpuart_is_32(sport)) + sport->port.rs485_config = lpuart32_config_rs485; + else + sport->port.rs485_config = lpuart_config_rs485; sport->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(sport->ipg_clk)) { @@ -2470,7 +2520,7 @@ static int lpuart_probe(struct platform_device *pdev) sport->port.rs485.delay_rts_after_send) dev_err(&pdev->dev, "driver doesn't support RTS delays\n"); - lpuart_config_rs485(&sport->port, &sport->port.rs485); + sport->port.rs485_config(&sport->port, &sport->port.rs485); sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx"); if (!sport->dma_tx_chan) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index ffefd218761e..31033d517e82 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -1230,6 +1230,9 @@ static int ifx_spi_spi_remove(struct spi_device *spi) struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi); /* stop activity */ tasklet_kill(&ifx_dev->io_work_tasklet); + + pm_runtime_disable(&spi->dev); + /* free irq */ free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev); free_irq(gpio_to_irq(ifx_dev->gpio.srdy), ifx_dev); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 5e08f2657b90..a9e20e6c63ad 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -619,7 +619,7 @@ static void imx_uart_dma_tx(struct imx_port *sport) dev_err(dev, "DMA mapping error for TX.\n"); return; } - desc = dmaengine_prep_slave_sg(chan, sgl, sport->dma_tx_nents, + desc = dmaengine_prep_slave_sg(chan, sgl, ret, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); if (!desc) { dma_unmap_sg(dev, sgl, sport->dma_tx_nents, @@ -1034,8 +1034,6 @@ static void imx_uart_timeout(struct timer_list *t) } } -#define RX_BUF_SIZE (PAGE_SIZE) - /* * There are two kinds of RX DMA interrupts(such as in the MX6Q): * [1] the RX DMA buffer is full. @@ -1118,7 +1116,8 @@ static void imx_uart_dma_rx_callback(void *data) } /* RX DMA buffer periods */ -#define RX_DMA_PERIODS 4 +#define RX_DMA_PERIODS 16 +#define RX_BUF_SIZE (RX_DMA_PERIODS * PAGE_SIZE / 4) static int imx_uart_start_rx_dma(struct imx_port *sport) { diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 3657a24913fc..1cbae0768b1f 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -301,7 +301,7 @@ static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base) dma = &msm_port->tx_dma; /* allocate DMA resources, if available */ - dma->chan = dma_request_slave_channel_reason(dev, "tx"); + dma->chan = dma_request_chan(dev, "tx"); if (IS_ERR(dma->chan)) goto no_tx; @@ -344,7 +344,7 @@ static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base) dma = &msm_port->rx_dma; /* allocate DMA resources, if available */ - dma->chan = dma_request_slave_channel_reason(dev, "rx"); + dma->chan = dma_request_chan(dev, "rx"); if (IS_ERR(dma->chan)) goto no_rx; @@ -980,6 +980,7 @@ static unsigned int msm_get_mctrl(struct uart_port *port) static void msm_reset(struct uart_port *port) { struct msm_port *msm_port = UART_TO_MSM(port); + unsigned int mr; /* reset everything */ msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); @@ -987,7 +988,10 @@ static void msm_reset(struct uart_port *port) msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR); msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); - msm_write(port, UART_CR_CMD_SET_RFR, UART_CR); + msm_write(port, UART_CR_CMD_RESET_RFR, UART_CR); + mr = msm_read(port, UART_MR1); + mr &= ~UART_MR1_RX_RDY_CTL; + msm_write(port, mr, UART_MR1); /* Disable DM modes */ if (msm_port->is_uartdm) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 6157213a8359..c16234bca78f 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -233,6 +233,7 @@ struct eg20t_port { struct dma_chan *chan_rx; struct scatterlist *sg_tx_p; int nent; + int orig_nent; struct scatterlist sg_rx; int tx_dma_use; void *rx_buf_virt; @@ -787,9 +788,10 @@ static void pch_dma_tx_complete(void *arg) } xmit->tail &= UART_XMIT_SIZE - 1; async_tx_ack(priv->desc_tx); - dma_unmap_sg(port->dev, sg, priv->nent, DMA_TO_DEVICE); + dma_unmap_sg(port->dev, sg, priv->orig_nent, DMA_TO_DEVICE); priv->tx_dma_use = 0; priv->nent = 0; + priv->orig_nent = 0; kfree(priv->sg_tx_p); pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT); } @@ -1010,6 +1012,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv) dev_err(priv->port.dev, "%s:dma_map_sg Failed\n", __func__); return 0; } + priv->orig_nent = num; priv->nent = nent; for (i = 0; i < nent; i++, sg++) { diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 14c6306bc462..ff63728a95f4 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -9,10 +9,12 @@ #include <linux/console.h> #include <linux/io.h> #include <linux/iopoll.h> +#include <linux/irq.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> +#include <linux/pm_wakeirq.h> #include <linux/qcom-geni-se.h> #include <linux/serial.h> #include <linux/serial_core.h> @@ -115,6 +117,7 @@ struct qcom_geni_serial_port { bool brk; unsigned int tx_remaining; + int wakeup_irq; }; static const struct uart_ops qcom_geni_console_pops; @@ -754,6 +757,15 @@ 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; @@ -830,7 +842,7 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport) if (uart_console(uport)) console_stop(uport->cons); - free_irq(uport->irq, uport); + disable_irq(uport->irq); spin_lock_irqsave(&uport->lock, flags); qcom_geni_serial_stop_tx(uport); qcom_geni_serial_stop_rx(uport); @@ -890,21 +902,14 @@ static int qcom_geni_serial_startup(struct uart_port *uport) int ret; struct qcom_geni_serial_port *port = to_dev_port(uport, uport); - scnprintf(port->name, sizeof(port->name), - "qcom_serial_%s%d", - (uart_console(uport) ? "console" : "uart"), uport->line); - if (!port->setup) { ret = qcom_geni_serial_port_setup(uport); if (ret) return ret; } + enable_irq(uport->irq); - ret = request_irq(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); - return ret; + return 0; } static unsigned long get_clk_cfg(unsigned long clk_freq) @@ -1297,11 +1302,44 @@ 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); irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; uport->irq = irq; + 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); + 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); + } + } uport->private_data = drv; platform_set_drvdata(pdev, port); port->handle_rx = console ? handle_rx_console : handle_rx_uart; @@ -1324,7 +1362,12 @@ 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; - return uart_suspend_port(uport->private_data, uport); + uart_suspend_port(uport->private_data, uport); + + if (port->wakeup_irq > 0) + enable_irq(port->wakeup_irq); + + return 0; } static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev) @@ -1332,6 +1375,9 @@ 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/samsung.c b/drivers/tty/serial/samsung_tty.c index 83fd51607741..83fd51607741 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung_tty.c diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index 2f599515c133..b6ace6290e23 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -1122,8 +1122,7 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup, int ret; struct dma_slave_config dma_sconfig; - dma_chan = dma_request_slave_channel_reason(tup->uport.dev, - dma_to_memory ? "rx" : "tx"); + dma_chan = dma_request_chan(tup->uport.dev, dma_to_memory ? "rx" : "tx"); if (IS_ERR(dma_chan)) { ret = PTR_ERR(dma_chan); dev_err(tup->uport.dev, diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index c4a414a46c7f..b0a6eb106edb 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1111,7 +1111,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state) if (!uport) goto out; - if (uport->type != PORT_UNKNOWN) + if (uport->type != PORT_UNKNOWN && uport->ops->break_ctl) uport->ops->break_ctl(uport, break_state); ret = 0; out: diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h index 004ca684d3ae..637b09d3fe79 100644 --- a/drivers/tty/serial/sirfsoc_uart.h +++ b/drivers/tty/serial/sirfsoc_uart.h @@ -120,7 +120,8 @@ static u32 uart_usp_ff_empty_mask(struct uart_port *port) empty_bit = ilog2(port->fifosize) + 1; return (1 << empty_bit); } -struct sirfsoc_uart_register sirfsoc_usp = { + +static struct sirfsoc_uart_register sirfsoc_usp = { .uart_reg = { .sirfsoc_mode1 = 0x0000, .sirfsoc_mode2 = 0x0004, @@ -186,7 +187,7 @@ struct sirfsoc_uart_register sirfsoc_usp = { }, }; -struct sirfsoc_uart_register sirfsoc_uart = { +static struct sirfsoc_uart_register sirfsoc_uart = { .uart_reg = { .sirfsoc_line_ctrl = 0x0040, .sirfsoc_tx_rx_en = 0x004c, diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index 771d11196523..31df23502562 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -919,6 +919,34 @@ static void sprd_pm(struct uart_port *port, unsigned int state, } } +#ifdef CONFIG_CONSOLE_POLL +static int sprd_poll_init(struct uart_port *port) +{ + if (port->state->pm_state != UART_PM_STATE_ON) { + sprd_pm(port, UART_PM_STATE_ON, 0); + port->state->pm_state = UART_PM_STATE_ON; + } + + return 0; +} + +static int sprd_poll_get_char(struct uart_port *port) +{ + while (!(serial_in(port, SPRD_STS1) & SPRD_RX_FIFO_CNT_MASK)) + cpu_relax(); + + return serial_in(port, SPRD_RXD); +} + +static void sprd_poll_put_char(struct uart_port *port, unsigned char ch) +{ + while (serial_in(port, SPRD_STS1) & SPRD_TX_FIFO_CNT_MASK) + cpu_relax(); + + serial_out(port, SPRD_TXD, ch); +} +#endif + static const struct uart_ops serial_sprd_ops = { .tx_empty = sprd_tx_empty, .get_mctrl = sprd_get_mctrl, @@ -936,6 +964,11 @@ static const struct uart_ops serial_sprd_ops = { .config_port = sprd_config_port, .verify_port = sprd_verify_port, .pm = sprd_pm, +#ifdef CONFIG_CONSOLE_POLL + .poll_init = sprd_poll_init, + .poll_get_char = sprd_poll_get_char, + .poll_put_char = sprd_poll_put_char, +#endif }; #ifdef CONFIG_SERIAL_SPRD_CONSOLE diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index df90747ee3a8..2f72514d63ed 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -240,8 +240,8 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded) * cleared by the sequence [read SR - read DR]. */ if ((sr & USART_SR_ERR_MASK) && ofs->icr != UNDEF_REG) - stm32_clr_bits(port, ofs->icr, USART_ICR_ORECF | - USART_ICR_PECF | USART_ICR_FECF); + writel_relaxed(sr & USART_SR_ERR_MASK, + port->membase + ofs->icr); c = stm32_get_char(port, &sr, &stm32_port->last_res); port->icount.rx++; @@ -435,7 +435,7 @@ static void stm32_transmit_chars(struct uart_port *port) if (ofs->icr == UNDEF_REG) stm32_clr_bits(port, ofs->isr, USART_SR_TC); else - stm32_set_bits(port, ofs->icr, USART_ICR_TCCF); + writel_relaxed(USART_ICR_TCCF, port->membase + ofs->icr); if (stm32_port->tx_ch) stm32_transmit_chars_dma(port); diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index 06e79c11141d..7dbd0c471d92 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -22,7 +22,6 @@ #include <linux/of_device.h> #include <linux/of_platform.h> #include <linux/clk.h> -#include <linux/pm_runtime.h> #define ULITE_NAME "ttyUL" #define ULITE_MAJOR 204 @@ -55,7 +54,6 @@ #define ULITE_CONTROL_RST_TX 0x01 #define ULITE_CONTROL_RST_RX 0x02 #define ULITE_CONTROL_IE 0x10 -#define UART_AUTOSUSPEND_TIMEOUT 3000 /* Static pointer to console port */ #ifdef CONFIG_SERIAL_UARTLITE_CONSOLE @@ -65,7 +63,6 @@ static struct uart_port *console_port; struct uartlite_data { const struct uartlite_reg_ops *reg_ops; struct clk *clk; - struct uart_driver *ulite_uart_driver; }; struct uartlite_reg_ops { @@ -393,12 +390,12 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser) static void ulite_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { - if (!state) { - pm_runtime_get_sync(port->dev); - } else { - pm_runtime_mark_last_busy(port->dev); - pm_runtime_put_autosuspend(port->dev); - } + struct uartlite_data *pdata = port->private_data; + + if (!state) + clk_enable(pdata->clk); + else + clk_disable(pdata->clk); } #ifdef CONFIG_CONSOLE_POLL @@ -697,9 +694,7 @@ static int ulite_release(struct device *dev) int rc = 0; if (port) { - struct uartlite_data *pdata = port->private_data; - - rc = uart_remove_one_port(pdata->ulite_uart_driver, port); + rc = uart_remove_one_port(&ulite_uart_driver, port); dev_set_drvdata(dev, NULL); port->mapbase = 0; } @@ -717,11 +712,8 @@ static int __maybe_unused ulite_suspend(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); - if (port) { - struct uartlite_data *pdata = port->private_data; - - uart_suspend_port(pdata->ulite_uart_driver, port); - } + if (port) + uart_suspend_port(&ulite_uart_driver, port); return 0; } @@ -736,41 +728,17 @@ static int __maybe_unused ulite_resume(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); - if (port) { - struct uartlite_data *pdata = port->private_data; - - uart_resume_port(pdata->ulite_uart_driver, port); - } + if (port) + uart_resume_port(&ulite_uart_driver, port); return 0; } -static int __maybe_unused ulite_runtime_suspend(struct device *dev) -{ - struct uart_port *port = dev_get_drvdata(dev); - struct uartlite_data *pdata = port->private_data; - - clk_disable(pdata->clk); - return 0; -}; - -static int __maybe_unused ulite_runtime_resume(struct device *dev) -{ - struct uart_port *port = dev_get_drvdata(dev); - struct uartlite_data *pdata = port->private_data; - - clk_enable(pdata->clk); - return 0; -} /* --------------------------------------------------------------------- * Platform bus binding */ -static const struct dev_pm_ops ulite_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(ulite_suspend, ulite_resume) - SET_RUNTIME_PM_OPS(ulite_runtime_suspend, - ulite_runtime_resume, NULL) -}; +static SIMPLE_DEV_PM_OPS(ulite_pm_ops, ulite_suspend, ulite_resume); #if defined(CONFIG_OF) /* Match table for of_platform binding */ @@ -795,22 +763,6 @@ static int ulite_probe(struct platform_device *pdev) if (prop) id = be32_to_cpup(prop); #endif - if (id < 0) { - /* Look for a serialN alias */ - id = of_alias_get_id(pdev->dev.of_node, "serial"); - if (id < 0) - id = 0; - } - - if (!ulite_uart_driver.state) { - dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n"); - ret = uart_register_driver(&ulite_uart_driver); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register driver\n"); - return ret; - } - } - pdata = devm_kzalloc(&pdev->dev, sizeof(struct uartlite_data), GFP_KERNEL); if (!pdata) @@ -836,22 +788,24 @@ static int ulite_probe(struct platform_device *pdev) pdata->clk = NULL; } - pdata->ulite_uart_driver = &ulite_uart_driver; ret = clk_prepare_enable(pdata->clk); if (ret) { dev_err(&pdev->dev, "Failed to prepare clock\n"); return ret; } - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT); - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); + if (!ulite_uart_driver.state) { + dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n"); + ret = uart_register_driver(&ulite_uart_driver); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register driver\n"); + return ret; + } + } ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata); - pm_runtime_mark_last_busy(&pdev->dev); - pm_runtime_put_autosuspend(&pdev->dev); + clk_disable(pdata->clk); return ret; } @@ -860,14 +814,9 @@ static int ulite_remove(struct platform_device *pdev) { struct uart_port *port = dev_get_drvdata(&pdev->dev); struct uartlite_data *pdata = port->private_data; - int rc; - clk_unprepare(pdata->clk); - rc = ulite_release(&pdev->dev); - pm_runtime_disable(&pdev->dev); - pm_runtime_set_suspended(&pdev->dev); - pm_runtime_dont_use_autosuspend(&pdev->dev); - return rc; + clk_disable_unprepare(pdata->clk); + return ulite_release(&pdev->dev); } /* work with hotplug and coldplug */ diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index a81807b394d1..d9f54c7d94f2 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1345,9 +1345,12 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) if (!tty->port) tty->port = driver->ports[idx]; - WARN_RATELIMIT(!tty->port, - "%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n", - __func__, tty->driver->name); + if (WARN_RATELIMIT(!tty->port, + "%s: %s driver does not set tty->port. This would crash the kernel. Fix the driver!\n", + __func__, tty->driver->name)) { + retval = -EINVAL; + goto err_release_lock; + } retval = tty_ldisc_lock(tty, 5 * HZ); if (retval) @@ -1925,7 +1928,6 @@ EXPORT_SYMBOL_GPL(tty_kopen); /** * tty_open_by_driver - open a tty device * @device: dev_t of device to open - * @inode: inode of device file * @filp: file pointer to tty * * Performs the driver lookup, checks for a reopen, or otherwise @@ -1938,7 +1940,7 @@ EXPORT_SYMBOL_GPL(tty_kopen); * - concurrent tty driver removal w/ lookup * - concurrent tty removal from driver table */ -static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode, +static struct tty_struct *tty_open_by_driver(dev_t device, struct file *filp) { struct tty_struct *tty; @@ -2030,7 +2032,7 @@ retry_open: tty = tty_open_current_tty(device, filp); if (!tty) - tty = tty_open_by_driver(device, inode, filp); + tty = tty_open_by_driver(device, filp); if (IS_ERR(tty)) { tty_free_file(filp); diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 4c49f53afa3e..ec1f6a48121e 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -156,12 +156,7 @@ static void put_ldops(struct tty_ldisc_ops *ldops) * takes tty_ldiscs_lock to guard against ldisc races */ -#if defined(CONFIG_LDISC_AUTOLOAD) - #define INITIAL_AUTOLOAD_STATE 1 -#else - #define INITIAL_AUTOLOAD_STATE 0 -#endif -static int tty_ldisc_autoload = INITIAL_AUTOLOAD_STATE; +static int tty_ldisc_autoload = IS_BUILTIN(CONFIG_LDISC_AUTOLOAD); static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) { diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 515fc095e3b4..15d33fa0c925 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1491,7 +1491,7 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type, if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev)) kbd_rawcode(value); - if (event_type == EV_KEY) + if (event_type == EV_KEY && event_code <= KEY_MAX) kbd_keycode(event_code, value, HW_RAW(handle->dev)); spin_unlock(&kbd_event_lock); diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index 1f042346e722..778f83ea2249 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c @@ -456,6 +456,9 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) size_t ret; char *con_buf; + if (use_unicode(inode)) + return -EOPNOTSUPP; + con_buf = (char *) __get_free_page(GFP_KERNEL); if (!con_buf) return -ENOMEM; |