diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-01 09:46:00 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-01 09:46:00 -0800 |
commit | db5933225f2fe50d3b91ebbba73ed9c3b703b99a (patch) | |
tree | b0178b4e74c9284d8c7ca6beb46e999b3b15d1f9 /drivers/tty/serial/8250 | |
parent | e4ee8b85b7657d9c769b727038faabdc2e6a3412 (diff) | |
parent | c7e1b4059075c9e8eed101d7cc5da43e95eb5e18 (diff) |
Merge tag 'tty-4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/staging driver updates from Greg KH:
"Here is the big tty/serial driver update for 4.16-rc1.
The usual number of various serial driver fixes and updates to try to
get them to work with crazy hardware configurations (seriously, how
many different ways are hardware engineers going to come up with to
hook up a simple UART?)
There is also some serdev bugfixes and updates, as well as a
smattering of other small fixes in here.
All have been in the linux-next tree for a while, with no reported
issues"
* tag 'tty-4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (65 commits)
tty: serial: exar: Relocate sleep wake-up handling
tty: fix data race between tty_init_dev and flush of buf
serial: imx: fix endless loop during suspend
serial: core: mark port as initialized after successful IRQ change
serdev: only match serdev devices
serdev: do not generate modaliases for controllers
serial: mxs-auart: don't use GPIOF_* with gpiod_get_direction
serial: 8250_dw: Revert "Improve clock rate setting"
MAINTAINERS: Add myself as designated reviewer for 8250_dw
gpio: serial: max310x: Support open-drain configuration for GPIOs
serdev: Fix serdev_uevent failure on ACPI enumerated serdev-controllers
serial: 8250_ingenic: Parse earlycon options
serial: 8250_ingenic: Add support for the JZ4770 SoC
serial: core: Make uart_parse_options take const char* argument
serial: 8250_of: fix return code when probe function fails to get reset
serial: imx: Only wakeup via RTSDEN bit if the system has RTS/CTS
serial: 8250_uniphier: fix error return code in uniphier_uart_probe()
tty: n_gsm: Allow ADM response in addition to UA for control dlci
tty: omap-serial: Fix initial on-boot RTS GPIO level
tty: serial: jsm: Add one check against NULL pointer dereference
...
Diffstat (limited to 'drivers/tty/serial/8250')
-rw-r--r-- | drivers/tty/serial/8250/8250_dw.c | 33 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_exar.c | 34 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_ingenic.c | 17 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_of.c | 5 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_omap.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_port.c | 26 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_uniphier.c | 5 | ||||
-rw-r--r-- | drivers/tty/serial/8250/Kconfig | 1 |
8 files changed, 68 insertions, 55 deletions
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 5bb0c42c88dd..cd1b94a0f451 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -252,31 +252,25 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old) { unsigned int baud = tty_termios_baud_rate(termios); - unsigned int target_rate, min_rate, max_rate; struct dw8250_data *d = p->private_data; long rate; - int i, ret; + int ret; if (IS_ERR(d->clk) || !old) goto out; - /* Find a clk rate within +/-1.6% of an integer multiple of baudx16 */ - target_rate = baud * 16; - min_rate = target_rate - (target_rate >> 6); - max_rate = target_rate + (target_rate >> 6); - - for (i = 1; i <= UART_DIV_MAX; i++) { - rate = clk_round_rate(d->clk, i * target_rate); - if (rate >= i * min_rate && rate <= i * max_rate) - break; - } - if (i <= UART_DIV_MAX) { - clk_disable_unprepare(d->clk); + clk_disable_unprepare(d->clk); + rate = clk_round_rate(d->clk, baud * 16); + if (rate < 0) + ret = rate; + else if (rate == 0) + ret = -ENOENT; + else ret = clk_set_rate(d->clk, rate); - clk_prepare_enable(d->clk); - if (!ret) - p->uartclk = rate; - } + clk_prepare_enable(d->clk); + + if (!ret) + p->uartclk = rate; out: p->status &= ~UPSTAT_AUTOCTS; @@ -515,7 +509,8 @@ static int dw8250_probe(struct platform_device *pdev) /* If no clock rate is defined, fail. */ if (!p->uartclk) { dev_err(dev, "clock rate not defined\n"); - return -EINVAL; + err = -EINVAL; + goto err_clk; } data->pclk = devm_clk_get(dev, "apb_pclk"); diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index a402878c9f30..38af306ca0e8 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -34,6 +34,7 @@ #define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 #define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 +#define UART_EXAR_INT0 0x80 #define UART_EXAR_8XMODE 0x88 /* 8X sampling rate select */ #define UART_EXAR_FCTR 0x08 /* Feature Control Register */ @@ -121,6 +122,7 @@ struct exar8250_board { struct exar8250 { unsigned int nr; struct exar8250_board *board; + void __iomem *virt; int line[0]; }; @@ -131,12 +133,9 @@ static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev, const struct exar8250_board *board = priv->board; unsigned int bar = 0; - if (!pcim_iomap_table(pcidev)[bar] && !pcim_iomap(pcidev, bar, 0)) - return -ENOMEM; - port->port.iotype = UPIO_MEM; port->port.mapbase = pci_resource_start(pcidev, bar) + offset; - port->port.membase = pcim_iomap_table(pcidev)[bar] + offset; + port->port.membase = priv->virt + offset; port->port.regshift = board->reg_shift; return 0; @@ -420,6 +419,25 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev) port->port.private_data = NULL; } +/* + * These Exar UARTs have an extra interrupt indicator that could fire for a + * few interrupts that are not presented/cleared through IIR. One of which is + * a wakeup interrupt when coming out of sleep. These interrupts are only + * cleared by reading global INT0 or INT1 registers as interrupts are + * associated with channel 0. The INT[3:0] registers _are_ accessible from each + * channel's address space, but for the sake of bus efficiency we register a + * dedicated handler at the PCI device level to handle them. + */ +static irqreturn_t exar_misc_handler(int irq, void *data) +{ + struct exar8250 *priv = data; + + /* Clear all PCI interrupts by reading INT0. No effect on IIR */ + ioread8(priv->virt + UART_EXAR_INT0); + + return IRQ_HANDLED; +} + static int exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) { @@ -448,6 +466,9 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) return -ENOMEM; priv->board = board; + priv->virt = pcim_iomap(pcidev, bar, 0); + if (!priv->virt) + return -ENOMEM; pci_set_master(pcidev); @@ -461,6 +482,11 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) uart.port.irq = pci_irq_vector(pcidev, 0); uart.port.dev = &pcidev->dev; + rc = devm_request_irq(&pcidev->dev, uart.port.irq, exar_misc_handler, + IRQF_SHARED, "exar_uart", priv); + if (rc) + return rc; + for (i = 0; i < nr_ports && i < maxnr; i++) { rc = board->setup(priv, pcidev, &uart, i); if (rc) { diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index 6af84900870e..15a8c8dfa92b 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -91,14 +91,22 @@ static int __init ingenic_early_console_setup(struct earlycon_device *dev, const char *opt) { struct uart_port *port = &dev->port; - unsigned int baud, divisor; + unsigned int divisor; + int baud = 115200; if (!dev->port.membase) return -ENODEV; + if (opt) { + unsigned int parity, bits, flow; /* unused for now */ + + uart_parse_options(opt, &baud, &parity, &bits, &flow); + } + ingenic_early_console_setup_clock(dev); - baud = dev->baud ?: 115200; + if (dev->baud) + baud = dev->baud; divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud); early_out(port, UART_IER, 0); @@ -125,6 +133,10 @@ EARLYCON_DECLARE(jz4740_uart, ingenic_early_console_setup); OF_EARLYCON_DECLARE(jz4740_uart, "ingenic,jz4740-uart", ingenic_early_console_setup); +EARLYCON_DECLARE(jz4770_uart, ingenic_early_console_setup); +OF_EARLYCON_DECLARE(jz4770_uart, "ingenic,jz4770-uart", + ingenic_early_console_setup); + EARLYCON_DECLARE(jz4775_uart, ingenic_early_console_setup); OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart", ingenic_early_console_setup); @@ -319,6 +331,7 @@ static const struct ingenic_uart_config jz4780_uart_config = { static const struct of_device_id of_match[] = { { .compatible = "ingenic,jz4740-uart", .data = &jz4740_uart_config }, { .compatible = "ingenic,jz4760-uart", .data = &jz4760_uart_config }, + { .compatible = "ingenic,jz4770-uart", .data = &jz4760_uart_config }, { .compatible = "ingenic,jz4775-uart", .data = &jz4760_uart_config }, { .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config }, { /* sentinel */ } diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 1e67a7e4a5fd..160b8906d9b9 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -136,8 +136,11 @@ static int of_platform_serial_setup(struct platform_device *ofdev, } info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL); - if (IS_ERR(info->rst)) + if (IS_ERR(info->rst)) { + ret = PTR_ERR(info->rst); goto err_dispose; + } + ret = reset_control_deassert(info->rst); if (ret) goto err_dispose; diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index bd40ba402410..57f6eba47f44 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -414,7 +414,7 @@ static void omap_8250_set_termios(struct uart_port *port, /* Up to here it was mostly serial8250_do_set_termios() */ /* - * We enable TRIG_GRANU for RX and TX and additionaly we set + * We enable TRIG_GRANU for RX and TX and additionally we set * SCR_TX_EMPTY bit. The result is the following: * - RX_TRIGGER amount of bytes in the FIFO will cause an interrupt. * - less than RX_TRIGGER number of bytes will also cause an interrupt diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 11434551ac0a..1328c7e70108 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -441,7 +441,6 @@ static void io_serial_out(struct uart_port *p, int offset, int value) } static int serial8250_default_handle_irq(struct uart_port *port); -static int exar_handle_irq(struct uart_port *port); static void set_io_from_upio(struct uart_port *p) { @@ -1884,26 +1883,6 @@ static int serial8250_default_handle_irq(struct uart_port *port) } /* - * These Exar UARTs have an extra interrupt indicator that could - * fire for a few unimplemented interrupts. One of which is a - * wakeup event when coming out of sleep. Put this here just - * to be on the safe side that these interrupts don't go unhandled. - */ -static int exar_handle_irq(struct uart_port *port) -{ - unsigned int iir = serial_port_in(port, UART_IIR); - int ret = 0; - - if (((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) && - serial_port_in(port, UART_EXAR_INT0) != 0) - ret = 1; - - ret |= serial8250_handle_irq(port, iir); - - return ret; -} - -/* * Newer 16550 compatible parts such as the SC16C650 & Altera 16550 Soft IP * have a programmable TX threshold that triggers the THRE interrupt in * the IIR register. In this case, the THRE interrupt indicates the FIFO @@ -3067,11 +3046,6 @@ static void serial8250_config_port(struct uart_port *port, int flags) if (port->type == PORT_UNKNOWN) serial8250_release_std_resource(up); - /* Fixme: probably not the best place for this */ - if ((port->type == PORT_XR17V35X) || - (port->type == PORT_XR17D15X)) - port->handle_irq = exar_handle_irq; - register_dev_spec_attr_grp(up); up->fcr = uart_config[up->port.type].fcr; } diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c index 45ef506293ae..28d88ccf5a0c 100644 --- a/drivers/tty/serial/8250/8250_uniphier.c +++ b/drivers/tty/serial/8250/8250_uniphier.c @@ -250,12 +250,13 @@ static int uniphier_uart_probe(struct platform_device *pdev) up.dl_read = uniphier_serial_dl_read; up.dl_write = uniphier_serial_dl_write; - priv->line = serial8250_register_8250_port(&up); - if (priv->line < 0) { + ret = serial8250_register_8250_port(&up); + if (ret < 0) { dev_err(dev, "failed to register 8250 port\n"); clk_disable_unprepare(priv->clk); return ret; } + priv->line = ret; platform_set_drvdata(pdev, priv); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index a5c0ef1e7695..16b1496e6105 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -5,6 +5,7 @@ config SERIAL_8250 tristate "8250/16550 and compatible serial support" + depends on !S390 select SERIAL_CORE ---help--- This selects whether you want to include the driver for the standard |