From 4d2ae601d80675af025e7a5bcbe918c58b6743aa Mon Sep 17 00:00:00 2001 From: Gavin Thomas Claugus Date: Tue, 1 Dec 2015 19:06:19 -0500 Subject: drivers: serial: jsm: Switch "jsm" to JSM_DRIVER_NAME This commit replaces every instance of the string "jsm" in the driver with JSM_DRIVER_NAME, as the two are equivalent. This should increase overall consistency. Signed-off-by: Gavin Thomas Claugus Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c index efbd87a..a119f11 100644 --- a/drivers/tty/serial/jsm/jsm_driver.c +++ b/drivers/tty/serial/jsm/jsm_driver.c @@ -70,7 +70,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto out; } - rc = pci_request_regions(pdev, "jsm"); + rc = pci_request_regions(pdev, JSM_DRIVER_NAME); if (rc) { dev_err(&pdev->dev, "pci_request_region FAILED\n"); goto out_disable_device; @@ -328,7 +328,7 @@ static struct pci_device_id jsm_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, jsm_pci_tbl); static struct pci_driver jsm_driver = { - .name = "jsm", + .name = JSM_DRIVER_NAME, .id_table = jsm_pci_tbl, .probe = jsm_probe_one, .remove = jsm_remove_one, -- cgit v0.10.2 From 5f8b90431fc9613d4559a602a1070b2270ff4444 Mon Sep 17 00:00:00 2001 From: LABBE Corentin Date: Tue, 24 Nov 2015 15:36:57 +0100 Subject: serial: imx: fix a possible NULL dereference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit of_match_device could return NULL, and so cause a NULL pointer dereference later. Even if the probability of this case is very low, fixing it made static analyzers happy. Solving this with of_device_get_match_data made also code simplier. Signed-off-by: LABBE Corentin Acked-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 016e4be..76818f5 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1857,11 +1857,10 @@ static int serial_imx_probe_dt(struct imx_port *sport, struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - const struct of_device_id *of_id = - of_match_device(imx_uart_dt_ids, &pdev->dev); int ret; - if (!np) + sport->devdata = of_device_get_match_data(&pdev->dev); + if (!sport->devdata) /* no device tree device */ return 1; @@ -1878,8 +1877,6 @@ static int serial_imx_probe_dt(struct imx_port *sport, if (of_get_property(np, "fsl,dte-mode", NULL)) sport->dte_mode = 1; - sport->devdata = of_id->data; - return 0; } #else -- cgit v0.10.2 From 456ad4a138d306ed0137e3330d5e2ff5937c1bf9 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Mon, 19 Oct 2015 14:31:49 +0200 Subject: serial: sh-sci: Add device tree bindings for r8a7793 Also replaces "R-Car M2" with "R-Car M2-W" to avoid confusion. Signed-off-by: Ulrich Hecht Acked-by: Simon Horman Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt index 73f825e..ce23378 100644 --- a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt +++ b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt @@ -15,10 +15,14 @@ Required properties: - "renesas,scifa-r8a7790" for R8A7790 (R-Car H2) SCIFA compatible UART. - "renesas,scifb-r8a7790" for R8A7790 (R-Car H2) SCIFB compatible UART. - "renesas,hscif-r8a7790" for R8A7790 (R-Car H2) HSCIF compatible UART. - - "renesas,scif-r8a7791" for R8A7791 (R-Car M2) SCIF compatible UART. - - "renesas,scifa-r8a7791" for R8A7791 (R-Car M2) SCIFA compatible UART. - - "renesas,scifb-r8a7791" for R8A7791 (R-Car M2) SCIFB compatible UART. - - "renesas,hscif-r8a7791" for R8A7791 (R-Car M2) HSCIF compatible UART. + - "renesas,scif-r8a7791" for R8A7791 (R-Car M2-W) SCIF compatible UART. + - "renesas,scifa-r8a7791" for R8A7791 (R-Car M2-W) SCIFA compatible UART. + - "renesas,scifb-r8a7791" for R8A7791 (R-Car M2-W) SCIFB compatible UART. + - "renesas,hscif-r8a7791" for R8A7791 (R-Car M2-W) HSCIF compatible UART. + - "renesas,scif-r8a7793" for R8A7793 (R-Car M2-N) SCIF compatible UART. + - "renesas,scifa-r8a7793" for R8A7793 (R-Car M2-N) SCIFA compatible UART. + - "renesas,scifb-r8a7793" for R8A7793 (R-Car M2-N) SCIFB compatible UART. + - "renesas,hscif-r8a7793" for R8A7793 (R-Car M2-N) HSCIF compatible UART. - "renesas,scif-r8a7794" for R8A7794 (R-Car E2) SCIF compatible UART. - "renesas,scifa-r8a7794" for R8A7794 (R-Car E2) SCIFA compatible UART. - "renesas,scifb-r8a7794" for R8A7794 (R-Car E2) SCIFB compatible UART. -- cgit v0.10.2 From 18dfef9c7f87b75bbb0fb66a634f7c13a45b9f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 18 Oct 2015 21:34:45 +0200 Subject: serial: atmel: convert to irq handling provided mctrl-gpio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested-by: Nicolas Ferre Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 9429455..002f7f2 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -155,7 +155,6 @@ struct atmel_uart_port { struct circ_buf rx_ring; struct mctrl_gpios *gpios; - int gpio_irq[UART_GPIO_MAX]; unsigned int tx_done_mask; u32 fifo_size; u32 rts_high; @@ -550,27 +549,21 @@ static void atmel_enable_ms(struct uart_port *port) atmel_port->ms_irq_enabled = true; - if (atmel_port->gpio_irq[UART_GPIO_CTS] >= 0) - enable_irq(atmel_port->gpio_irq[UART_GPIO_CTS]); - else + if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) ier |= ATMEL_US_CTSIC; - if (atmel_port->gpio_irq[UART_GPIO_DSR] >= 0) - enable_irq(atmel_port->gpio_irq[UART_GPIO_DSR]); - else + if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DSR)) ier |= ATMEL_US_DSRIC; - if (atmel_port->gpio_irq[UART_GPIO_RI] >= 0) - enable_irq(atmel_port->gpio_irq[UART_GPIO_RI]); - else + if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_RI)) ier |= ATMEL_US_RIIC; - if (atmel_port->gpio_irq[UART_GPIO_DCD] >= 0) - enable_irq(atmel_port->gpio_irq[UART_GPIO_DCD]); - else + if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DCD)) ier |= ATMEL_US_DCDIC; atmel_uart_writel(port, ATMEL_US_IER, ier); + + mctrl_gpio_enable_ms(atmel_port->gpios); } /* @@ -589,24 +582,18 @@ static void atmel_disable_ms(struct uart_port *port) atmel_port->ms_irq_enabled = false; - if (atmel_port->gpio_irq[UART_GPIO_CTS] >= 0) - disable_irq(atmel_port->gpio_irq[UART_GPIO_CTS]); - else + mctrl_gpio_disable_ms(atmel_port->gpios); + + if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) idr |= ATMEL_US_CTSIC; - if (atmel_port->gpio_irq[UART_GPIO_DSR] >= 0) - disable_irq(atmel_port->gpio_irq[UART_GPIO_DSR]); - else + if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DSR)) idr |= ATMEL_US_DSRIC; - if (atmel_port->gpio_irq[UART_GPIO_RI] >= 0) - disable_irq(atmel_port->gpio_irq[UART_GPIO_RI]); - else + if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_RI)) idr |= ATMEL_US_RIIC; - if (atmel_port->gpio_irq[UART_GPIO_DCD] >= 0) - disable_irq(atmel_port->gpio_irq[UART_GPIO_DCD]); - else + if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DCD)) idr |= ATMEL_US_DCDIC; atmel_uart_writel(port, ATMEL_US_IDR, idr); @@ -1264,7 +1251,6 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) struct uart_port *port = dev_id; struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); unsigned int status, pending, mask, pass_counter = 0; - bool gpio_handled = false; spin_lock(&atmel_port->lock_suspended); @@ -1272,24 +1258,6 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) status = atmel_get_lines_status(port); mask = atmel_uart_readl(port, ATMEL_US_IMR); pending = status & mask; - if (!gpio_handled) { - /* - * Dealing with GPIO interrupt - */ - if (irq == atmel_port->gpio_irq[UART_GPIO_CTS]) - pending |= ATMEL_US_CTSIC; - - if (irq == atmel_port->gpio_irq[UART_GPIO_DSR]) - pending |= ATMEL_US_DSRIC; - - if (irq == atmel_port->gpio_irq[UART_GPIO_RI]) - pending |= ATMEL_US_RIIC; - - if (irq == atmel_port->gpio_irq[UART_GPIO_DCD]) - pending |= ATMEL_US_DCDIC; - - gpio_handled = true; - } if (!pending) break; @@ -1778,45 +1746,6 @@ static void atmel_get_ip_name(struct uart_port *port) } } -static void atmel_free_gpio_irq(struct uart_port *port) -{ - struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - enum mctrl_gpio_idx i; - - for (i = 0; i < UART_GPIO_MAX; i++) - if (atmel_port->gpio_irq[i] >= 0) - free_irq(atmel_port->gpio_irq[i], port); -} - -static int atmel_request_gpio_irq(struct uart_port *port) -{ - struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - int *irq = atmel_port->gpio_irq; - enum mctrl_gpio_idx i; - int err = 0; - - for (i = 0; (i < UART_GPIO_MAX) && !err; i++) { - if (irq[i] < 0) - continue; - - irq_set_status_flags(irq[i], IRQ_NOAUTOEN); - err = request_irq(irq[i], atmel_interrupt, IRQ_TYPE_EDGE_BOTH, - "atmel_serial", port); - if (err) - dev_err(port->dev, "atmel_startup - Can't get %d irq\n", - irq[i]); - } - - /* - * If something went wrong, rollback. - */ - while (err && (--i >= 0)) - if (irq[i] >= 0) - free_irq(irq[i], port); - - return err; -} - /* * Perform initialization and enable port for reception */ @@ -1846,13 +1775,6 @@ static int atmel_startup(struct uart_port *port) return retval; } - /* - * Get the GPIO lines IRQ - */ - retval = atmel_request_gpio_irq(port); - if (retval) - goto free_irq; - tasklet_enable(&atmel_port->tasklet); /* @@ -1948,11 +1870,6 @@ static int atmel_startup(struct uart_port *port) } return 0; - -free_irq: - free_irq(port->irq, port); - - return retval; } /* @@ -2018,7 +1935,6 @@ static void atmel_shutdown(struct uart_port *port) * Free the interrupts */ free_irq(port->irq, port); - atmel_free_gpio_irq(port); atmel_port->ms_irq_enabled = false; @@ -2686,26 +2602,6 @@ static int atmel_serial_resume(struct platform_device *pdev) #define atmel_serial_resume NULL #endif -static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev) -{ - enum mctrl_gpio_idx i; - struct gpio_desc *gpiod; - - p->gpios = mctrl_gpio_init_noauto(dev, 0); - if (IS_ERR(p->gpios)) - return PTR_ERR(p->gpios); - - for (i = 0; i < UART_GPIO_MAX; i++) { - gpiod = mctrl_gpio_to_gpiod(p->gpios, i); - if (gpiod && (gpiod_get_direction(gpiod) == GPIOF_DIR_IN)) - p->gpio_irq[i] = gpiod_to_irq(gpiod); - else - p->gpio_irq[i] = -EINVAL; - } - - return 0; -} - static void atmel_serial_probe_fifos(struct atmel_uart_port *port, struct platform_device *pdev) { @@ -2788,16 +2684,16 @@ static int atmel_serial_probe(struct platform_device *pdev) spin_lock_init(&port->lock_suspended); - ret = atmel_init_gpios(port, &pdev->dev); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to initialize GPIOs."); - goto err_clear_bit; - } - ret = atmel_init_port(port, pdev); if (ret) goto err_clear_bit; + port->gpios = mctrl_gpio_init(&port->uart, 0); + if (IS_ERR(port->gpios)) { + ret = PTR_ERR(port->gpios); + goto err_clear_bit; + } + if (!atmel_use_pdc_rx(&port->uart)) { ret = -ENOMEM; data = kmalloc(sizeof(struct atmel_uart_char) -- cgit v0.10.2 From 90ebc4838666d148eac5bbac6f4044e5b25cd2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 18 Oct 2015 21:34:46 +0200 Subject: serial: imx: repair and complete handshaking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .get_mctrl callback should not report the status of RTS or LOOP, so drop this. Instead implement reporting the state of CAR (aka DCD) and RI. For .set_mctrl implement setting the DTR line. Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 76818f5..086675e 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -148,8 +148,11 @@ #define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */ #define USR2_DTRF (1<<13) /* DTR edge interrupt flag */ #define USR2_IDLE (1<<12) /* Idle condition */ +#define USR2_RIDELT (1<<10) /* Ring Interrupt Delta */ +#define USR2_RIIN (1<<9) /* Ring Indicator Input */ #define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */ #define USR2_WAKE (1<<7) /* Wake */ +#define USR2_DCDIN (1<<5) /* Data Carrier Detect Input */ #define USR2_RTSF (1<<4) /* RTS edge interrupt flag */ #define USR2_TXDC (1<<3) /* Transmitter complete */ #define USR2_BRCD (1<<2) /* Break condition */ @@ -804,16 +807,19 @@ static unsigned int imx_tx_empty(struct uart_port *port) static unsigned int imx_get_mctrl(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; - unsigned int tmp = TIOCM_DSR | TIOCM_CAR; + unsigned int tmp = TIOCM_DSR; + unsigned usr1 = readl(sport->port.membase + USR1); - if (readl(sport->port.membase + USR1) & USR1_RTSS) + if (usr1 & USR1_RTSS) tmp |= TIOCM_CTS; - if (readl(sport->port.membase + UCR2) & UCR2_CTS) - tmp |= TIOCM_RTS; + /* in DCE mode DCDIN is always 0 */ + if (!(usr1 & USR2_DCDIN)) + tmp |= TIOCM_CAR; - if (readl(sport->port.membase + uts_reg(sport)) & UTS_LOOP) - tmp |= TIOCM_LOOP; + /* in DCE mode RIIN is always 0 */ + if (readl(sport->port.membase + USR2) & USR2_RIIN) + tmp |= TIOCM_RI; return tmp; } @@ -831,6 +837,11 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) writel(temp, sport->port.membase + UCR2); } + temp = readl(sport->port.membase + UCR3) & ~UCR3_DSR; + if (!(mctrl & TIOCM_DTR)) + temp |= UCR3_DSR; + writel(temp, sport->port.membase + UCR3); + temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP; if (mctrl & TIOCM_LOOP) temp |= UTS_LOOP; -- cgit v0.10.2 From cc568849370bb131d896f4c5933cc72bf7ee603d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 18 Oct 2015 21:34:47 +0200 Subject: serial: imx: reorder functions and simplify a bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that imx_mctrl_check is implemented below imx_get_mctrl the former can call the latter directly instead of via sport->port.ops->get_mctrl. Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 086675e..591f1c2 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -312,51 +312,6 @@ static void imx_port_ucrs_restore(struct uart_port *port, #endif /* - * Handle any change of modem status signal since we were last called. - */ -static void imx_mctrl_check(struct imx_port *sport) -{ - unsigned int status, changed; - - status = sport->port.ops->get_mctrl(&sport->port); - changed = status ^ sport->old_status; - - if (changed == 0) - return; - - sport->old_status = status; - - if (changed & TIOCM_RI) - sport->port.icount.rng++; - if (changed & TIOCM_DSR) - sport->port.icount.dsr++; - if (changed & TIOCM_CAR) - uart_handle_dcd_change(&sport->port, status & TIOCM_CAR); - if (changed & TIOCM_CTS) - uart_handle_cts_change(&sport->port, status & TIOCM_CTS); - - wake_up_interruptible(&sport->port.state->port.delta_msr_wait); -} - -/* - * This is our per-port timeout handler, for checking the - * modem status signals. - */ -static void imx_timeout(unsigned long data) -{ - struct imx_port *sport = (struct imx_port *)data; - unsigned long flags; - - if (sport->port.state) { - spin_lock_irqsave(&sport->port.lock, flags); - imx_mctrl_check(sport); - spin_unlock_irqrestore(&sport->port.lock, flags); - - mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT); - } -} - -/* * interrupts disabled on entry */ static void imx_stop_tx(struct uart_port *port) @@ -868,6 +823,51 @@ static void imx_break_ctl(struct uart_port *port, int break_state) spin_unlock_irqrestore(&sport->port.lock, flags); } +/* + * Handle any change of modem status signal since we were last called. + */ +static void imx_mctrl_check(struct imx_port *sport) +{ + unsigned int status, changed; + + status = imx_get_mctrl(&sport->port); + changed = status ^ sport->old_status; + + if (changed == 0) + return; + + sport->old_status = status; + + if (changed & TIOCM_RI) + sport->port.icount.rng++; + if (changed & TIOCM_DSR) + sport->port.icount.dsr++; + if (changed & TIOCM_CAR) + uart_handle_dcd_change(&sport->port, status & TIOCM_CAR); + if (changed & TIOCM_CTS) + uart_handle_cts_change(&sport->port, status & TIOCM_CTS); + + wake_up_interruptible(&sport->port.state->port.delta_msr_wait); +} + +/* + * This is our per-port timeout handler, for checking the + * modem status signals. + */ +static void imx_timeout(unsigned long data) +{ + struct imx_port *sport = (struct imx_port *)data; + unsigned long flags; + + if (sport->port.state) { + spin_lock_irqsave(&sport->port.lock, flags); + imx_mctrl_check(sport); + spin_unlock_irqrestore(&sport->port.lock, flags); + + mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT); + } +} + #define RX_BUF_SIZE (PAGE_SIZE) static void imx_rx_dma_done(struct imx_port *sport) { -- cgit v0.10.2 From c39dfebc7798956fd2140ae6321786ff35da30c3 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 18 Oct 2015 18:21:16 -0400 Subject: drivers/tty/serial: make serial/atmel_serial.c explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/tty/serial/Kconfig:config SERIAL_ATMEL drivers/tty/serial/Kconfig: bool "AT91 / AT32 on-chip serial port support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We don't replace module.h with init.h since the file already has that. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Nicolas Ferre Cc: Jiri Slaby Cc: linux-serial@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 002f7f2..50e785a 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -22,7 +22,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#include #include #include #include @@ -2762,37 +2761,14 @@ err: return ret; } -static int atmel_serial_remove(struct platform_device *pdev) -{ - struct uart_port *port = platform_get_drvdata(pdev); - struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - int ret = 0; - - tasklet_kill(&atmel_port->tasklet); - - device_init_wakeup(&pdev->dev, 0); - - ret = uart_remove_one_port(&atmel_uart, port); - - kfree(atmel_port->rx_ring.buf); - - /* "port" is allocated statically, so we shouldn't free it */ - - clear_bit(port->line, atmel_ports_in_use); - - clk_put(atmel_port->clk); - - return ret; -} - static struct platform_driver atmel_serial_driver = { .probe = atmel_serial_probe, - .remove = atmel_serial_remove, .suspend = atmel_serial_suspend, .resume = atmel_serial_resume, .driver = { - .name = "atmel_usart", - .of_match_table = of_match_ptr(atmel_serial_dt_ids), + .name = "atmel_usart", + .of_match_table = of_match_ptr(atmel_serial_dt_ids), + .suppress_bind_attrs = true, }, }; @@ -2810,17 +2786,4 @@ static int __init atmel_serial_init(void) return ret; } - -static void __exit atmel_serial_exit(void) -{ - platform_driver_unregister(&atmel_serial_driver); - uart_unregister_driver(&atmel_uart); -} - -module_init(atmel_serial_init); -module_exit(atmel_serial_exit); - -MODULE_AUTHOR("Rick Bronson"); -MODULE_DESCRIPTION("Atmel AT91 / AT32 serial port driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:atmel_usart"); +device_initcall(atmel_serial_init); -- cgit v0.10.2 From d72d391c126e0ffd3047c06c4bef4d795853d5d5 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 18 Oct 2015 18:21:18 -0400 Subject: drivers/tty/serial: make 8250/8250_mtk.c explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/tty/serial/8250/Kconfig:config SERIAL_8250_MT6577 drivers/tty/serial/8250/Kconfig: bool "Mediatek serial port support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. Cc: Jiri Slaby Cc: Matthias Brugger Cc: linux-serial@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mediatek@lists.infradead.org Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index 78883ca..0e590b2 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -16,7 +16,7 @@ */ #include #include -#include +#include #include #include #include @@ -245,23 +245,6 @@ static int mtk8250_probe(struct platform_device *pdev) return 0; } -static int mtk8250_remove(struct platform_device *pdev) -{ - struct mtk8250_data *data = platform_get_drvdata(pdev); - - pm_runtime_get_sync(&pdev->dev); - - serial8250_unregister_port(data->line); - - pm_runtime_disable(&pdev->dev); - pm_runtime_put_noidle(&pdev->dev); - - if (!pm_runtime_status_suspended(&pdev->dev)) - mtk8250_runtime_suspend(&pdev->dev); - - return 0; -} - #ifdef CONFIG_PM_SLEEP static int mtk8250_suspend(struct device *dev) { @@ -292,18 +275,18 @@ static const struct of_device_id mtk8250_of_match[] = { { .compatible = "mediatek,mt6577-uart" }, { /* Sentinel */ } }; -MODULE_DEVICE_TABLE(of, mtk8250_of_match); static struct platform_driver mtk8250_platform_driver = { .driver = { - .name = "mt6577-uart", - .pm = &mtk8250_pm_ops, - .of_match_table = mtk8250_of_match, + .name = "mt6577-uart", + .pm = &mtk8250_pm_ops, + .of_match_table = mtk8250_of_match, + .suppress_bind_attrs = true, + }, .probe = mtk8250_probe, - .remove = mtk8250_remove, }; -module_platform_driver(mtk8250_platform_driver); +builtin_platform_driver(mtk8250_platform_driver); #ifdef CONFIG_SERIAL_8250_CONSOLE static int __init early_mtk8250_setup(struct earlycon_device *device, @@ -319,7 +302,3 @@ static int __init early_mtk8250_setup(struct earlycon_device *device, OF_EARLYCON_DECLARE(mtk8250, "mediatek,mt6577-uart", early_mtk8250_setup); #endif - -MODULE_AUTHOR("Matthias Brugger"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Mediatek 8250 serial port driver"); -- cgit v0.10.2 From b8d20e06eaad4c2bd64746cacd95be9a5d3e747f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 30 Oct 2015 11:46:16 +0900 Subject: serial: 8250_uniphier: add earlycon support This reuses the code of drivers/tty/serial/8250/8250_early.c except - Overwrite device->port.iotype and device->port.regshift for UPIO_MEM32 because of_setup_earlycon() has set them for UPIO_MEM. - Set device->baud to zero to prevent early8250_setup() from initializing the divisor register because port->uartclk does not match the frequency expected by this hardware. Signed-off-by: Masahiro Yamada Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c index d11621e..1e2237a 100644 --- a/drivers/tty/serial/8250/8250_uniphier.c +++ b/drivers/tty/serial/8250/8250_uniphier.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -34,6 +35,29 @@ struct uniphier8250_priv { spinlock_t atomic_write_lock; }; +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init uniphier_early_console_setup(struct earlycon_device *device, + const char *options) +{ + if (!device->port.membase) + return -ENODEV; + + /* This hardware always expects MMIO32 register interface. */ + device->port.iotype = UPIO_MEM32; + device->port.regshift = 2; + + /* + * Do not touch the divisor register in early_serial8250_setup(); + * we assume it has been initialized by a boot loader. + */ + device->baud = 0; + + return early_serial8250_setup(device, options); +} +OF_EARLYCON_DECLARE(uniphier, "socionext,uniphier-uart", + uniphier_early_console_setup); +#endif + /* * The register map is slightly different from that of 8250. * IO callbacks must be overridden for correct access to FCR, LCR, and MCR. -- cgit v0.10.2 From fbccaca9bd099e3b8bc6dfabb8dc6f57ad83d1a8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 23 Oct 2015 22:31:15 +0900 Subject: serial: 8250_ingenic: delete redundant "select SERIAL_EARLYCON" SERIAL_8250_INGENIC depends on SERIAL_8250_CONSOLE, which already selects SERIAL_EARLYCON. This line is redundant. Signed-off-by: Masahiro Yamada Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 6412f14..5d6808c 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -363,7 +363,6 @@ config SERIAL_8250_INGENIC bool "Support for Ingenic SoC serial ports" depends on SERIAL_8250_CONSOLE && OF_FLATTREE select LIBFDT - select SERIAL_EARLYCON help If you have a system using an Ingenic SoC and wish to make use of its UARTs, say Y to this option. If unsure, say N. -- cgit v0.10.2 From 4828d5c30a2e1d300f7ca7c15868cead2ef7fb29 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 23 Oct 2015 22:31:16 +0900 Subject: serial: 8250_ingenic: allow to be independent of SERIAL_8250_CONSOLE This UART driver should not depend on the console. They should be orthogonal. Surround the earlycon code with CONFIG_SERIAL_EARLYCON conditional and rip off "depends on SERIAL_8250_CONSOLE". Signed-off-by: Masahiro Yamada Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index 49394b4..d6e1ec9 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -48,6 +48,7 @@ static const struct of_device_id of_match[]; #define UART_MCR_MDCE BIT(7) #define UART_MCR_FCM BIT(6) +#ifdef CONFIG_SERIAL_EARLYCON static struct earlycon_device *early_device; static uint8_t __init early_in(struct uart_port *port, int offset) @@ -140,6 +141,7 @@ OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart", EARLYCON_DECLARE(jz4780_uart, ingenic_early_console_setup); OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart", ingenic_early_console_setup); +#endif /* CONFIG_SERIAL_EARLYCON */ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value) { diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 5d6808c..25da430 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -361,7 +361,7 @@ config SERIAL_8250_UNIPHIER config SERIAL_8250_INGENIC bool "Support for Ingenic SoC serial ports" - depends on SERIAL_8250_CONSOLE && OF_FLATTREE + depends on OF_FLATTREE select LIBFDT help If you have a system using an Ingenic SoC and wish to make use of -- cgit v0.10.2 From f88d86831b69be7d2ad1ac1ba80af386139e76af Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 17:39:55 +0100 Subject: cyclades: Deinline cyy_readb, save 368 bytes This function compiles to 32 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index d4a1331..9600aa3 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -299,7 +299,7 @@ static inline void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val) cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val); } -static inline u8 cyy_readb(struct cyclades_port *port, u32 reg) +static u8 cyy_readb(struct cyclades_port *port, u32 reg) { struct cyclades_card *card = port->card; -- cgit v0.10.2 From f25d596fc2ef038ec91e1135ea7c7717bbd85f55 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 17:39:56 +0100 Subject: cyclades: Deinline cyy_writeb, save 880 bytes This function compiles to 35 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index 9600aa3..da15d16 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -292,7 +292,7 @@ static void cyz_rx_restart(unsigned long); static struct timer_list cyz_rx_full_timer[NR_PORTS]; #endif /* CONFIG_CYZ_INTR */ -static inline void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val) +static void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val) { struct cyclades_card *card = port->card; -- cgit v0.10.2 From 8c6ba003ee4dd43448b3986108f9d5299543b53f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 17:39:57 +0100 Subject: cyclades: Deinline serial_paranoia_check, save 304 bytes This function compiles to 52 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index da15d16..6ddf903 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -329,7 +329,7 @@ static inline bool cyz_is_loaded(struct cyclades_card *card) readl(&fw_id->signature) == ZFIRM_ID; } -static inline int serial_paranoia_check(struct cyclades_port *info, +static int serial_paranoia_check(struct cyclades_port *info, const char *name, const char *routine) { #ifdef SERIAL_PARANOIA_CHECK -- cgit v0.10.2 From 810e20e705d76b6d3229b4417ab2ba1e178a92fa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 17:39:58 +0100 Subject: isicom: Deinline WaitTillCardIsFree, save 1120 bytes This function compiles to 96 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index 2054427..c7698fb 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -220,7 +220,7 @@ static struct isi_port isi_ports[PORT_COUNT]; * it wants to talk. */ -static inline int WaitTillCardIsFree(unsigned long base) +static int WaitTillCardIsFree(unsigned long base) { unsigned int count = 0; unsigned int a = in_atomic(); /* do we run under spinlock? */ -- cgit v0.10.2 From 1a5b34ebebf9be06b03a801cc12a676f2af42a9f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 17:39:59 +0100 Subject: serial/bcm63xx_uart: Deinline wait_for_xmitr, save 374 bytes This function compiles to 141 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c index a1c0a89..c28e5c24 100644 --- a/drivers/tty/serial/bcm63xx_uart.c +++ b/drivers/tty/serial/bcm63xx_uart.c @@ -653,7 +653,7 @@ static struct uart_ops bcm_uart_ops = { #ifdef CONFIG_SERIAL_BCM63XX_CONSOLE -static inline void wait_for_xmitr(struct uart_port *port) +static void wait_for_xmitr(struct uart_port *port) { unsigned int tmout; -- cgit v0.10.2 From 6d70f46ba0012d0cc4ade4d0eaad9db61b2e54bb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 17:40:00 +0100 Subject: serial/jsm: Deinline neo_parse_isr, save 688 bytes This function compiles to 811 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c index 932b2ac..c6fdd63 100644 --- a/drivers/tty/serial/jsm/jsm_neo.c +++ b/drivers/tty/serial/jsm/jsm_neo.c @@ -714,7 +714,7 @@ static void neo_clear_break(struct jsm_channel *ch) /* * Parse the ISR register. */ -static inline void neo_parse_isr(struct jsm_board *brd, u32 port) +static void neo_parse_isr(struct jsm_board *brd, u32 port) { struct jsm_channel *ch; u8 isr; -- cgit v0.10.2 From f4581cab8ddd7270e6f342b163191e30e1398d74 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 17:40:01 +0100 Subject: serial_core: Deinline uart_update_mctrl, save 304 bytes This function compiles to 92 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index def5199..22cfc32 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -110,7 +110,7 @@ static void uart_start(struct tty_struct *tty) spin_unlock_irqrestore(&port->lock, flags); } -static inline void +static void uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) { unsigned long flags; -- cgit v0.10.2 From cb128f69ca61b456126280bb9a969befe7cfdd7c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 17:40:02 +0100 Subject: tty/tty_ldisc: Deinline tty_ldisc_put, save 368 bytes This function compiles to 72 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 629e3c8..7d43ff1 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -185,7 +185,7 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) * * Complement of tty_ldisc_get(). */ -static inline void tty_ldisc_put(struct tty_ldisc *ld) +static void tty_ldisc_put(struct tty_ldisc *ld) { if (WARN_ON_ONCE(!ld)) return; -- cgit v0.10.2 From 1c82363eef25420f41a49a53cda9f0f9e513bb38 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:33 +0100 Subject: cyclades: Deinline cyz_is_loaded, save 240 bytes This function compiles to 58 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index 6ddf903..abbed20 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -321,7 +321,7 @@ static inline bool cyz_fpga_loaded(struct cyclades_card *card) return __cyz_fpga_loaded(card->ctl_addr.p9060); } -static inline bool cyz_is_loaded(struct cyclades_card *card) +static bool cyz_is_loaded(struct cyclades_card *card) { struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS; -- cgit v0.10.2 From 9428d712d1b42c48ab92e3466d58bf3ee5c9f58f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:34 +0100 Subject: isicom: Deinline drop_dtr, save 112 bytes This function compiles to 181 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index c7698fb..9987594 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -280,7 +280,7 @@ static void raise_dtr(struct isi_port *port) } /* card->lock HAS to be held */ -static inline void drop_dtr(struct isi_port *port) +static void drop_dtr(struct isi_port *port) { struct isi_board *card = port->card; unsigned long base = card->base; -- cgit v0.10.2 From 9cdb933274662c4bf1a16146f4731782661b9831 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:37 +0100 Subject: serial/m32r_sio: Deinline wait_for_xmitr, save 165 bytes This function compiles to 141 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 8f7f83a..0eeb64f 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -990,7 +990,7 @@ static void __init m32r_sio_register_ports(struct uart_driver *drv) /* * Wait for transmitter & holding register to empty */ -static inline void wait_for_xmitr(struct uart_sio_port *up) +static void wait_for_xmitr(struct uart_sio_port *up) { unsigned int status, tmout = 10000; -- cgit v0.10.2 From fed76af0c7d005cb4b7d9b19d6d43137149b77ef Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:38 +0100 Subject: serial/men_z135_uart: Deinline men_z135_reg_clr, save 176 bytes This function compiles to 98 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Greg Kroah-Hartman CC: Peter Hurley CC: Jiri Slaby CC: linux-serial@vger.kernel.org Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/men_z135_uart.c b/drivers/tty/serial/men_z135_uart.c index 3141aa2..a44290e 100644 --- a/drivers/tty/serial/men_z135_uart.c +++ b/drivers/tty/serial/men_z135_uart.c @@ -158,7 +158,7 @@ static inline void men_z135_reg_set(struct men_z135_port *uart, * @addr: Register address * @val: value to clear */ -static inline void men_z135_reg_clr(struct men_z135_port *uart, +static void men_z135_reg_clr(struct men_z135_port *uart, u32 addr, u32 val) { struct uart_port *port = &uart->port; -- cgit v0.10.2 From 2172076d2399660a1f49ee5a228ebcb56a2c3544 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:40 +0100 Subject: serial/omap-serial: Deinline wait_for_xmitr, save 165 bytes This function compiles to 141 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 9d4c84f..b645f92 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1165,7 +1165,7 @@ serial_omap_type(struct uart_port *port) #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) -static inline void wait_for_xmitr(struct uart_omap_port *up) +static void wait_for_xmitr(struct uart_omap_port *up) { unsigned int status, tmout = 10000; -- cgit v0.10.2 From be9ae5d9f7d771879dc93766e5cf8d923aed0e1e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:41 +0100 Subject: serial/pxa: Deinline wait_for_xmitr, save 165 bytes This function compiles to 141 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index 9becba6..41eab75 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -603,7 +603,7 @@ static struct uart_driver serial_pxa_reg; /* * Wait for transmitter & holding register to empty */ -static inline void wait_for_xmitr(struct uart_pxa_port *up) +static void wait_for_xmitr(struct uart_pxa_port *up) { unsigned int status, tmout = 10000; -- cgit v0.10.2 From 63744a690280d5b6981231072ba147c0c8b6da2e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:42 +0100 Subject: serial/sprd_serial: Deinline wait_for_xmitr, save 165 bytes This function compiles to 141 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index 9dbae01..ef26c4a 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -517,7 +517,7 @@ static struct uart_ops serial_sprd_ops = { }; #ifdef CONFIG_SERIAL_SPRD_CONSOLE -static inline void wait_for_xmitr(struct uart_port *port) +static void wait_for_xmitr(struct uart_port *port) { unsigned int status, tmout = 10000; -- cgit v0.10.2 From 0d5547ca1bd7c7f55dab39c700e27ed33ff7eeef Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:43 +0100 Subject: serial/sunsu: Deinline wait_for_xmitr, save 165 bytes This function compiles to 141 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index e124d2e..9ad98ea 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -1262,7 +1262,7 @@ static int sunsu_kbd_ms_init(struct uart_sunsu_port *up) /* * Wait for transmitter & holding register to empty */ -static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up) +static void wait_for_xmitr(struct uart_sunsu_port *up) { unsigned int status, tmout = 10000; -- cgit v0.10.2 From eba3b47b26191385326406903120ca6f88300785 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:44 +0100 Subject: serial/vt8500_serial: Deinline wait_for_xmitr, save 165 bytes This function compiles to 141 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 4079ec5..b384060 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -485,7 +485,7 @@ static struct uart_driver vt8500_uart_driver; #ifdef CONFIG_SERIAL_VT8500_CONSOLE -static inline void wait_for_xmitr(struct uart_port *port) +static void wait_for_xmitr(struct uart_port *port) { unsigned int status, tmout = 10000; -- cgit v0.10.2 From fc0285f210500acad01dd8bd578dcd7f013db064 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:45 +0100 Subject: tty: Deinline __ldsem_down_read_nested, save 128 bytes This function compiles to 479 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c index ad7eba5..f901089 100644 --- a/drivers/tty/tty_ldsem.c +++ b/drivers/tty/tty_ldsem.c @@ -319,7 +319,7 @@ down_write_failed(struct ld_semaphore *sem, long count, long timeout) -static inline int __ldsem_down_read_nested(struct ld_semaphore *sem, +static int __ldsem_down_read_nested(struct ld_semaphore *sem, int subclass, long timeout) { long count; -- cgit v0.10.2 From 5ef6504e9d0dcada48384b41d2cd77dba295bd36 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:46 +0100 Subject: tty: Deinline __ldsem_down_write_nested, save 128 bytes This function compiles to 491 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c index f901089..1bf8ed1 100644 --- a/drivers/tty/tty_ldsem.c +++ b/drivers/tty/tty_ldsem.c @@ -338,7 +338,7 @@ static int __ldsem_down_read_nested(struct ld_semaphore *sem, return 1; } -static inline int __ldsem_down_write_nested(struct ld_semaphore *sem, +static int __ldsem_down_write_nested(struct ld_semaphore *sem, int subclass, long timeout) { long count; -- cgit v0.10.2 From c0f160a7355380e9b7f9c5cbb1a0f9eecf6ec601 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Oct 2015 18:46:47 +0100 Subject: vt: Deinline save_screen, save 238 bytes This function compiles to 79 bytes of machine code. Signed-off-by: Denys Vlasenko CC: Jiri Slaby CC: linux-serial@vger.kernel.org Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 4462d16..e7cbc44 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -634,7 +634,7 @@ static void set_origin(struct vc_data *vc) vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x; } -static inline void save_screen(struct vc_data *vc) +static void save_screen(struct vc_data *vc) { WARN_CONSOLE_UNLOCKED(); -- cgit v0.10.2 From 2cda227bba7e8398c6f8a7792c7f35818187dcc6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 30 Oct 2015 11:39:03 +0900 Subject: serial: 8250_early: do not save and restore IER in write callback The IER has already been masked in early_serial8250_setup(), there is no reason to save and restore it every time early_serial8250_write() is called. Signed-off-by: Masahiro Yamada Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index ceb8579..5afc4d4 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -96,20 +96,11 @@ static void __init early_serial8250_write(struct console *console, { struct earlycon_device *device = console->data; struct uart_port *port = &device->port; - unsigned int ier; - - /* Save the IER and disable interrupts preserving the UUE bit */ - ier = serial8250_early_in(port, UART_IER); - if (ier) - serial8250_early_out(port, UART_IER, ier & UART_IER_UUE); uart_console_write(port, s, count, serial_putc); - /* Wait for transmitter to become empty and restore the IER */ + /* Wait for transmitter to become empty */ wait_for_xmitr(port); - - if (ier) - serial8250_early_out(port, UART_IER, ier); } static void __init init_port(struct earlycon_device *device) -- cgit v0.10.2 From f2bfdb0628d50339a70de475eb2be1c4c1eb9014 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 30 Oct 2015 11:39:04 +0900 Subject: serial: 8250_early: confirm empty transmitter after sending characters The current code waits until the transmitter becomes empty, before sending each character, and after finishing the whole string. This seems a bit redundant. It can be more efficient by checking the transmitter only after sending each character. This should be safe because the transmitter is already empty at the first entry of serial_putc(). Signed-off-by: Masahiro Yamada Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index 5afc4d4..20ec27b 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -87,8 +87,8 @@ static void __init wait_for_xmitr(struct uart_port *port) static void __init serial_putc(struct uart_port *port, int c) { - wait_for_xmitr(port); serial8250_early_out(port, UART_TX, c); + wait_for_xmitr(port); } static void __init early_serial8250_write(struct console *console, @@ -98,9 +98,6 @@ static void __init early_serial8250_write(struct console *console, struct uart_port *port = &device->port; uart_console_write(port, s, count, serial_putc); - - /* Wait for transmitter to become empty */ - wait_for_xmitr(port); } static void __init init_port(struct earlycon_device *device) -- cgit v0.10.2 From 004e2ed5cc6d89201140ca96693bf9c0b2945f43 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 30 Oct 2015 11:39:05 +0900 Subject: serial: 8250_early: squash wait_for_xmitr() into serial_putc() Now, wait_for_xmitr() is only called from serial_putc(), and both are short enough. They can be merged into a single function. Signed-off-by: Masahiro Yamada Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index 20ec27b..ca16195 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -73,24 +73,20 @@ static void __init serial8250_early_out(struct uart_port *port, int offset, int #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) -static void __init wait_for_xmitr(struct uart_port *port) +static void __init serial_putc(struct uart_port *port, int c) { unsigned int status; + serial8250_early_out(port, UART_TX, c); + for (;;) { status = serial8250_early_in(port, UART_LSR); if ((status & BOTH_EMPTY) == BOTH_EMPTY) - return; + break; cpu_relax(); } } -static void __init serial_putc(struct uart_port *port, int c) -{ - serial8250_early_out(port, UART_TX, c); - wait_for_xmitr(port); -} - static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count) { -- cgit v0.10.2 From bd94c4077a0b2ecc35562c294f80f3659ecd8499 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 28 Oct 2015 12:46:05 +0900 Subject: serial: support 16-bit register interface for console Currently, 8-bit (MMIO) and 32-bit (MMIO32) register interfaces are supported for the 8250 console, but the 16-bit (MMIO16) is not. The 8250 UART device on my board is connected to a 16-bit bus and my main motivation is to use earlycon with it. (Refer to arch/arm/boot/dts/uniphier-support-card.dtsi) Signed-off-by: Masahiro Yamada Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 742f69d..054e11d 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -721,16 +721,17 @@ bytes respectively. Such letter suffixes can also be entirely omitted. uart[8250],io,[,options] uart[8250],mmio,[,options] + uart[8250],mmio16,[,options] uart[8250],mmio32,[,options] uart[8250],0x[,options] Start an early, polled-mode console on the 8250/16550 UART at the specified I/O port or MMIO address, switching to the matching ttyS device later. MMIO inter-register address stride is either 8-bit - (mmio) or 32-bit (mmio32). - If none of [io|mmio|mmio32], is assumed to be - equivalent to 'mmio'. 'options' are specified in the - same format described for ttyS above; if unspecified, + (mmio), 16-bit (mmio16), or 32-bit (mmio32). + If none of [io|mmio|mmio16|mmio32], is assumed + to be equivalent to 'mmio'. 'options' are specified in + the same format described for ttyS above; if unspecified, the h/w is not re-initialized. hvc Use the hypervisor console device . This is for diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 3912646..c9720a9 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -620,7 +620,7 @@ static int univ8250_console_setup(struct console *co, char *options) * @options: ptr to option string from console command line * * Only attempts to match console command lines of the form: - * console=uart[8250],io|mmio|mmio32,[,] + * console=uart[8250],io|mmio|mmio16|mmio32,[,] * console=uart[8250],0x[,] * This form is used to register an initial earlycon boot console and * replace it with the serial8250_console at 8250 driver init. @@ -650,8 +650,9 @@ static int univ8250_console_match(struct console *co, char *name, int idx, if (port->iotype != iotype) continue; - if ((iotype == UPIO_MEM || iotype == UPIO_MEM32) && - (port->mapbase != addr)) + if ((iotype == UPIO_MEM || iotype == UPIO_MEM16 || + iotype == UPIO_MEM32 || iotype == UPIO_MEM32BE) + && (port->mapbase != addr)) continue; if (iotype == UPIO_PORT && port->iobase != addr) continue; diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index ca16195..af62131 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -42,6 +42,8 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse switch (port->iotype) { case UPIO_MEM: return readb(port->membase + offset); + case UPIO_MEM16: + return readw(port->membase + (offset << 1)); case UPIO_MEM32: return readl(port->membase + (offset << 2)); case UPIO_MEM32BE: @@ -59,6 +61,9 @@ static void __init serial8250_early_out(struct uart_port *port, int offset, int case UPIO_MEM: writeb(value, port->membase + offset); break; + case UPIO_MEM16: + writew(value, port->membase + (offset << 1)); + break; case UPIO_MEM32: writel(value, port->membase + (offset << 2)); break; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 52d82d2..8d262bc 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -368,6 +368,18 @@ static void mem_serial_out(struct uart_port *p, int offset, int value) writeb(value, p->membase + offset); } +static void mem16_serial_out(struct uart_port *p, int offset, int value) +{ + offset = offset << p->regshift; + writew(value, p->membase + offset); +} + +static unsigned int mem16_serial_in(struct uart_port *p, int offset) +{ + offset = offset << p->regshift; + return readw(p->membase + offset); +} + static void mem32_serial_out(struct uart_port *p, int offset, int value) { offset = offset << p->regshift; @@ -425,6 +437,11 @@ static void set_io_from_upio(struct uart_port *p) p->serial_out = mem_serial_out; break; + case UPIO_MEM16: + p->serial_in = mem16_serial_in; + p->serial_out = mem16_serial_out; + break; + case UPIO_MEM32: p->serial_in = mem32_serial_in; p->serial_out = mem32_serial_out; @@ -459,6 +476,7 @@ serial_port_out_sync(struct uart_port *p, int offset, int value) { switch (p->iotype) { case UPIO_MEM: + case UPIO_MEM16: case UPIO_MEM32: case UPIO_MEM32BE: case UPIO_AU: @@ -2462,6 +2480,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) case UPIO_TSI: case UPIO_MEM32: case UPIO_MEM32BE: + case UPIO_MEM16: case UPIO_MEM: if (!port->mapbase) break; @@ -2499,6 +2518,7 @@ static void serial8250_release_std_resource(struct uart_8250_port *up) case UPIO_TSI: case UPIO_MEM32: case UPIO_MEM32BE: + case UPIO_MEM16: case UPIO_MEM: if (!port->mapbase) break; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index f096360..07f7393 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -71,10 +71,16 @@ static int __init parse_options(struct earlycon_device *device, char *options) return -EINVAL; switch (port->iotype) { + case UPIO_MEM: + port->mapbase = addr; + break; + case UPIO_MEM16: + port->regshift = 1; + port->mapbase = addr; + break; case UPIO_MEM32: case UPIO_MEM32BE: - port->regshift = 2; /* fall-through */ - case UPIO_MEM: + port->regshift = 2; port->mapbase = addr; break; case UPIO_PORT: @@ -91,10 +97,11 @@ static int __init parse_options(struct earlycon_device *device, char *options) strlcpy(device->options, options, length); } - if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32 || - port->iotype == UPIO_MEM32BE) + if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 || + port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE) pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n", (port->iotype == UPIO_MEM) ? "" : + (port->iotype == UPIO_MEM16) ? "16" : (port->iotype == UPIO_MEM32) ? "32" : "32be", (unsigned long long)port->mapbase, device->options); diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index de50296..6d002ee 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -122,6 +122,9 @@ static int of_platform_serial_setup(struct platform_device *ofdev, case 1: port->iotype = UPIO_MEM; break; + case 2: + port->iotype = UPIO_MEM16; + break; case 4: port->iotype = of_device_is_big_endian(np) ? UPIO_MEM32BE : UPIO_MEM32; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 22cfc32..b1f54ab 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1818,8 +1818,8 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co) * @options: ptr for field; NULL if not present (out) * * Decodes earlycon kernel command line parameters of the form - * earlycon=,io|mmio|mmio32|mmio32be|mmio32native,, - * console=,io|mmio|mmio32|mmio32be|mmio32native,, + * earlycon=,io|mmio|mmio16|mmio32|mmio32be|mmio32native,, + * console=,io|mmio|mmio16|mmio32|mmio32be|mmio32native,, * * The optional form * earlycon=,0x, @@ -1834,6 +1834,9 @@ int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr, if (strncmp(p, "mmio,", 5) == 0) { *iotype = UPIO_MEM; p += 5; + } else if (strncmp(p, "mmio16,", 7) == 0) { + *iotype = UPIO_MEM16; + p += 7; } else if (strncmp(p, "mmio32,", 7) == 0) { *iotype = UPIO_MEM32; p += 7; @@ -2186,6 +2189,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) "I/O 0x%lx offset 0x%x", port->iobase, port->hub6); break; case UPIO_MEM: + case UPIO_MEM16: case UPIO_MEM32: case UPIO_MEM32BE: case UPIO_AU: @@ -2831,6 +2835,7 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2) return (port1->iobase == port2->iobase) && (port1->hub6 == port2->hub6); case UPIO_MEM: + case UPIO_MEM16: case UPIO_MEM32: case UPIO_MEM32BE: case UPIO_AU: diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 297d4fa..35aa87b 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -150,6 +150,7 @@ struct uart_port { #define UPIO_AU (SERIAL_IO_AU) /* Au1x00 and RT288x type IO */ #define UPIO_TSI (SERIAL_IO_TSI) /* Tsi108/109 type IO */ #define UPIO_MEM32BE (SERIAL_IO_MEM32BE) /* 32b big endian */ +#define UPIO_MEM16 (SERIAL_IO_MEM16) /* 16b little endian */ unsigned int read_status_mask; /* driver specific */ unsigned int ignore_status_mask; /* driver specific */ diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h index 25331f9..5d59c3e 100644 --- a/include/uapi/linux/serial.h +++ b/include/uapi/linux/serial.h @@ -69,6 +69,7 @@ struct serial_struct { #define SERIAL_IO_AU 4 #define SERIAL_IO_TSI 5 #define SERIAL_IO_MEM32BE 6 +#define SERIAL_IO_MEM16 7 #define UART_CLEAR_FIFO 0x01 #define UART_USE_FIFO 0x02 -- cgit v0.10.2 From 7583633921d54f33e96b65569a0c980ae1d05dba Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 3 Nov 2015 14:50:58 +0000 Subject: tty: amba-pl011: add register accessor functions Add register accessor functions to amba-pl011. Much of this transformation was done using the sed expression below, with any left-overs fixed up manually afterwards, and code formatted to remain within coding style. s/readw(\(uap->port.membase\|regs\|port->membase\) +/pl011_read(\1,/g s/writew(\(.*\) +/pl011_write(\1,/g Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 899a771..bd01e75 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -184,6 +184,16 @@ struct uart_amba_port { #endif }; +static unsigned int pl011_read(void __iomem *base, unsigned int reg) +{ + return readw(base + reg); +} + +static void pl011_write(unsigned int val, void __iomem *base, unsigned int reg) +{ + writew(val, base + reg); +} + /* * Reads up to 256 characters from the FIFO or until it's empty and * inserts them into the TTY layer. Returns the number of characters @@ -196,12 +206,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) int fifotaken = 0; while (max_count--) { - status = readw(uap->port.membase + UART01x_FR); + status = pl011_read(uap->port.membase, UART01x_FR); if (status & UART01x_FR_RXFE) break; /* Take chars from the FIFO and update status */ - ch = readw(uap->port.membase + UART01x_DR) | + ch = pl011_read(uap->port.membase, UART01x_DR) | UART_DUMMY_DR_RX; flag = TTY_NORMAL; uap->port.icount.rx++; @@ -438,7 +448,7 @@ static void pl011_dma_tx_callback(void *data) dmacr = uap->dmacr; uap->dmacr = dmacr & ~UART011_TXDMAE; - writew(uap->dmacr, uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); /* * If TX DMA was disabled, it means that we've stopped the DMA for @@ -552,7 +562,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap) dma_dev->device_issue_pending(chan); uap->dmacr |= UART011_TXDMAE; - writew(uap->dmacr, uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); uap->dmatx.queued = true; /* @@ -588,9 +598,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap) */ if (uap->dmatx.queued) { uap->dmacr |= UART011_TXDMAE; - writew(uap->dmacr, uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); uap->im &= ~UART011_TXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); return true; } @@ -600,7 +610,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap) */ if (pl011_dma_tx_refill(uap) > 0) { uap->im &= ~UART011_TXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); return true; } return false; @@ -614,7 +624,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap) { if (uap->dmatx.queued) { uap->dmacr &= ~UART011_TXDMAE; - writew(uap->dmacr, uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); } } @@ -640,14 +650,14 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) if (!uap->dmatx.queued) { if (pl011_dma_tx_refill(uap) > 0) { uap->im &= ~UART011_TXIM; - writew(uap->im, uap->port.membase + - UART011_IMSC); + pl011_write(uap->im, uap->port.membase, + UART011_IMSC); } else ret = false; } else if (!(uap->dmacr & UART011_TXDMAE)) { uap->dmacr |= UART011_TXDMAE; - writew(uap->dmacr, - uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, + UART011_DMACR); } return ret; } @@ -658,9 +668,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) */ dmacr = uap->dmacr; uap->dmacr &= ~UART011_TXDMAE; - writew(uap->dmacr, uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); - if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) { + if (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF) { /* * No space in the FIFO, so enable the transmit interrupt * so we know when there is space. Note that once we've @@ -669,13 +679,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) return false; } - writew(uap->port.x_char, uap->port.membase + UART01x_DR); + pl011_write(uap->port.x_char, uap->port.membase, UART01x_DR); uap->port.icount.tx++; uap->port.x_char = 0; /* Success - restore the DMA state */ uap->dmacr = dmacr; - writew(dmacr, uap->port.membase + UART011_DMACR); + pl011_write(dmacr, uap->port.membase, UART011_DMACR); return true; } @@ -703,7 +713,7 @@ __acquires(&uap->port.lock) DMA_TO_DEVICE); uap->dmatx.queued = false; uap->dmacr &= ~UART011_TXDMAE; - writew(uap->dmacr, uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); } } @@ -743,11 +753,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap) dma_async_issue_pending(rxchan); uap->dmacr |= UART011_RXDMAE; - writew(uap->dmacr, uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); uap->dmarx.running = true; uap->im &= ~UART011_RXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); return 0; } @@ -805,8 +815,8 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, */ if (dma_count == pending && readfifo) { /* Clear any error flags */ - writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS, - uap->port.membase + UART011_ICR); + pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS | + UART011_FEIS, uap->port.membase, UART011_ICR); /* * If we read all the DMA'd characters, and we had an @@ -854,7 +864,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) /* Disable RX DMA - incoming data will wait in the FIFO */ uap->dmacr &= ~UART011_RXDMAE; - writew(uap->dmacr, uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); uap->dmarx.running = false; pending = sgbuf->sg.length - state.residue; @@ -874,7 +884,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) dev_dbg(uap->port.dev, "could not retrigger RX DMA job " "fall back to interrupt mode\n"); uap->im |= UART011_RXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); } } @@ -922,7 +932,7 @@ static void pl011_dma_rx_callback(void *data) dev_dbg(uap->port.dev, "could not retrigger RX DMA job " "fall back to interrupt mode\n"); uap->im |= UART011_RXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); } } @@ -935,7 +945,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap) { /* FIXME. Just disable the DMA enable */ uap->dmacr &= ~UART011_RXDMAE; - writew(uap->dmacr, uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); } /* @@ -979,7 +989,7 @@ static void pl011_dma_rx_poll(unsigned long args) spin_lock_irqsave(&uap->port.lock, flags); pl011_dma_rx_stop(uap); uap->im |= UART011_RXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); spin_unlock_irqrestore(&uap->port.lock, flags); uap->dmarx.running = false; @@ -1041,7 +1051,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap) skip_rx: /* Turn on DMA error (RX/TX will be enabled on demand) */ uap->dmacr |= UART011_DMAONERR; - writew(uap->dmacr, uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); /* * ST Micro variants has some specific dma burst threshold @@ -1049,8 +1059,8 @@ skip_rx: * be issued above/below 16 bytes. */ if (uap->vendor->dma_threshold) - writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16, - uap->port.membase + ST_UART011_DMAWM); + pl011_write(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16, + uap->port.membase, ST_UART011_DMAWM); if (uap->using_rx_dma) { if (pl011_dma_rx_trigger_dma(uap)) @@ -1075,12 +1085,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) return; /* Disable RX and TX DMA */ - while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) + while (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_BUSY) barrier(); spin_lock_irq(&uap->port.lock); uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE); - writew(uap->dmacr, uap->port.membase + UART011_DMACR); + pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); spin_unlock_irq(&uap->port.lock); if (uap->using_tx_dma) { @@ -1181,7 +1191,7 @@ static void pl011_stop_tx(struct uart_port *port) container_of(port, struct uart_amba_port, port); uap->im &= ~UART011_TXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); pl011_dma_tx_stop(uap); } @@ -1191,7 +1201,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq); static void pl011_start_tx_pio(struct uart_amba_port *uap) { uap->im |= UART011_TXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); pl011_tx_chars(uap, false); } @@ -1211,7 +1221,7 @@ static void pl011_stop_rx(struct uart_port *port) uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM| UART011_PEIM|UART011_BEIM|UART011_OEIM); - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); pl011_dma_rx_stop(uap); } @@ -1222,7 +1232,7 @@ static void pl011_enable_ms(struct uart_port *port) container_of(port, struct uart_amba_port, port); uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM; - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); } static void pl011_rx_chars(struct uart_amba_port *uap) @@ -1242,7 +1252,7 @@ __acquires(&uap->port.lock) dev_dbg(uap->port.dev, "could not trigger RX DMA job " "fall back to interrupt mode again\n"); uap->im |= UART011_RXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); } else { #ifdef CONFIG_DMA_ENGINE /* Start Rx DMA poll */ @@ -1263,10 +1273,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c, bool from_irq) { if (unlikely(!from_irq) && - readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) + pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF) return false; /* unable to transmit character */ - writew(c, uap->port.membase + UART01x_DR); + pl011_write(c, uap->port.membase, UART01x_DR); uap->port.icount.tx++; return true; @@ -1313,7 +1323,8 @@ static void pl011_modem_status(struct uart_amba_port *uap) { unsigned int status, delta; - status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; + status = pl011_read(uap->port.membase, UART01x_FR); + status &= UART01x_FR_MODEM_ANY; delta = status ^ uap->old_status; uap->old_status = status; @@ -1341,15 +1352,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap) return; /* workaround to make sure that all bits are unlocked.. */ - writew(0x00, uap->port.membase + UART011_ICR); + pl011_write(0x00, uap->port.membase, UART011_ICR); /* * WA: introduce 26ns(1 uart clk) delay before W1C; * single apb access will incur 2 pclk(133.12Mhz) delay, * so add 2 dummy reads */ - dummy_read = readw(uap->port.membase + UART011_ICR); - dummy_read = readw(uap->port.membase + UART011_ICR); + dummy_read = pl011_read(uap->port.membase, UART011_ICR); + dummy_read = pl011_read(uap->port.membase, UART011_ICR); } static irqreturn_t pl011_int(int irq, void *dev_id) @@ -1361,15 +1372,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id) int handled = 0; spin_lock_irqsave(&uap->port.lock, flags); - imsc = readw(uap->port.membase + UART011_IMSC); - status = readw(uap->port.membase + UART011_RIS) & imsc; + imsc = pl011_read(uap->port.membase, UART011_IMSC); + status = pl011_read(uap->port.membase, UART011_RIS) & imsc; if (status) { do { check_apply_cts_event_workaround(uap); - writew(status & ~(UART011_TXIS|UART011_RTIS| - UART011_RXIS), - uap->port.membase + UART011_ICR); + pl011_write(status & ~(UART011_TXIS|UART011_RTIS| + UART011_RXIS), + uap->port.membase, UART011_ICR); if (status & (UART011_RTIS|UART011_RXIS)) { if (pl011_dma_rx_running(uap)) @@ -1386,7 +1397,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) if (pass_counter-- == 0) break; - status = readw(uap->port.membase + UART011_RIS) & imsc; + status = pl011_read(uap->port.membase, UART011_RIS) & imsc; } while (status != 0); handled = 1; } @@ -1400,7 +1411,7 @@ static unsigned int pl011_tx_empty(struct uart_port *port) { struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - unsigned int status = readw(uap->port.membase + UART01x_FR); + unsigned int status = pl011_read(uap->port.membase, UART01x_FR); return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT; } @@ -1409,7 +1420,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); unsigned int result = 0; - unsigned int status = readw(uap->port.membase + UART01x_FR); + unsigned int status = pl011_read(uap->port.membase, UART01x_FR); #define TIOCMBIT(uartbit, tiocmbit) \ if (status & uartbit) \ @@ -1429,7 +1440,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) container_of(port, struct uart_amba_port, port); unsigned int cr; - cr = readw(uap->port.membase + UART011_CR); + cr = pl011_read(uap->port.membase, UART011_CR); #define TIOCMBIT(tiocmbit, uartbit) \ if (mctrl & tiocmbit) \ @@ -1449,7 +1460,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) } #undef TIOCMBIT - writew(cr, uap->port.membase + UART011_CR); + pl011_write(cr, uap->port.membase, UART011_CR); } static void pl011_break_ctl(struct uart_port *port, int break_state) @@ -1460,12 +1471,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) unsigned int lcr_h; spin_lock_irqsave(&uap->port.lock, flags); - lcr_h = readw(uap->port.membase + uap->lcrh_tx); + lcr_h = pl011_read(uap->port.membase, uap->lcrh_tx); if (break_state == -1) lcr_h |= UART01x_LCRH_BRK; else lcr_h &= ~UART01x_LCRH_BRK; - writew(lcr_h, uap->port.membase + uap->lcrh_tx); + pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx); spin_unlock_irqrestore(&uap->port.lock, flags); } @@ -1477,7 +1488,7 @@ static void pl011_quiesce_irqs(struct uart_port *port) container_of(port, struct uart_amba_port, port); unsigned char __iomem *regs = uap->port.membase; - writew(readw(regs + UART011_MIS), regs + UART011_ICR); + pl011_write(pl011_read(regs, UART011_MIS), regs, UART011_ICR); /* * There is no way to clear TXIM as this is "ready to transmit IRQ", so * we simply mask it. start_tx() will unmask it. @@ -1491,7 +1502,8 @@ static void pl011_quiesce_irqs(struct uart_port *port) * (including tx queue), so we're also fine with start_tx()'s caller * side. */ - writew(readw(regs + UART011_IMSC) & ~UART011_TXIM, regs + UART011_IMSC); + pl011_write(pl011_read(regs, UART011_IMSC) & ~UART011_TXIM, + regs, UART011_IMSC); } static int pl011_get_poll_char(struct uart_port *port) @@ -1506,11 +1518,11 @@ static int pl011_get_poll_char(struct uart_port *port) */ pl011_quiesce_irqs(port); - status = readw(uap->port.membase + UART01x_FR); + status = pl011_read(uap->port.membase, UART01x_FR); if (status & UART01x_FR_RXFE) return NO_POLL_CHAR; - return readw(uap->port.membase + UART01x_DR); + return pl011_read(uap->port.membase, UART01x_DR); } static void pl011_put_poll_char(struct uart_port *port, @@ -1519,10 +1531,10 @@ static void pl011_put_poll_char(struct uart_port *port, struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) + while (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF) barrier(); - writew(ch, uap->port.membase + UART01x_DR); + pl011_write(ch, uap->port.membase, UART01x_DR); } #endif /* CONFIG_CONSOLE_POLL */ @@ -1546,15 +1558,17 @@ static int pl011_hwinit(struct uart_port *port) uap->port.uartclk = clk_get_rate(uap->clk); /* Clear pending error and receive interrupts */ - writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | - UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); + pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS | + UART011_FEIS | UART011_RTIS | UART011_RXIS, + uap->port.membase, UART011_ICR); /* * Save interrupts enable mask, and enable RX interrupts in case if * the interrupt is used for NMI entry. */ - uap->im = readw(uap->port.membase + UART011_IMSC); - writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); + uap->im = pl011_read(uap->port.membase, UART011_IMSC); + pl011_write(UART011_RTIM | UART011_RXIM, uap->port.membase, + UART011_IMSC); if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; @@ -1568,7 +1582,7 @@ static int pl011_hwinit(struct uart_port *port) static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) { - writew(lcr_h, uap->port.membase + uap->lcrh_rx); + pl011_write(lcr_h, uap->port.membase, uap->lcrh_rx); if (uap->lcrh_rx != uap->lcrh_tx) { int i; /* @@ -1576,14 +1590,14 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) * to get this delay write read only register 10 times */ for (i = 0; i < 10; ++i) - writew(0xff, uap->port.membase + UART011_MIS); - writew(lcr_h, uap->port.membase + uap->lcrh_tx); + pl011_write(0xff, uap->port.membase, UART011_MIS); + pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx); } } static int pl011_allocate_irq(struct uart_amba_port *uap) { - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap); } @@ -1598,12 +1612,12 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap) spin_lock_irq(&uap->port.lock); /* Clear out any spuriously appearing RX interrupts */ - writew(UART011_RTIS | UART011_RXIS, - uap->port.membase + UART011_ICR); + pl011_write(UART011_RTIS | UART011_RXIS, uap->port.membase, + UART011_ICR); uap->im = UART011_RTIM; if (!pl011_dma_rx_running(uap)) uap->im |= UART011_RXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); spin_unlock_irq(&uap->port.lock); } @@ -1622,21 +1636,21 @@ static int pl011_startup(struct uart_port *port) if (retval) goto clk_dis; - writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); + pl011_write(uap->vendor->ifls, uap->port.membase, UART011_IFLS); spin_lock_irq(&uap->port.lock); /* restore RTS and DTR */ cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; - writew(cr, uap->port.membase + UART011_CR); + pl011_write(cr, uap->port.membase, UART011_CR); spin_unlock_irq(&uap->port.lock); /* * initialise the old status of the modem signals */ - uap->old_status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; + uap->old_status = pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_MODEM_ANY; /* Startup DMA */ pl011_dma_startup(uap); @@ -1677,9 +1691,9 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap, { unsigned long val; - val = readw(uap->port.membase + lcrh); + val = pl011_read(uap->port.membase, lcrh); val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); - writew(val, uap->port.membase + lcrh); + pl011_write(val, uap->port.membase, lcrh); } /* @@ -1693,11 +1707,11 @@ static void pl011_disable_uart(struct uart_amba_port *uap) uap->autorts = false; spin_lock_irq(&uap->port.lock); - cr = readw(uap->port.membase + UART011_CR); + cr = pl011_read(uap->port.membase, UART011_CR); uap->old_cr = cr; cr &= UART011_CR_RTS | UART011_CR_DTR; cr |= UART01x_CR_UARTEN | UART011_CR_TXE; - writew(cr, uap->port.membase + UART011_CR); + pl011_write(cr, uap->port.membase, UART011_CR); spin_unlock_irq(&uap->port.lock); /* @@ -1714,8 +1728,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap) /* mask all interrupts and clear all pending ones */ uap->im = 0; - writew(uap->im, uap->port.membase + UART011_IMSC); - writew(0xffff, uap->port.membase + UART011_ICR); + pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(0xffff, uap->port.membase, UART011_ICR); spin_unlock_irq(&uap->port.lock); } @@ -1867,8 +1881,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, pl011_enable_ms(port); /* first, disable everything */ - old_cr = readw(port->membase + UART011_CR); - writew(0, port->membase + UART011_CR); + old_cr = pl011_read(port->membase, UART011_CR); + pl011_write(0, port->membase, UART011_CR); if (termios->c_cflag & CRTSCTS) { if (old_cr & UART011_CR_RTS) @@ -1901,8 +1915,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, quot -= 2; } /* Set baud rate */ - writew(quot & 0x3f, port->membase + UART011_FBRD); - writew(quot >> 6, port->membase + UART011_IBRD); + pl011_write(quot & 0x3f, port->membase, UART011_FBRD); + pl011_write(quot >> 6, port->membase, UART011_IBRD); /* * ----------v----------v----------v----------v----- @@ -1911,7 +1925,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, * ----------^----------^----------^----------^----- */ pl011_write_lcr_h(uap, lcr_h); - writew(old_cr, port->membase + UART011_CR); + pl011_write(old_cr, port->membase, UART011_CR); spin_unlock_irqrestore(&port->lock, flags); } @@ -2052,9 +2066,9 @@ static void pl011_console_putchar(struct uart_port *port, int ch) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) + while (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF) barrier(); - writew(ch, uap->port.membase + UART01x_DR); + pl011_write(ch, uap->port.membase, UART01x_DR); } static void @@ -2079,10 +2093,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) * First save the CR then disable the interrupts */ if (!uap->vendor->always_enabled) { - old_cr = readw(uap->port.membase + UART011_CR); + old_cr = pl011_read(uap->port.membase, UART011_CR); new_cr = old_cr & ~UART011_CR_CTSEN; new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; - writew(new_cr, uap->port.membase + UART011_CR); + pl011_write(new_cr, uap->port.membase, UART011_CR); } uart_console_write(&uap->port, s, count, pl011_console_putchar); @@ -2092,10 +2106,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) * and restore the TCR */ do { - status = readw(uap->port.membase + UART01x_FR); + status = pl011_read(uap->port.membase, UART01x_FR); } while (status & UART01x_FR_BUSY); if (!uap->vendor->always_enabled) - writew(old_cr, uap->port.membase + UART011_CR); + pl011_write(old_cr, uap->port.membase, UART011_CR); if (locked) spin_unlock(&uap->port.lock); @@ -2108,10 +2122,10 @@ static void __init pl011_console_get_options(struct uart_amba_port *uap, int *baud, int *parity, int *bits) { - if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) { + if (pl011_read(uap->port.membase, UART011_CR) & UART01x_CR_UARTEN) { unsigned int lcr_h, ibrd, fbrd; - lcr_h = readw(uap->port.membase + uap->lcrh_tx); + lcr_h = pl011_read(uap->port.membase, uap->lcrh_tx); *parity = 'n'; if (lcr_h & UART01x_LCRH_PEN) { @@ -2126,13 +2140,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud, else *bits = 8; - ibrd = readw(uap->port.membase + UART011_IBRD); - fbrd = readw(uap->port.membase + UART011_FBRD); + ibrd = pl011_read(uap->port.membase, UART011_IBRD); + fbrd = pl011_read(uap->port.membase, UART011_FBRD); *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); if (uap->vendor->oversampling) { - if (readw(uap->port.membase + UART011_CR) + if (pl011_read(uap->port.membase, UART011_CR) & ST_UART011_CR_OVSFACT) *baud *= 2; } @@ -2334,8 +2348,8 @@ static int pl011_register_port(struct uart_amba_port *uap) int ret; /* Ensure interrupts from this UART are masked and cleared */ - writew(0, uap->port.membase + UART011_IMSC); - writew(0xffff, uap->port.membase + UART011_ICR); + pl011_write(0, uap->port.membase, UART011_IMSC); + pl011_write(0xffff, uap->port.membase, UART011_ICR); if (!amba_reg.state) { ret = uart_register_driver(&amba_reg); -- cgit v0.10.2 From b2a4e24c2efd76a2c25478836fb35951e00d5b52 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 3 Nov 2015 14:51:03 +0000 Subject: tty: amba-pl011: convert accessor functions to take uart_amba_port Convert the new accessor functions to take the uart_amba_port instead of the port base address. Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index bd01e75..0e7f045 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -184,14 +184,16 @@ struct uart_amba_port { #endif }; -static unsigned int pl011_read(void __iomem *base, unsigned int reg) +static unsigned int pl011_read(const struct uart_amba_port *uap, + unsigned int reg) { - return readw(base + reg); + return readw(uap->port.membase + reg); } -static void pl011_write(unsigned int val, void __iomem *base, unsigned int reg) +static void pl011_write(unsigned int val, const struct uart_amba_port *uap, + unsigned int reg) { - writew(val, base + reg); + writew(val, uap->port.membase + reg); } /* @@ -206,13 +208,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) int fifotaken = 0; while (max_count--) { - status = pl011_read(uap->port.membase, UART01x_FR); + status = pl011_read(uap, UART01x_FR); if (status & UART01x_FR_RXFE) break; /* Take chars from the FIFO and update status */ - ch = pl011_read(uap->port.membase, UART01x_DR) | - UART_DUMMY_DR_RX; + ch = pl011_read(uap, UART01x_DR) | UART_DUMMY_DR_RX; flag = TTY_NORMAL; uap->port.icount.rx++; fifotaken++; @@ -448,7 +449,7 @@ static void pl011_dma_tx_callback(void *data) dmacr = uap->dmacr; uap->dmacr = dmacr & ~UART011_TXDMAE; - pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); /* * If TX DMA was disabled, it means that we've stopped the DMA for @@ -562,7 +563,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap) dma_dev->device_issue_pending(chan); uap->dmacr |= UART011_TXDMAE; - pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); uap->dmatx.queued = true; /* @@ -598,9 +599,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap) */ if (uap->dmatx.queued) { uap->dmacr |= UART011_TXDMAE; - pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); uap->im &= ~UART011_TXIM; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); return true; } @@ -610,7 +611,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap) */ if (pl011_dma_tx_refill(uap) > 0) { uap->im &= ~UART011_TXIM; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); return true; } return false; @@ -624,7 +625,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap) { if (uap->dmatx.queued) { uap->dmacr &= ~UART011_TXDMAE; - pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); } } @@ -650,14 +651,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) if (!uap->dmatx.queued) { if (pl011_dma_tx_refill(uap) > 0) { uap->im &= ~UART011_TXIM; - pl011_write(uap->im, uap->port.membase, - UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); } else ret = false; } else if (!(uap->dmacr & UART011_TXDMAE)) { uap->dmacr |= UART011_TXDMAE; - pl011_write(uap->dmacr, uap->port.membase, - UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); } return ret; } @@ -668,9 +667,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) */ dmacr = uap->dmacr; uap->dmacr &= ~UART011_TXDMAE; - pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); - if (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF) { + if (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF) { /* * No space in the FIFO, so enable the transmit interrupt * so we know when there is space. Note that once we've @@ -679,13 +678,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) return false; } - pl011_write(uap->port.x_char, uap->port.membase, UART01x_DR); + pl011_write(uap->port.x_char, uap, UART01x_DR); uap->port.icount.tx++; uap->port.x_char = 0; /* Success - restore the DMA state */ uap->dmacr = dmacr; - pl011_write(dmacr, uap->port.membase, UART011_DMACR); + pl011_write(dmacr, uap, UART011_DMACR); return true; } @@ -713,7 +712,7 @@ __acquires(&uap->port.lock) DMA_TO_DEVICE); uap->dmatx.queued = false; uap->dmacr &= ~UART011_TXDMAE; - pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); } } @@ -753,11 +752,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap) dma_async_issue_pending(rxchan); uap->dmacr |= UART011_RXDMAE; - pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); uap->dmarx.running = true; uap->im &= ~UART011_RXIM; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); return 0; } @@ -816,7 +815,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, if (dma_count == pending && readfifo) { /* Clear any error flags */ pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS | - UART011_FEIS, uap->port.membase, UART011_ICR); + UART011_FEIS, uap, UART011_ICR); /* * If we read all the DMA'd characters, and we had an @@ -864,7 +863,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) /* Disable RX DMA - incoming data will wait in the FIFO */ uap->dmacr &= ~UART011_RXDMAE; - pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); uap->dmarx.running = false; pending = sgbuf->sg.length - state.residue; @@ -884,7 +883,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) dev_dbg(uap->port.dev, "could not retrigger RX DMA job " "fall back to interrupt mode\n"); uap->im |= UART011_RXIM; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); } } @@ -932,7 +931,7 @@ static void pl011_dma_rx_callback(void *data) dev_dbg(uap->port.dev, "could not retrigger RX DMA job " "fall back to interrupt mode\n"); uap->im |= UART011_RXIM; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); } } @@ -945,7 +944,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap) { /* FIXME. Just disable the DMA enable */ uap->dmacr &= ~UART011_RXDMAE; - pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); } /* @@ -989,7 +988,7 @@ static void pl011_dma_rx_poll(unsigned long args) spin_lock_irqsave(&uap->port.lock, flags); pl011_dma_rx_stop(uap); uap->im |= UART011_RXIM; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); spin_unlock_irqrestore(&uap->port.lock, flags); uap->dmarx.running = false; @@ -1051,7 +1050,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap) skip_rx: /* Turn on DMA error (RX/TX will be enabled on demand) */ uap->dmacr |= UART011_DMAONERR; - pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); /* * ST Micro variants has some specific dma burst threshold @@ -1060,7 +1059,7 @@ skip_rx: */ if (uap->vendor->dma_threshold) pl011_write(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16, - uap->port.membase, ST_UART011_DMAWM); + uap, ST_UART011_DMAWM); if (uap->using_rx_dma) { if (pl011_dma_rx_trigger_dma(uap)) @@ -1085,12 +1084,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) return; /* Disable RX and TX DMA */ - while (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_BUSY) + while (pl011_read(uap, UART01x_FR) & UART01x_FR_BUSY) barrier(); spin_lock_irq(&uap->port.lock); uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE); - pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR); + pl011_write(uap->dmacr, uap, UART011_DMACR); spin_unlock_irq(&uap->port.lock); if (uap->using_tx_dma) { @@ -1191,7 +1190,7 @@ static void pl011_stop_tx(struct uart_port *port) container_of(port, struct uart_amba_port, port); uap->im &= ~UART011_TXIM; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); pl011_dma_tx_stop(uap); } @@ -1201,7 +1200,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq); static void pl011_start_tx_pio(struct uart_amba_port *uap) { uap->im |= UART011_TXIM; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); pl011_tx_chars(uap, false); } @@ -1221,7 +1220,7 @@ static void pl011_stop_rx(struct uart_port *port) uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM| UART011_PEIM|UART011_BEIM|UART011_OEIM); - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); pl011_dma_rx_stop(uap); } @@ -1232,7 +1231,7 @@ static void pl011_enable_ms(struct uart_port *port) container_of(port, struct uart_amba_port, port); uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); } static void pl011_rx_chars(struct uart_amba_port *uap) @@ -1252,7 +1251,7 @@ __acquires(&uap->port.lock) dev_dbg(uap->port.dev, "could not trigger RX DMA job " "fall back to interrupt mode again\n"); uap->im |= UART011_RXIM; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); } else { #ifdef CONFIG_DMA_ENGINE /* Start Rx DMA poll */ @@ -1273,10 +1272,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c, bool from_irq) { if (unlikely(!from_irq) && - pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF) + pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF) return false; /* unable to transmit character */ - pl011_write(c, uap->port.membase, UART01x_DR); + pl011_write(c, uap, UART01x_DR); uap->port.icount.tx++; return true; @@ -1323,8 +1322,7 @@ static void pl011_modem_status(struct uart_amba_port *uap) { unsigned int status, delta; - status = pl011_read(uap->port.membase, UART01x_FR); - status &= UART01x_FR_MODEM_ANY; + status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY; delta = status ^ uap->old_status; uap->old_status = status; @@ -1352,15 +1350,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap) return; /* workaround to make sure that all bits are unlocked.. */ - pl011_write(0x00, uap->port.membase, UART011_ICR); + pl011_write(0x00, uap, UART011_ICR); /* * WA: introduce 26ns(1 uart clk) delay before W1C; * single apb access will incur 2 pclk(133.12Mhz) delay, * so add 2 dummy reads */ - dummy_read = pl011_read(uap->port.membase, UART011_ICR); - dummy_read = pl011_read(uap->port.membase, UART011_ICR); + dummy_read = pl011_read(uap, UART011_ICR); + dummy_read = pl011_read(uap, UART011_ICR); } static irqreturn_t pl011_int(int irq, void *dev_id) @@ -1372,15 +1370,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id) int handled = 0; spin_lock_irqsave(&uap->port.lock, flags); - imsc = pl011_read(uap->port.membase, UART011_IMSC); - status = pl011_read(uap->port.membase, UART011_RIS) & imsc; + imsc = pl011_read(uap, UART011_IMSC); + status = pl011_read(uap, UART011_RIS) & imsc; if (status) { do { check_apply_cts_event_workaround(uap); pl011_write(status & ~(UART011_TXIS|UART011_RTIS| UART011_RXIS), - uap->port.membase, UART011_ICR); + uap, UART011_ICR); if (status & (UART011_RTIS|UART011_RXIS)) { if (pl011_dma_rx_running(uap)) @@ -1397,7 +1395,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) if (pass_counter-- == 0) break; - status = pl011_read(uap->port.membase, UART011_RIS) & imsc; + status = pl011_read(uap, UART011_RIS) & imsc; } while (status != 0); handled = 1; } @@ -1411,7 +1409,7 @@ static unsigned int pl011_tx_empty(struct uart_port *port) { struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - unsigned int status = pl011_read(uap->port.membase, UART01x_FR); + unsigned int status = pl011_read(uap, UART01x_FR); return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT; } @@ -1420,7 +1418,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); unsigned int result = 0; - unsigned int status = pl011_read(uap->port.membase, UART01x_FR); + unsigned int status = pl011_read(uap, UART01x_FR); #define TIOCMBIT(uartbit, tiocmbit) \ if (status & uartbit) \ @@ -1440,7 +1438,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) container_of(port, struct uart_amba_port, port); unsigned int cr; - cr = pl011_read(uap->port.membase, UART011_CR); + cr = pl011_read(uap, UART011_CR); #define TIOCMBIT(tiocmbit, uartbit) \ if (mctrl & tiocmbit) \ @@ -1460,7 +1458,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) } #undef TIOCMBIT - pl011_write(cr, uap->port.membase, UART011_CR); + pl011_write(cr, uap, UART011_CR); } static void pl011_break_ctl(struct uart_port *port, int break_state) @@ -1471,12 +1469,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) unsigned int lcr_h; spin_lock_irqsave(&uap->port.lock, flags); - lcr_h = pl011_read(uap->port.membase, uap->lcrh_tx); + lcr_h = pl011_read(uap, uap->lcrh_tx); if (break_state == -1) lcr_h |= UART01x_LCRH_BRK; else lcr_h &= ~UART01x_LCRH_BRK; - pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx); + pl011_write(lcr_h, uap, uap->lcrh_tx); spin_unlock_irqrestore(&uap->port.lock, flags); } @@ -1486,9 +1484,8 @@ static void pl011_quiesce_irqs(struct uart_port *port) { struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - unsigned char __iomem *regs = uap->port.membase; - pl011_write(pl011_read(regs, UART011_MIS), regs, UART011_ICR); + pl011_write(pl011_read(uap, UART011_MIS), uap, UART011_ICR); /* * There is no way to clear TXIM as this is "ready to transmit IRQ", so * we simply mask it. start_tx() will unmask it. @@ -1502,8 +1499,8 @@ static void pl011_quiesce_irqs(struct uart_port *port) * (including tx queue), so we're also fine with start_tx()'s caller * side. */ - pl011_write(pl011_read(regs, UART011_IMSC) & ~UART011_TXIM, - regs, UART011_IMSC); + pl011_write(pl011_read(uap, UART011_IMSC) & ~UART011_TXIM, uap, + UART011_IMSC); } static int pl011_get_poll_char(struct uart_port *port) @@ -1518,11 +1515,11 @@ static int pl011_get_poll_char(struct uart_port *port) */ pl011_quiesce_irqs(port); - status = pl011_read(uap->port.membase, UART01x_FR); + status = pl011_read(uap, UART01x_FR); if (status & UART01x_FR_RXFE) return NO_POLL_CHAR; - return pl011_read(uap->port.membase, UART01x_DR); + return pl011_read(uap, UART01x_DR); } static void pl011_put_poll_char(struct uart_port *port, @@ -1531,10 +1528,10 @@ static void pl011_put_poll_char(struct uart_port *port, struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - while (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF) + while (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF) barrier(); - pl011_write(ch, uap->port.membase, UART01x_DR); + pl011_write(ch, uap, UART01x_DR); } #endif /* CONFIG_CONSOLE_POLL */ @@ -1560,15 +1557,14 @@ static int pl011_hwinit(struct uart_port *port) /* Clear pending error and receive interrupts */ pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | UART011_RTIS | UART011_RXIS, - uap->port.membase, UART011_ICR); + uap, UART011_ICR); /* * Save interrupts enable mask, and enable RX interrupts in case if * the interrupt is used for NMI entry. */ - uap->im = pl011_read(uap->port.membase, UART011_IMSC); - pl011_write(UART011_RTIM | UART011_RXIM, uap->port.membase, - UART011_IMSC); + uap->im = pl011_read(uap, UART011_IMSC); + pl011_write(UART011_RTIM | UART011_RXIM, uap, UART011_IMSC); if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; @@ -1582,7 +1578,7 @@ static int pl011_hwinit(struct uart_port *port) static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) { - pl011_write(lcr_h, uap->port.membase, uap->lcrh_rx); + pl011_write(lcr_h, uap, uap->lcrh_rx); if (uap->lcrh_rx != uap->lcrh_tx) { int i; /* @@ -1590,14 +1586,14 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) * to get this delay write read only register 10 times */ for (i = 0; i < 10; ++i) - pl011_write(0xff, uap->port.membase, UART011_MIS); - pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx); + pl011_write(0xff, uap, UART011_MIS); + pl011_write(lcr_h, uap, uap->lcrh_tx); } } static int pl011_allocate_irq(struct uart_amba_port *uap) { - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap); } @@ -1612,12 +1608,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap) spin_lock_irq(&uap->port.lock); /* Clear out any spuriously appearing RX interrupts */ - pl011_write(UART011_RTIS | UART011_RXIS, uap->port.membase, - UART011_ICR); + pl011_write(UART011_RTIS | UART011_RXIS, uap, UART011_ICR); uap->im = UART011_RTIM; if (!pl011_dma_rx_running(uap)) uap->im |= UART011_RXIM; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); + pl011_write(uap->im, uap, UART011_IMSC); spin_unlock_irq(&uap->port.lock); } @@ -1636,21 +1631,21 @@ static int pl011_startup(struct uart_port *port) if (retval) goto clk_dis; - pl011_write(uap->vendor->ifls, uap->port.membase, UART011_IFLS); + pl011_write(uap->vendor->ifls, uap, UART011_IFLS); spin_lock_irq(&uap->port.lock); /* restore RTS and DTR */ cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; - pl011_write(cr, uap->port.membase, UART011_CR); + pl011_write(cr, uap, UART011_CR); spin_unlock_irq(&uap->port.lock); /* * initialise the old status of the modem signals */ - uap->old_status = pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_MODEM_ANY; + uap->old_status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY; /* Startup DMA */ pl011_dma_startup(uap); @@ -1691,9 +1686,9 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap, { unsigned long val; - val = pl011_read(uap->port.membase, lcrh); + val = pl011_read(uap, lcrh); val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); - pl011_write(val, uap->port.membase, lcrh); + pl011_write(val, uap, lcrh); } /* @@ -1707,11 +1702,11 @@ static void pl011_disable_uart(struct uart_amba_port *uap) uap->autorts = false; spin_lock_irq(&uap->port.lock); - cr = pl011_read(uap->port.membase, UART011_CR); + cr = pl011_read(uap, UART011_CR); uap->old_cr = cr; cr &= UART011_CR_RTS | UART011_CR_DTR; cr |= UART01x_CR_UARTEN | UART011_CR_TXE; - pl011_write(cr, uap->port.membase, UART011_CR); + pl011_write(cr, uap, UART011_CR); spin_unlock_irq(&uap->port.lock); /* @@ -1728,8 +1723,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap) /* mask all interrupts and clear all pending ones */ uap->im = 0; - pl011_write(uap->im, uap->port.membase, UART011_IMSC); - pl011_write(0xffff, uap->port.membase, UART011_ICR); + pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(0xffff, uap, UART011_ICR); spin_unlock_irq(&uap->port.lock); } @@ -1881,8 +1876,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, pl011_enable_ms(port); /* first, disable everything */ - old_cr = pl011_read(port->membase, UART011_CR); - pl011_write(0, port->membase, UART011_CR); + old_cr = pl011_read(uap, UART011_CR); + pl011_write(0, uap, UART011_CR); if (termios->c_cflag & CRTSCTS) { if (old_cr & UART011_CR_RTS) @@ -1915,8 +1910,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, quot -= 2; } /* Set baud rate */ - pl011_write(quot & 0x3f, port->membase, UART011_FBRD); - pl011_write(quot >> 6, port->membase, UART011_IBRD); + pl011_write(quot & 0x3f, uap, UART011_FBRD); + pl011_write(quot >> 6, uap, UART011_IBRD); /* * ----------v----------v----------v----------v----- @@ -1925,7 +1920,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, * ----------^----------^----------^----------^----- */ pl011_write_lcr_h(uap, lcr_h); - pl011_write(old_cr, port->membase, UART011_CR); + pl011_write(old_cr, uap, UART011_CR); spin_unlock_irqrestore(&port->lock, flags); } @@ -2066,9 +2061,9 @@ static void pl011_console_putchar(struct uart_port *port, int ch) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - while (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF) + while (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF) barrier(); - pl011_write(ch, uap->port.membase, UART01x_DR); + pl011_write(ch, uap, UART01x_DR); } static void @@ -2093,10 +2088,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) * First save the CR then disable the interrupts */ if (!uap->vendor->always_enabled) { - old_cr = pl011_read(uap->port.membase, UART011_CR); + old_cr = pl011_read(uap, UART011_CR); new_cr = old_cr & ~UART011_CR_CTSEN; new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; - pl011_write(new_cr, uap->port.membase, UART011_CR); + pl011_write(new_cr, uap, UART011_CR); } uart_console_write(&uap->port, s, count, pl011_console_putchar); @@ -2106,10 +2101,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) * and restore the TCR */ do { - status = pl011_read(uap->port.membase, UART01x_FR); + status = pl011_read(uap, UART01x_FR); } while (status & UART01x_FR_BUSY); if (!uap->vendor->always_enabled) - pl011_write(old_cr, uap->port.membase, UART011_CR); + pl011_write(old_cr, uap, UART011_CR); if (locked) spin_unlock(&uap->port.lock); @@ -2122,10 +2117,10 @@ static void __init pl011_console_get_options(struct uart_amba_port *uap, int *baud, int *parity, int *bits) { - if (pl011_read(uap->port.membase, UART011_CR) & UART01x_CR_UARTEN) { + if (pl011_read(uap, UART011_CR) & UART01x_CR_UARTEN) { unsigned int lcr_h, ibrd, fbrd; - lcr_h = pl011_read(uap->port.membase, uap->lcrh_tx); + lcr_h = pl011_read(uap, uap->lcrh_tx); *parity = 'n'; if (lcr_h & UART01x_LCRH_PEN) { @@ -2140,13 +2135,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud, else *bits = 8; - ibrd = pl011_read(uap->port.membase, UART011_IBRD); - fbrd = pl011_read(uap->port.membase, UART011_FBRD); + ibrd = pl011_read(uap, UART011_IBRD); + fbrd = pl011_read(uap, UART011_FBRD); *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); if (uap->vendor->oversampling) { - if (pl011_read(uap->port.membase, UART011_CR) + if (pl011_read(uap, UART011_CR) & ST_UART011_CR_OVSFACT) *baud *= 2; } @@ -2348,8 +2343,8 @@ static int pl011_register_port(struct uart_amba_port *uap) int ret; /* Ensure interrupts from this UART are masked and cleared */ - pl011_write(0, uap->port.membase, UART011_IMSC); - pl011_write(0xffff, uap->port.membase, UART011_ICR); + pl011_write(0, uap, UART011_IMSC); + pl011_write(0xffff, uap, UART011_ICR); if (!amba_reg.state) { ret = uart_register_driver(&amba_reg); -- cgit v0.10.2 From 7fe9a5a9d91f0e9ac65c723665bbdf899c3a4a24 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 3 Nov 2015 14:51:08 +0000 Subject: tty: amba-pl011: add helper to detect split LCRH register Add a helper to detect the split LCRH register found on ST variants. Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 0e7f045..c9ae0a1 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1576,10 +1576,15 @@ static int pl011_hwinit(struct uart_port *port) return 0; } +static bool pl011_split_lcrh(const struct uart_amba_port *uap) +{ + return uap->lcrh_rx != uap->lcrh_tx; +} + static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) { pl011_write(lcr_h, uap, uap->lcrh_rx); - if (uap->lcrh_rx != uap->lcrh_tx) { + if (pl011_split_lcrh(uap)) { int i; /* * Wait 10 PCLKs before writing LCRH_TX register, @@ -1713,7 +1718,7 @@ static void pl011_disable_uart(struct uart_amba_port *uap) * disable break condition and fifos */ pl011_shutdown_channel(uap, uap->lcrh_rx); - if (uap->lcrh_rx != uap->lcrh_tx) + if (pl011_split_lcrh(uap)) pl011_shutdown_channel(uap, uap->lcrh_tx); } -- cgit v0.10.2 From 9f25bc510e960c551dc295c2d1d60e3da334590c Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 3 Nov 2015 14:51:13 +0000 Subject: tty: amba-pl011: prepare REG_* register indexes Prepare for REG_* register accessors. This change involves introducing pl011_reg_to_offset() to convert REG_* to the hardware register offset, and converting all call sites to use REG_* names. We need to fix up locations where we check for equivalence of register offsets as well. Much of this change was made via these sed expressions: s/ST_UART01[1x]\(_[^_]*\|_LCRH_[TR]X\)\>/REG_ST\1/ s/UART01[1x]_\(DR\|RSR\|ECR\|FR\|ILPR\|[IF]BRD\|LCRH\|CR\|IFLS\|IMSC\|RIS\|MIS\|ICR\|DMACR\)\>/REG_\1/g Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c9ae0a1..62b9cb2 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -60,6 +60,8 @@ #include #include +#include "amba-pl011.h" + #define UART_NR 14 #define SERIAL_AMBA_MAJOR 204 @@ -92,8 +94,8 @@ static unsigned int get_fifosize_arm(struct amba_device *dev) static struct vendor_data vendor_arm = { .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, - .lcrh_tx = UART011_LCRH, - .lcrh_rx = UART011_LCRH, + .lcrh_tx = REG_LCRH, + .lcrh_rx = REG_LCRH, .oversampling = false, .dma_threshold = false, .cts_event_workaround = false, @@ -117,8 +119,8 @@ static unsigned int get_fifosize_st(struct amba_device *dev) static struct vendor_data vendor_st = { .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, - .lcrh_tx = ST_UART011_LCRH_TX, - .lcrh_rx = ST_UART011_LCRH_RX, + .lcrh_tx = REG_ST_LCRH_TX, + .lcrh_rx = REG_ST_LCRH_RX, .oversampling = true, .dma_threshold = true, .cts_event_workaround = true, @@ -184,16 +186,22 @@ struct uart_amba_port { #endif }; +static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap, + unsigned int reg) +{ + return reg; +} + static unsigned int pl011_read(const struct uart_amba_port *uap, unsigned int reg) { - return readw(uap->port.membase + reg); + return readw(uap->port.membase + pl011_reg_to_offset(uap, reg)); } static void pl011_write(unsigned int val, const struct uart_amba_port *uap, unsigned int reg) { - writew(val, uap->port.membase + reg); + writew(val, uap->port.membase + pl011_reg_to_offset(uap, reg)); } /* @@ -208,12 +216,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) int fifotaken = 0; while (max_count--) { - status = pl011_read(uap, UART01x_FR); + status = pl011_read(uap, REG_FR); if (status & UART01x_FR_RXFE) break; /* Take chars from the FIFO and update status */ - ch = pl011_read(uap, UART01x_DR) | UART_DUMMY_DR_RX; + ch = pl011_read(uap, REG_DR) | UART_DUMMY_DR_RX; flag = TTY_NORMAL; uap->port.icount.rx++; fifotaken++; @@ -295,7 +303,8 @@ static void pl011_dma_probe(struct uart_amba_port *uap) struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev); struct device *dev = uap->port.dev; struct dma_slave_config tx_conf = { - .dst_addr = uap->port.mapbase + UART01x_DR, + .dst_addr = uap->port.mapbase + + pl011_reg_to_offset(uap, REG_DR), .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .direction = DMA_MEM_TO_DEV, .dst_maxburst = uap->fifosize >> 1, @@ -350,7 +359,8 @@ static void pl011_dma_probe(struct uart_amba_port *uap) if (chan) { struct dma_slave_config rx_conf = { - .src_addr = uap->port.mapbase + UART01x_DR, + .src_addr = uap->port.mapbase + + pl011_reg_to_offset(uap, REG_DR), .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .direction = DMA_DEV_TO_MEM, .src_maxburst = uap->fifosize >> 2, @@ -449,7 +459,7 @@ static void pl011_dma_tx_callback(void *data) dmacr = uap->dmacr; uap->dmacr = dmacr & ~UART011_TXDMAE; - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); /* * If TX DMA was disabled, it means that we've stopped the DMA for @@ -563,7 +573,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap) dma_dev->device_issue_pending(chan); uap->dmacr |= UART011_TXDMAE; - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); uap->dmatx.queued = true; /* @@ -599,9 +609,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap) */ if (uap->dmatx.queued) { uap->dmacr |= UART011_TXDMAE; - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); uap->im &= ~UART011_TXIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); return true; } @@ -611,7 +621,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap) */ if (pl011_dma_tx_refill(uap) > 0) { uap->im &= ~UART011_TXIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); return true; } return false; @@ -625,7 +635,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap) { if (uap->dmatx.queued) { uap->dmacr &= ~UART011_TXDMAE; - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); } } @@ -651,12 +661,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) if (!uap->dmatx.queued) { if (pl011_dma_tx_refill(uap) > 0) { uap->im &= ~UART011_TXIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); } else ret = false; } else if (!(uap->dmacr & UART011_TXDMAE)) { uap->dmacr |= UART011_TXDMAE; - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); } return ret; } @@ -667,9 +677,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) */ dmacr = uap->dmacr; uap->dmacr &= ~UART011_TXDMAE; - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); - if (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF) { + if (pl011_read(uap, REG_FR) & UART01x_FR_TXFF) { /* * No space in the FIFO, so enable the transmit interrupt * so we know when there is space. Note that once we've @@ -678,13 +688,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) return false; } - pl011_write(uap->port.x_char, uap, UART01x_DR); + pl011_write(uap->port.x_char, uap, REG_DR); uap->port.icount.tx++; uap->port.x_char = 0; /* Success - restore the DMA state */ uap->dmacr = dmacr; - pl011_write(dmacr, uap, UART011_DMACR); + pl011_write(dmacr, uap, REG_DMACR); return true; } @@ -712,7 +722,7 @@ __acquires(&uap->port.lock) DMA_TO_DEVICE); uap->dmatx.queued = false; uap->dmacr &= ~UART011_TXDMAE; - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); } } @@ -752,11 +762,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap) dma_async_issue_pending(rxchan); uap->dmacr |= UART011_RXDMAE; - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); uap->dmarx.running = true; uap->im &= ~UART011_RXIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); return 0; } @@ -815,7 +825,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, if (dma_count == pending && readfifo) { /* Clear any error flags */ pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS | - UART011_FEIS, uap, UART011_ICR); + UART011_FEIS, uap, REG_ICR); /* * If we read all the DMA'd characters, and we had an @@ -863,7 +873,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) /* Disable RX DMA - incoming data will wait in the FIFO */ uap->dmacr &= ~UART011_RXDMAE; - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); uap->dmarx.running = false; pending = sgbuf->sg.length - state.residue; @@ -883,7 +893,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) dev_dbg(uap->port.dev, "could not retrigger RX DMA job " "fall back to interrupt mode\n"); uap->im |= UART011_RXIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); } } @@ -931,7 +941,7 @@ static void pl011_dma_rx_callback(void *data) dev_dbg(uap->port.dev, "could not retrigger RX DMA job " "fall back to interrupt mode\n"); uap->im |= UART011_RXIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); } } @@ -944,7 +954,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap) { /* FIXME. Just disable the DMA enable */ uap->dmacr &= ~UART011_RXDMAE; - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); } /* @@ -988,7 +998,7 @@ static void pl011_dma_rx_poll(unsigned long args) spin_lock_irqsave(&uap->port.lock, flags); pl011_dma_rx_stop(uap); uap->im |= UART011_RXIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); spin_unlock_irqrestore(&uap->port.lock, flags); uap->dmarx.running = false; @@ -1050,7 +1060,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap) skip_rx: /* Turn on DMA error (RX/TX will be enabled on demand) */ uap->dmacr |= UART011_DMAONERR; - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); /* * ST Micro variants has some specific dma burst threshold @@ -1059,7 +1069,7 @@ skip_rx: */ if (uap->vendor->dma_threshold) pl011_write(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16, - uap, ST_UART011_DMAWM); + uap, REG_ST_DMAWM); if (uap->using_rx_dma) { if (pl011_dma_rx_trigger_dma(uap)) @@ -1084,12 +1094,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) return; /* Disable RX and TX DMA */ - while (pl011_read(uap, UART01x_FR) & UART01x_FR_BUSY) + while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY) barrier(); spin_lock_irq(&uap->port.lock); uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE); - pl011_write(uap->dmacr, uap, UART011_DMACR); + pl011_write(uap->dmacr, uap, REG_DMACR); spin_unlock_irq(&uap->port.lock); if (uap->using_tx_dma) { @@ -1190,7 +1200,7 @@ static void pl011_stop_tx(struct uart_port *port) container_of(port, struct uart_amba_port, port); uap->im &= ~UART011_TXIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); pl011_dma_tx_stop(uap); } @@ -1200,7 +1210,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq); static void pl011_start_tx_pio(struct uart_amba_port *uap) { uap->im |= UART011_TXIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); pl011_tx_chars(uap, false); } @@ -1220,7 +1230,7 @@ static void pl011_stop_rx(struct uart_port *port) uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM| UART011_PEIM|UART011_BEIM|UART011_OEIM); - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); pl011_dma_rx_stop(uap); } @@ -1231,7 +1241,7 @@ static void pl011_enable_ms(struct uart_port *port) container_of(port, struct uart_amba_port, port); uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); } static void pl011_rx_chars(struct uart_amba_port *uap) @@ -1251,7 +1261,7 @@ __acquires(&uap->port.lock) dev_dbg(uap->port.dev, "could not trigger RX DMA job " "fall back to interrupt mode again\n"); uap->im |= UART011_RXIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); } else { #ifdef CONFIG_DMA_ENGINE /* Start Rx DMA poll */ @@ -1272,10 +1282,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c, bool from_irq) { if (unlikely(!from_irq) && - pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF) + pl011_read(uap, REG_FR) & UART01x_FR_TXFF) return false; /* unable to transmit character */ - pl011_write(c, uap, UART01x_DR); + pl011_write(c, uap, REG_DR); uap->port.icount.tx++; return true; @@ -1322,7 +1332,7 @@ static void pl011_modem_status(struct uart_amba_port *uap) { unsigned int status, delta; - status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY; + status = pl011_read(uap, REG_FR) & UART01x_FR_MODEM_ANY; delta = status ^ uap->old_status; uap->old_status = status; @@ -1350,15 +1360,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap) return; /* workaround to make sure that all bits are unlocked.. */ - pl011_write(0x00, uap, UART011_ICR); + pl011_write(0x00, uap, REG_ICR); /* * WA: introduce 26ns(1 uart clk) delay before W1C; * single apb access will incur 2 pclk(133.12Mhz) delay, * so add 2 dummy reads */ - dummy_read = pl011_read(uap, UART011_ICR); - dummy_read = pl011_read(uap, UART011_ICR); + dummy_read = pl011_read(uap, REG_ICR); + dummy_read = pl011_read(uap, REG_ICR); } static irqreturn_t pl011_int(int irq, void *dev_id) @@ -1370,15 +1380,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id) int handled = 0; spin_lock_irqsave(&uap->port.lock, flags); - imsc = pl011_read(uap, UART011_IMSC); - status = pl011_read(uap, UART011_RIS) & imsc; + imsc = pl011_read(uap, REG_IMSC); + status = pl011_read(uap, REG_RIS) & imsc; if (status) { do { check_apply_cts_event_workaround(uap); pl011_write(status & ~(UART011_TXIS|UART011_RTIS| UART011_RXIS), - uap, UART011_ICR); + uap, REG_ICR); if (status & (UART011_RTIS|UART011_RXIS)) { if (pl011_dma_rx_running(uap)) @@ -1395,7 +1405,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) if (pass_counter-- == 0) break; - status = pl011_read(uap, UART011_RIS) & imsc; + status = pl011_read(uap, REG_RIS) & imsc; } while (status != 0); handled = 1; } @@ -1409,7 +1419,7 @@ static unsigned int pl011_tx_empty(struct uart_port *port) { struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - unsigned int status = pl011_read(uap, UART01x_FR); + unsigned int status = pl011_read(uap, REG_FR); return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT; } @@ -1418,7 +1428,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); unsigned int result = 0; - unsigned int status = pl011_read(uap, UART01x_FR); + unsigned int status = pl011_read(uap, REG_FR); #define TIOCMBIT(uartbit, tiocmbit) \ if (status & uartbit) \ @@ -1438,7 +1448,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) container_of(port, struct uart_amba_port, port); unsigned int cr; - cr = pl011_read(uap, UART011_CR); + cr = pl011_read(uap, REG_CR); #define TIOCMBIT(tiocmbit, uartbit) \ if (mctrl & tiocmbit) \ @@ -1458,7 +1468,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) } #undef TIOCMBIT - pl011_write(cr, uap, UART011_CR); + pl011_write(cr, uap, REG_CR); } static void pl011_break_ctl(struct uart_port *port, int break_state) @@ -1485,7 +1495,7 @@ static void pl011_quiesce_irqs(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - pl011_write(pl011_read(uap, UART011_MIS), uap, UART011_ICR); + pl011_write(pl011_read(uap, REG_MIS), uap, REG_ICR); /* * There is no way to clear TXIM as this is "ready to transmit IRQ", so * we simply mask it. start_tx() will unmask it. @@ -1499,8 +1509,8 @@ static void pl011_quiesce_irqs(struct uart_port *port) * (including tx queue), so we're also fine with start_tx()'s caller * side. */ - pl011_write(pl011_read(uap, UART011_IMSC) & ~UART011_TXIM, uap, - UART011_IMSC); + pl011_write(pl011_read(uap, REG_IMSC) & ~UART011_TXIM, uap, + REG_IMSC); } static int pl011_get_poll_char(struct uart_port *port) @@ -1515,11 +1525,11 @@ static int pl011_get_poll_char(struct uart_port *port) */ pl011_quiesce_irqs(port); - status = pl011_read(uap, UART01x_FR); + status = pl011_read(uap, REG_FR); if (status & UART01x_FR_RXFE) return NO_POLL_CHAR; - return pl011_read(uap, UART01x_DR); + return pl011_read(uap, REG_DR); } static void pl011_put_poll_char(struct uart_port *port, @@ -1528,10 +1538,10 @@ static void pl011_put_poll_char(struct uart_port *port, struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - while (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF) + while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF) barrier(); - pl011_write(ch, uap, UART01x_DR); + pl011_write(ch, uap, REG_DR); } #endif /* CONFIG_CONSOLE_POLL */ @@ -1557,14 +1567,14 @@ static int pl011_hwinit(struct uart_port *port) /* Clear pending error and receive interrupts */ pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | UART011_RTIS | UART011_RXIS, - uap, UART011_ICR); + uap, REG_ICR); /* * Save interrupts enable mask, and enable RX interrupts in case if * the interrupt is used for NMI entry. */ - uap->im = pl011_read(uap, UART011_IMSC); - pl011_write(UART011_RTIM | UART011_RXIM, uap, UART011_IMSC); + uap->im = pl011_read(uap, REG_IMSC); + pl011_write(UART011_RTIM | UART011_RXIM, uap, REG_IMSC); if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; @@ -1578,7 +1588,8 @@ static int pl011_hwinit(struct uart_port *port) static bool pl011_split_lcrh(const struct uart_amba_port *uap) { - return uap->lcrh_rx != uap->lcrh_tx; + return pl011_reg_to_offset(uap, uap->lcrh_rx) != + pl011_reg_to_offset(uap, uap->lcrh_tx); } static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) @@ -1591,14 +1602,14 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) * to get this delay write read only register 10 times */ for (i = 0; i < 10; ++i) - pl011_write(0xff, uap, UART011_MIS); + pl011_write(0xff, uap, REG_MIS); pl011_write(lcr_h, uap, uap->lcrh_tx); } } static int pl011_allocate_irq(struct uart_amba_port *uap) { - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap); } @@ -1613,11 +1624,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap) spin_lock_irq(&uap->port.lock); /* Clear out any spuriously appearing RX interrupts */ - pl011_write(UART011_RTIS | UART011_RXIS, uap, UART011_ICR); + pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR); uap->im = UART011_RTIM; if (!pl011_dma_rx_running(uap)) uap->im |= UART011_RXIM; - pl011_write(uap->im, uap, UART011_IMSC); + pl011_write(uap->im, uap, REG_IMSC); spin_unlock_irq(&uap->port.lock); } @@ -1636,21 +1647,21 @@ static int pl011_startup(struct uart_port *port) if (retval) goto clk_dis; - pl011_write(uap->vendor->ifls, uap, UART011_IFLS); + pl011_write(uap->vendor->ifls, uap, REG_IFLS); spin_lock_irq(&uap->port.lock); /* restore RTS and DTR */ cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; - pl011_write(cr, uap, UART011_CR); + pl011_write(cr, uap, REG_CR); spin_unlock_irq(&uap->port.lock); /* * initialise the old status of the modem signals */ - uap->old_status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY; + uap->old_status = pl011_read(uap, REG_FR) & UART01x_FR_MODEM_ANY; /* Startup DMA */ pl011_dma_startup(uap); @@ -1707,11 +1718,11 @@ static void pl011_disable_uart(struct uart_amba_port *uap) uap->autorts = false; spin_lock_irq(&uap->port.lock); - cr = pl011_read(uap, UART011_CR); + cr = pl011_read(uap, REG_CR); uap->old_cr = cr; cr &= UART011_CR_RTS | UART011_CR_DTR; cr |= UART01x_CR_UARTEN | UART011_CR_TXE; - pl011_write(cr, uap, UART011_CR); + pl011_write(cr, uap, REG_CR); spin_unlock_irq(&uap->port.lock); /* @@ -1728,8 +1739,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap) /* mask all interrupts and clear all pending ones */ uap->im = 0; - pl011_write(uap->im, uap, UART011_IMSC); - pl011_write(0xffff, uap, UART011_ICR); + pl011_write(uap->im, uap, REG_IMSC); + pl011_write(0xffff, uap, REG_ICR); spin_unlock_irq(&uap->port.lock); } @@ -1881,8 +1892,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, pl011_enable_ms(port); /* first, disable everything */ - old_cr = pl011_read(uap, UART011_CR); - pl011_write(0, uap, UART011_CR); + old_cr = pl011_read(uap, REG_CR); + pl011_write(0, uap, REG_CR); if (termios->c_cflag & CRTSCTS) { if (old_cr & UART011_CR_RTS) @@ -1915,17 +1926,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, quot -= 2; } /* Set baud rate */ - pl011_write(quot & 0x3f, uap, UART011_FBRD); - pl011_write(quot >> 6, uap, UART011_IBRD); + pl011_write(quot & 0x3f, uap, REG_FBRD); + pl011_write(quot >> 6, uap, REG_IBRD); /* * ----------v----------v----------v----------v----- * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER - * UART011_FBRD & UART011_IBRD. + * REG_FBRD & REG_IBRD. * ----------^----------^----------^----------^----- */ pl011_write_lcr_h(uap, lcr_h); - pl011_write(old_cr, uap, UART011_CR); + pl011_write(old_cr, uap, REG_CR); spin_unlock_irqrestore(&port->lock, flags); } @@ -2066,9 +2077,9 @@ static void pl011_console_putchar(struct uart_port *port, int ch) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); - while (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF) + while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF) barrier(); - pl011_write(ch, uap, UART01x_DR); + pl011_write(ch, uap, REG_DR); } static void @@ -2093,10 +2104,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) * First save the CR then disable the interrupts */ if (!uap->vendor->always_enabled) { - old_cr = pl011_read(uap, UART011_CR); + old_cr = pl011_read(uap, REG_CR); new_cr = old_cr & ~UART011_CR_CTSEN; new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; - pl011_write(new_cr, uap, UART011_CR); + pl011_write(new_cr, uap, REG_CR); } uart_console_write(&uap->port, s, count, pl011_console_putchar); @@ -2106,10 +2117,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) * and restore the TCR */ do { - status = pl011_read(uap, UART01x_FR); + status = pl011_read(uap, REG_FR); } while (status & UART01x_FR_BUSY); if (!uap->vendor->always_enabled) - pl011_write(old_cr, uap, UART011_CR); + pl011_write(old_cr, uap, REG_CR); if (locked) spin_unlock(&uap->port.lock); @@ -2122,7 +2133,7 @@ static void __init pl011_console_get_options(struct uart_amba_port *uap, int *baud, int *parity, int *bits) { - if (pl011_read(uap, UART011_CR) & UART01x_CR_UARTEN) { + if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) { unsigned int lcr_h, ibrd, fbrd; lcr_h = pl011_read(uap, uap->lcrh_tx); @@ -2140,13 +2151,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud, else *bits = 8; - ibrd = pl011_read(uap, UART011_IBRD); - fbrd = pl011_read(uap, UART011_FBRD); + ibrd = pl011_read(uap, REG_IBRD); + fbrd = pl011_read(uap, REG_FBRD); *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); if (uap->vendor->oversampling) { - if (pl011_read(uap, UART011_CR) + if (pl011_read(uap, REG_CR) & ST_UART011_CR_OVSFACT) *baud *= 2; } @@ -2218,10 +2229,10 @@ static struct console amba_console = { static void pl011_putc(struct uart_port *port, int c) { - while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF) + while (readl(port->membase + REG_FR) & UART01x_FR_TXFF) ; - writeb(c, port->membase + UART01x_DR); - while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY) + writeb(c, port->membase + REG_DR); + while (readl(port->membase + REG_FR) & UART01x_FR_BUSY) ; } @@ -2348,8 +2359,8 @@ static int pl011_register_port(struct uart_amba_port *uap) int ret; /* Ensure interrupts from this UART are masked and cleared */ - pl011_write(0, uap, UART011_IMSC); - pl011_write(0xffff, uap, UART011_ICR); + pl011_write(0, uap, REG_IMSC); + pl011_write(0xffff, uap, REG_ICR); if (!amba_reg.state) { ret = uart_register_driver(&amba_reg); diff --git a/drivers/tty/serial/amba-pl011.h b/drivers/tty/serial/amba-pl011.h new file mode 100644 index 0000000..b7eb1bc --- /dev/null +++ b/drivers/tty/serial/amba-pl011.h @@ -0,0 +1,32 @@ +#ifndef AMBA_PL011_H +#define AMBA_PL011_H + +enum { + REG_DR = UART01x_DR, + REG_ST_DMAWM = ST_UART011_DMAWM, + REG_ST_TIMEOUT = ST_UART011_TIMEOUT, + REG_FR = UART01x_FR, + REG_ST_LCRH_RX = ST_UART011_LCRH_RX, + REG_IBRD = UART011_IBRD, + REG_FBRD = UART011_FBRD, + REG_LCRH = UART011_LCRH, + REG_ST_LCRH_TX = ST_UART011_LCRH_TX, + REG_CR = UART011_CR, + REG_IFLS = UART011_IFLS, + REG_IMSC = UART011_IMSC, + REG_RIS = UART011_RIS, + REG_MIS = UART011_MIS, + REG_ICR = UART011_ICR, + REG_DMACR = UART011_DMACR, + REG_ST_XFCR = ST_UART011_XFCR, + REG_ST_XON1 = ST_UART011_XON1, + REG_ST_XON2 = ST_UART011_XON2, + REG_ST_XOFF1 = ST_UART011_XOFF1, + REG_ST_XOFF2 = ST_UART011_XOFF2, + REG_ST_ITCR = ST_UART011_ITCR, + REG_ST_ITIP = ST_UART011_ITIP, + REG_ST_ABCR = ST_UART011_ABCR, + REG_ST_ABIMSC = ST_UART011_ABIMSC, +}; + +#endif -- cgit v0.10.2 From 998b4a4571b87eb6795863e07683fa5d4e0398ba Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:08 -0500 Subject: tty: Improve tty_debug() macro Incorporate suggestions for tty core debug macro improvements - printk(KERN_DEBUG) => pr_debug() - ##args => ##__VA_ARGS__ - remove do {} while() - output tty_name() first cc: Joe Perches Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/include/linux/tty.h b/include/linux/tty.h index 5e31f1b..3695c88 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -667,10 +667,7 @@ static inline void proc_tty_register_driver(struct tty_driver *d) {} static inline void proc_tty_unregister_driver(struct tty_driver *d) {} #endif -#define tty_debug(tty, f, args...) \ - do { \ - printk(KERN_DEBUG "%s: %s: " f, __func__, \ - tty_name(tty), ##args); \ - } while (0) +#define tty_debug(tty, f, ...) \ + pr_debug("%s: %s: " f, tty_name(tty), __func__, ##__VA_ARGS__) #endif -- cgit v0.10.2 From 82b8f888e99c81c609710901d8defbc8eff13f79 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:09 -0500 Subject: tty: Make tty_paranoia_check() file scope tty_paranoia_check() is only used within drivers/tty/tty_io.c; remove extern declaration in header and limit symbol to file scope. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index bcc8e1e..adc0229 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -256,7 +256,7 @@ const char *tty_name(const struct tty_struct *tty) EXPORT_SYMBOL(tty_name); -int tty_paranoia_check(struct tty_struct *tty, struct inode *inode, +static int tty_paranoia_check(struct tty_struct *tty, struct inode *inode, const char *routine) { #ifdef TTY_PARANOIA_CHECK diff --git a/include/linux/tty.h b/include/linux/tty.h index 3695c88..0532465 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -419,8 +419,6 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty) return tty; } -extern int tty_paranoia_check(struct tty_struct *tty, struct inode *inode, - const char *routine); extern const char *tty_name(const struct tty_struct *tty); extern void tty_wait_until_sent(struct tty_struct *tty, long timeout); extern int __tty_check_change(struct tty_struct *tty, int sig); -- cgit v0.10.2 From 076fe30334557d69c8f11db1f3f192f4ae448686 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:10 -0500 Subject: tty: synclink_gt: Rename tty_driver_name Eliminate symbol name collision with new tty core function, tty_driver_name(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 6fc39fb..5505ea8 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -89,7 +89,7 @@ * module identification */ static char *driver_name = "SyncLink GT"; -static char *tty_driver_name = "synclink_gt"; +static char *slgt_driver_name = "synclink_gt"; static char *tty_dev_prefix = "ttySLG"; MODULE_LICENSE("GPL"); #define MGSL_MAGIC 0x5401 @@ -3799,7 +3799,7 @@ static int __init slgt_init(void) /* Initialize the tty_driver structure */ - serial_driver->driver_name = tty_driver_name; + serial_driver->driver_name = slgt_driver_name; serial_driver->name = tty_dev_prefix; serial_driver->major = ttymajor; serial_driver->minor_start = 64; -- cgit v0.10.2 From 25080652a2d4a6d27a51fc1412e258f467174615 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:11 -0500 Subject: tty: core: Remove redundant oom message kmalloc() already emits a diagnostic for failed allocations; remove tty-specific message. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index adc0229..336714c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1580,10 +1580,8 @@ void tty_free_termios(struct tty_struct *tty) tp = tty->driver->termios[idx]; if (tp == NULL) { tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); - if (tp == NULL) { - pr_warn("tty: no memory to save termios state.\n"); + if (tp == NULL) return; - } tty->driver->termios[idx] = tp; } *tp = tty->termios; -- cgit v0.10.2 From 0a083eddae33b6e20234d05a9cf54f87b0095511 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:12 -0500 Subject: tty: core: Add helper fn to deref tty driver name Similar to tty_name(), add tty_driver_name() helper to safely dereference tty->driver->name (otherwise return empty string). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 336714c..ef8ee34 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -256,6 +256,13 @@ const char *tty_name(const struct tty_struct *tty) EXPORT_SYMBOL(tty_name); +const char *tty_driver_name(const struct tty_struct *tty) +{ + if (!tty || !tty->driver) + return ""; + return tty->driver->name; +} + static int tty_paranoia_check(struct tty_struct *tty, struct inode *inode, const char *routine) { diff --git a/include/linux/tty.h b/include/linux/tty.h index 0532465..a9c1af9 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -420,6 +420,7 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty) } extern const char *tty_name(const struct tty_struct *tty); +extern const char *tty_driver_name(const struct tty_struct *tty); extern void tty_wait_until_sent(struct tty_struct *tty, long timeout); extern int __tty_check_change(struct tty_struct *tty, int sig); extern int tty_check_change(struct tty_struct *tty); -- cgit v0.10.2 From 339f36ba14cf9f8fcf6e6b78385bd6811ec59fbe Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:13 -0500 Subject: tty: Define tty_*() printk macros Since not all ttys are devices (eg., SysV ptys), dev_*() printk macros cannot be used. Define tty_*() printk macros that output in similar format to dev_*() macros (ie., : .....). Transform the most-trivial printk( LEVEL ...) usage to tty_*() usage. NB: The function name has been eliminated from messages with unique context, or prefixed to the format when given. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index ed77614..c37c15d 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1201,9 +1201,7 @@ static void n_tty_receive_overrun(struct tty_struct *tty) ldata->num_overrun++; if (time_after(jiffies, ldata->overrun_time + HZ) || time_after(ldata->overrun_time, jiffies)) { - printk(KERN_WARNING "%s: %d input overrun(s)\n", - tty_name(tty), - ldata->num_overrun); + tty_warn(tty, "%d input overrun(s)\n", ldata->num_overrun); ldata->overrun_time = jiffies; ldata->num_overrun = 0; } @@ -1486,8 +1484,7 @@ n_tty_receive_char_flagged(struct tty_struct *tty, unsigned char c, char flag) n_tty_receive_overrun(tty); break; default: - printk(KERN_ERR "%s: unknown flag %d\n", - tty_name(tty), flag); + tty_err(tty, "unknown flag %d\n", flag); break; } } diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index ef8ee34..c9d3989 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -300,9 +300,8 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) tty->link && tty->link->count) count++; if (tty->count != count) { - printk(KERN_WARNING "Warning: dev (%s) tty->count(%d) " - "!= #fd's(%d) in %s\n", - tty->name, tty->count, count, routine); + tty_warn(tty, "%s: tty->count(%d) != #fd's(%d)\n", + routine, tty->count, count); return count; } #endif @@ -427,10 +426,8 @@ int __tty_check_change(struct tty_struct *tty, int sig) } rcu_read_unlock(); - if (!tty_pgrp) { - pr_warn("%s: tty_check_change: sig=%d, tty->pgrp == NULL!\n", - tty_name(tty), sig); - } + if (!tty_pgrp) + tty_warn(tty, "sig=%d, tty->pgrp == NULL!\n", sig); return ret; } @@ -1246,8 +1243,7 @@ static ssize_t tty_write(struct file *file, const char __user *buf, return -EIO; /* Short term debug to catch buggy drivers */ if (tty->ops->write_room == NULL) - printk(KERN_ERR "tty driver %s lacks a write_room method.\n", - tty->driver->name); + tty_err(tty, "missing write_room method\n"); ld = tty_ldisc_ref_wait(tty); if (!ld->ops->write) ret = -EIO; @@ -1568,8 +1564,8 @@ err_module_put: /* call the tty release_tty routine to clean out this slot */ err_release_tty: tty_unlock(tty); - printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, " - "clearing slot %d\n", idx); + tty_info_ratelimited(tty, "ldisc open failed (%d), clearing slot %d\n", + retval, idx); release_tty(tty, idx); return ERR_PTR(retval); } @@ -1842,8 +1838,7 @@ int tty_release(struct inode *inode, struct file *filp) if (once) { once = 0; - printk(KERN_WARNING "%s: %s: read/write wait queue active!\n", - __func__, tty_name(tty)); + tty_warn(tty, "read/write wait queue active!\n"); } schedule_timeout_killable(timeout); if (timeout < 120 * HZ) @@ -1854,14 +1849,12 @@ int tty_release(struct inode *inode, struct file *filp) if (o_tty) { if (--o_tty->count < 0) { - printk(KERN_WARNING "%s: bad pty slave count (%d) for %s\n", - __func__, o_tty->count, tty_name(o_tty)); + tty_warn(tty, "bad slave count (%d)\n", o_tty->count); o_tty->count = 0; } } if (--tty->count < 0) { - printk(KERN_WARNING "%s: bad tty->count (%d) for %s\n", - __func__, tty->count, tty_name(tty)); + tty_warn(tty, "bad tty->count (%d)\n", tty->count); tty->count = 0; } diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 482f33f..846ed48 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -462,14 +462,13 @@ int tty_port_close_start(struct tty_port *port, spin_lock_irqsave(&port->lock, flags); if (tty->count == 1 && port->count != 1) { - printk(KERN_WARNING - "tty_port_close_start: tty->count = 1 port count = %d.\n", - port->count); + tty_warn(tty, "%s: tty->count = 1 port count = %d\n", __func__, + port->count); port->count = 1; } if (--port->count < 0) { - printk(KERN_WARNING "tty_port_close_start: count = %d\n", - port->count); + tty_warn(tty, "%s: bad port count (%d)\n", __func__, + port->count); port->count = 0; } diff --git a/include/linux/tty.h b/include/linux/tty.h index a9c1af9..f578e84 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -666,7 +666,17 @@ static inline void proc_tty_register_driver(struct tty_driver *d) {} static inline void proc_tty_unregister_driver(struct tty_driver *d) {} #endif +#define tty_msg(fn, tty, f, ...) \ + fn("%s %s: " f, tty_driver_name(tty), tty_name(tty), ##__VA_ARGS__) + #define tty_debug(tty, f, ...) \ - pr_debug("%s: %s: " f, tty_name(tty), __func__, ##__VA_ARGS__) + tty_msg(pr_debug, tty, "%s:" f, __func__, ##__VA_ARGS__) +#define tty_info(tty, f, ...) tty_msg(pr_info, tty, f, ##__VA_ARGS__) +#define tty_notice(tty, f, ...) tty_msg(pr_notice, tty, f, ##__VA_ARGS__) +#define tty_warn(tty, f, ...) tty_msg(pr_warn, tty, f, ##__VA_ARGS__) +#define tty_err(tty, f, ...) tty_msg(pr_err, tty, f, ##__VA_ARGS__) + +#define tty_info_ratelimited(tty, f, ...) \ + tty_msg(pr_info_ratelimited, tty, f, ##__VA_ARGS__) #endif -- cgit v0.10.2 From 9b42bb750f24f5925d2fffed3f071726af72763a Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:14 -0500 Subject: tty: Convert SAK messages to tty_notice() Use tty_notice() for unified message format from the tty core. Fix each message to accurately reflect the cause of each termination. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index c9d3989..b64cd64 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3026,28 +3026,24 @@ void __do_SAK(struct tty_struct *tty) read_lock(&tasklist_lock); /* Kill the entire session */ do_each_pid_task(session, PIDTYPE_SID, p) { - printk(KERN_NOTICE "SAK: killed process %d" - " (%s): task_session(p)==tty->session\n", - task_pid_nr(p), p->comm); + tty_notice(tty, "SAK: killed process %d (%s): by session\n", + task_pid_nr(p), p->comm); send_sig(SIGKILL, p, 1); } while_each_pid_task(session, PIDTYPE_SID, p); - /* Now kill any processes that happen to have the - * tty open. - */ + + /* Now kill any processes that happen to have the tty open */ do_each_thread(g, p) { if (p->signal->tty == tty) { - printk(KERN_NOTICE "SAK: killed process %d" - " (%s): task_session(p)==tty->session\n", - task_pid_nr(p), p->comm); + tty_notice(tty, "SAK: killed process %d (%s): by controlling tty\n", + task_pid_nr(p), p->comm); send_sig(SIGKILL, p, 1); continue; } task_lock(p); i = iterate_fd(p->files, 0, this_tty, tty); if (i != 0) { - printk(KERN_NOTICE "SAK: killed process %d" - " (%s): fd#%d opened to the tty\n", - task_pid_nr(p), p->comm, i - 1); + tty_notice(tty, "SAK: killed process %d (%s): by fd#%d\n", + task_pid_nr(p), p->comm, i - 1); force_sig(SIGKILL, p); } task_unlock(p); -- cgit v0.10.2 From 656fb86770cffe25d002e1228931960219ccda6b Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:15 -0500 Subject: tty: core: Add driver name to invalid device registration message Include the driver name in the tty_register_device_attr() error message for invalid index. Note that tty_err() cannot be used here because there is no tty; use pr_err(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index b64cd64..86e379a 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3249,8 +3249,8 @@ struct device *tty_register_device_attr(struct tty_driver *driver, bool cdev = false; if (index >= driver->num) { - printk(KERN_ERR "Attempt to register invalid tty line number " - " (%d).\n", index); + pr_err("%s: Attempt to register invalid tty line number (%d)\n", + driver->name, index); return ERR_PTR(-EINVAL); } -- cgit v0.10.2 From d97ba9cdae73a69944c6051622c08bfa9016320e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:16 -0500 Subject: tty: core: Refactor parameters for unset_locked_termios() helper Add tty as parameter to unset_locked_termios() and extract former parameters, termios and locked, as locals. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 1445dd3..b41c708 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -239,10 +239,10 @@ EXPORT_SYMBOL(tty_wait_until_sent); * Termios Helper Methods */ -static void unset_locked_termios(struct ktermios *termios, - struct ktermios *old, - struct ktermios *locked) +static void unset_locked_termios(struct tty_struct *tty, struct ktermios *old) { + struct ktermios *termios = &tty->termios; + struct ktermios *locked = &tty->termios_locked; int i; #define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z))) @@ -556,7 +556,7 @@ int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios) down_write(&tty->termios_rwsem); old_termios = tty->termios; tty->termios = *new_termios; - unset_locked_termios(&tty->termios, &old_termios, &tty->termios_locked); + unset_locked_termios(tty, &old_termios); if (tty->ops->set_termios) tty->ops->set_termios(tty, &old_termios); -- cgit v0.10.2 From f658dca95075e0b6823650968edad68538494ab8 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:17 -0500 Subject: tty: Remove unset_locked_termios() error message With the refactor of 'locked' from parameter to local, it's now obvious locked cannot be NULL. Remove entire conditional. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index b41c708..e54879d 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -247,11 +247,6 @@ static void unset_locked_termios(struct tty_struct *tty, struct ktermios *old) #define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z))) - if (!locked) { - printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n"); - return; - } - NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag); NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag); NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag); -- cgit v0.10.2 From 89222e62662237faee90cd8486d23350f26b181d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:18 -0500 Subject: tty: core: Prefer pr_* to printk(*) Convert remaining printk() use to pr_*() when tty is unknown or unsafe to use. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 86e379a..d9df15f 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -268,14 +268,12 @@ static int tty_paranoia_check(struct tty_struct *tty, struct inode *inode, { #ifdef TTY_PARANOIA_CHECK if (!tty) { - printk(KERN_WARNING - "null TTY for (%d:%d) in %s\n", + pr_warn("(%d:%d): %s: NULL tty\n", imajor(inode), iminor(inode), routine); return 1; } if (tty->magic != TTY_MAGIC) { - printk(KERN_WARNING - "bad magic number for tty struct (%d:%d) in %s\n", + pr_warn("(%d:%d): %s: bad magic number\n", imajor(inode), iminor(inode), routine); return 1; } diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index e54879d..40964ea 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -458,10 +458,8 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, if (ifound == -1 && (ibaud != obaud || ibinput)) termios->c_cflag |= (BOTHER << IBSHIFT); #else - if (ifound == -1 || ofound == -1) { - printk_once(KERN_WARNING "tty: Unable to return correct " - "speed data as your architecture needs updating.\n"); - } + if (ifound == -1 || ofound == -1) + pr_warn_once("tty: Unable to return correct speed data as your architecture needs updating.\n"); #endif } EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate); -- cgit v0.10.2 From d435cefe9cbc9308cac8d4b19069a572e2bd1558 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:19 -0500 Subject: tty: Remove __func__ from tty_debug() macro Now that tty_debug() macro uses pr_debug(), the function name can be printed when using dynamic debug; printing the function name within the format string is redundant. Remove the __func__ parameter and print specifier from the format string. Add context to messages for when the function name is not printed by dynamic debug, or when dynamic debug is not enabled. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index a45660f..b311004 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -788,7 +788,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) if (retval) goto err_release; - tty_debug_hangup(tty, "(tty count=%d)\n", tty->count); + tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); tty_unlock(tty); return 0; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index d9df15f..f8e1fce 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -783,7 +783,7 @@ static void do_tty_hangup(struct work_struct *work) void tty_hangup(struct tty_struct *tty) { - tty_debug_hangup(tty, "\n"); + tty_debug_hangup(tty, "hangup\n"); schedule_work(&tty->hangup_work); } @@ -800,7 +800,7 @@ EXPORT_SYMBOL(tty_hangup); void tty_vhangup(struct tty_struct *tty) { - tty_debug_hangup(tty, "\n"); + tty_debug_hangup(tty, "vhangup\n"); __tty_hangup(tty, 0); } @@ -837,7 +837,7 @@ void tty_vhangup_self(void) static void tty_vhangup_session(struct tty_struct *tty) { - tty_debug_hangup(tty, "\n"); + tty_debug_hangup(tty, "session hangup\n"); __tty_hangup(tty, 1); } @@ -1787,7 +1787,7 @@ int tty_release(struct inode *inode, struct file *filp) return 0; } - tty_debug_hangup(tty, "(tty count=%d)...\n", tty->count); + tty_debug_hangup(tty, "releasing (count=%d)\n", tty->count); if (tty->ops->close) tty->ops->close(tty, filp); @@ -1903,7 +1903,7 @@ int tty_release(struct inode *inode, struct file *filp) /* Wait for pending work before tty destruction commmences */ tty_flush_works(tty); - tty_debug_hangup(tty, "freeing structure...\n"); + tty_debug_hangup(tty, "freeing structure\n"); /* * The release_tty function takes care of the details of clearing * the slots and preserving the termios structure. The tty_unlock_pair @@ -2093,7 +2093,7 @@ retry_open: tty->driver->subtype == PTY_TYPE_MASTER) noctty = 1; - tty_debug_hangup(tty, "(tty count=%d)\n", tty->count); + tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); if (tty->ops->open) retval = tty->ops->open(tty, filp); @@ -2102,7 +2102,7 @@ retry_open: filp->f_flags = saved_flags; if (retval) { - tty_debug_hangup(tty, "error %d, releasing...\n", retval); + tty_debug_hangup(tty, "open error %d, releasing\n", retval); tty_unlock(tty); /* need to call tty_release without BTM */ tty_release(inode, filp); diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 40964ea..0ea3513 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -216,7 +216,7 @@ int tty_unthrottle_safe(struct tty_struct *tty) void tty_wait_until_sent(struct tty_struct *tty, long timeout) { - tty_debug_wait_until_sent(tty, "\n"); + tty_debug_wait_until_sent(tty, "wait until sent, timeout=%ld\n", timeout); if (!timeout) timeout = MAX_SCHEDULE_TIMEOUT; diff --git a/include/linux/tty.h b/include/linux/tty.h index f578e84..f06dd7a 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -669,8 +669,7 @@ static inline void proc_tty_unregister_driver(struct tty_driver *d) {} #define tty_msg(fn, tty, f, ...) \ fn("%s %s: " f, tty_driver_name(tty), tty_name(tty), ##__VA_ARGS__) -#define tty_debug(tty, f, ...) \ - tty_msg(pr_debug, tty, "%s:" f, __func__, ##__VA_ARGS__) +#define tty_debug(tty, f, ...) tty_msg(pr_debug, tty, f, ##__VA_ARGS__) #define tty_info(tty, f, ...) tty_msg(pr_info, tty, f, ##__VA_ARGS__) #define tty_notice(tty, f, ...) tty_msg(pr_notice, tty, f, ##__VA_ARGS__) #define tty_warn(tty, f, ...) tty_msg(pr_warn, tty, f, ##__VA_ARGS__) -- cgit v0.10.2 From 6d029c68de1219ed791b484d0d289562a51520c7 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:20 -0500 Subject: tty: Merge conditional + error message + WARN_ON() WARN() does all of these things in one statement. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index 0efcf71..77703a39 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@ -12,11 +12,8 @@ void __lockfunc tty_lock(struct tty_struct *tty) { - if (tty->magic != TTY_MAGIC) { - pr_err("L Bad %p\n", tty); - WARN_ON(1); + if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty)) return; - } tty_kref_get(tty); mutex_lock(&tty->legacy_mutex); } @@ -24,11 +21,8 @@ EXPORT_SYMBOL(tty_lock); void __lockfunc tty_unlock(struct tty_struct *tty) { - if (tty->magic != TTY_MAGIC) { - pr_err("U Bad %p\n", tty); - WARN_ON(1); + if (WARN(tty->magic != TTY_MAGIC, "U Bad %p\n", tty)) return; - } mutex_unlock(&tty->legacy_mutex); tty_kref_put(tty); } -- cgit v0.10.2 From 83db1df4461c8731a413cd6cb1cbf351f01a57b1 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 13:01:21 -0500 Subject: tty: core: Prefer dev_dbg() over pr_debug() Where possible, use dev_dbg() instead of pr_debug() Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index f8e1fce..f38ae01 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3211,7 +3211,7 @@ EXPORT_SYMBOL(tty_register_device); static void tty_device_create_release(struct device *dev) { - pr_debug("device: '%s': %s\n", dev_name(dev), __func__); + dev_dbg(dev, "releasing...\n"); kfree(dev); } -- cgit v0.10.2 From d1d3a0f7448fe038ce7e94e2c281dcd2f91b23c6 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 09:06:05 -0500 Subject: tty: Only allow slave pty as controlling tty A master pty should never be a controlling tty in Linux; if the master pty is specified to ioctl(TIOCSCTTY), silently substitute the slave pty as the controlling tty. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index f38ae01..892c923 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2866,7 +2866,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) no_tty(); return 0; case TIOCSCTTY: - return tiocsctty(tty, file, arg); + return tiocsctty(real_tty, file, arg); case TIOCGPGRP: return tiocgpgrp(tty, real_tty, p); case TIOCSPGRP: -- cgit v0.10.2 From 4de91ebcc788f81d2a974d91208f5560ddf36378 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 09:18:31 -0500 Subject: tty: Remove dead tty_write_flush() declaration and macro tty_write_flush() has no definition and the TTY_WRITE_FLUSH() macro is never invoked; remove. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/include/linux/tty.h b/include/linux/tty.h index f06dd7a..2fd8708 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -345,8 +345,6 @@ struct tty_file_private { #define TTY_HUPPED 18 /* Post driver->hangup() */ #define TTY_LDISC_HALTED 22 /* Line discipline is halted */ -#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty)) - /* Values for tty->flow_change */ #define TTY_THROTTLE_SAFE 1 #define TTY_UNTHROTTLE_SAFE 2 @@ -395,8 +393,6 @@ static inline int __init tty_init(void) { return 0; } #endif -extern void tty_write_flush(struct tty_struct *); - extern struct ktermios tty_std_termios; extern int vcs_init(void); -- cgit v0.10.2 From 5841fc4b136b8dbab551749d2b12d71628f34635 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 09:18:32 -0500 Subject: tty: Remove unused SERIAL_DO_RESTART define SERIAL_DO_RESTART is not used by these 3 drivers; remove. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index e53d9a5..2caaf5a 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -32,7 +32,6 @@ #include #undef SERIAL_PARANOIA_CHECK -#define SERIAL_DO_RESTART /* Set of debugging defines */ diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index 14c54e0..92982d7 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -155,7 +155,6 @@ struct mon_str { #define LOWWAIT 2 #define EMPTYWAIT 3 -#define SERIAL_DO_RESTART #define WAKEUP_CHARS 256 diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c index ffc7cb2..c60a8d5e 100644 --- a/drivers/tty/serial/icom.c +++ b/drivers/tty/serial/icom.c @@ -22,7 +22,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#define SERIAL_DO_RESTART #include #include #include -- cgit v0.10.2 From 63d8cb3f19dabb409a09b4f2b8827934ab9365a3 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 8 Nov 2015 09:29:38 -0500 Subject: tty: Simplify tty_set_ldisc() exit handling Perform common exit for both successful and error exit handling in tty_set_ldisc(). Fixes unlikely possibility of failing to restart input kworker when switching to the same line discipline (noop case). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 7d43ff1..9ec1250 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -529,34 +529,21 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) tty_lock(tty); retval = tty_ldisc_lock(tty, 5 * HZ); - if (retval) { - tty_ldisc_put(new_ldisc); - tty_unlock(tty); - return retval; - } + if (retval) + goto err; - /* - * Check the no-op case - */ + /* Check the no-op case */ + if (tty->ldisc->ops->num == ldisc) + goto out; - if (tty->ldisc->ops->num == ldisc) { - tty_ldisc_unlock(tty); - tty_ldisc_put(new_ldisc); - tty_unlock(tty); - return 0; + if (test_bit(TTY_HUPPED, &tty->flags)) { + /* We were raced by hangup */ + retval = -EIO; + goto out; } old_ldisc = tty->ldisc; - if (test_bit(TTY_HUPPED, &tty->flags)) { - /* We were raced by the hangup method. It will have stomped - the ldisc data and closed the ldisc down */ - tty_ldisc_unlock(tty); - tty_ldisc_put(new_ldisc); - tty_unlock(tty); - return -EIO; - } - /* Shutdown the old discipline. */ tty_ldisc_close(tty, old_ldisc); @@ -582,18 +569,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) the old ldisc (if it was restored as part of error cleanup above). In either case, releasing a single reference from the old ldisc is correct. */ - - tty_ldisc_put(old_ldisc); - - /* - * Allow ldisc referencing to occur again - */ + new_ldisc = old_ldisc; +out: tty_ldisc_unlock(tty); /* Restart the work queue in case no characters kick it off. Safe if already running */ tty_buffer_restart_work(tty->port); - +err: + tty_ldisc_put(new_ldisc); /* drop the extra reference */ tty_unlock(tty); return retval; } -- cgit v0.10.2 From ed7a85045d0a0688a51bdab9e1a1d6ee79cb33b6 Mon Sep 17 00:00:00 2001 From: Florian Achleitner Date: Wed, 18 Nov 2015 09:04:12 +0100 Subject: sc16is7xx: Fix TX buffer overrun caused by wrong tx fifo level read-out We found that our sc16is7xx on spi reported a TX fifo free space value (TXLVL_REG) of 255 ocassionally, which is obviously wrong, with a 64 byte fifo and caused a buffer overrun and a kernel crash. To trigger this, a large write to the tty is sufficient. The fifo fills, TXLVL_REG reads zero, but the handle_tx function does a zero-data-length write to the TX fifo anyways through sc16is7xx_fifo_write. The next TXLVL_REG read then yields 255, for unknown reasons. A subsequent read is ok. Prevent zero-data-length writes if the TX fifo is full, because they are pointless, and because they trigger wrong TXLVL read-outs. Furthermore, prevent a TX buffer overrun if the peripheral reports values larger than the buffer size and thus, don't allow the peripheral to crash the kernel. Signed-off-by: Florian Achleitner Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index edb5305..5815bcb 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -389,6 +389,13 @@ static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send) const u8 line = sc16is7xx_line(port); u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | line; + /* + * Don't send zero-length data, at least on SPI it confuses the chip + * delivering wrong TXLVL data. + */ + if (unlikely(!to_send)) + return; + regcache_cache_bypass(s->regmap, true); regmap_raw_write(s->regmap, addr, s->buf, to_send); regcache_cache_bypass(s->regmap, false); @@ -630,6 +637,12 @@ static void sc16is7xx_handle_tx(struct uart_port *port) if (likely(to_send)) { /* Limit to size of TX FIFO */ txlen = sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG); + if (txlen > SC16IS7XX_FIFO_SIZE) { + dev_err_ratelimited(port->dev, + "chip reports %d free bytes in TX fifo, but it only has %d", + txlen, SC16IS7XX_FIFO_SIZE); + txlen = 0; + } to_send = (to_send > txlen) ? txlen : to_send; /* Add data to send */ -- cgit v0.10.2 From 55fe84b17a8f9c7a3cdfbfefdb519311aa6ff1da Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 9 Nov 2015 10:31:14 +0100 Subject: serial: SERIAL_ATMEL should depend on HAS_DMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If NO_DMA=y: drivers/built-in.o: In function `atmel_release_rx_dma': atmel_serial.c:(.text+0x2502e): undefined reference to `dma_unmap_sg' drivers/built-in.o: In function `atmel_release_tx_dma': atmel_serial.c:(.text+0x25080): undefined reference to `dma_unmap_sg' drivers/built-in.o: In function `atmel_tx_dma': atmel_serial.c:(.text+0x2517a): undefined reference to `dma_sync_sg_for_cpu' drivers/built-in.o: In function `atmel_release_tx_pdc': atmel_serial.c:(.text+0x252e6): undefined reference to `dma_unmap_single' drivers/built-in.o: In function `atmel_prepare_tx_pdc': atmel_serial.c:(.text+0x2531a): undefined reference to `dma_map_single' drivers/built-in.o: In function `atmel_release_rx_pdc': atmel_serial.c:(.text+0x25362): undefined reference to `dma_unmap_single' drivers/built-in.o: In function `atmel_tx_pdc': atmel_serial.c:(.text+0x25722): undefined reference to `dma_sync_single_for_cpu' drivers/built-in.o: In function `atmel_rx_from_pdc': atmel_serial.c:(.text+0x2601a): undefined reference to `dma_sync_single_for_cpu' drivers/built-in.o: In function `atmel_rx_from_dma': atmel_serial.c:(.text+0x261b2): undefined reference to `dma_sync_sg_for_cpu' atmel_serial.c:(.text+0x26264): undefined reference to `dma_sync_sg_for_cpu' drivers/built-in.o: In function `atmel_prepare_rx_pdc': atmel_serial.c:(.text+0x262de): undefined reference to `dma_unmap_single' atmel_serial.c:(.text+0x26308): undefined reference to `dma_map_single' Add a dependency on HAS_DMA to fix this. Signed-off-by: Geert Uytterhoeven Acked-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index f38beb2..a1003ea 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -115,6 +115,7 @@ config SERIAL_SB1250_DUART_CONSOLE config SERIAL_ATMEL bool "AT91 / AT32 on-chip serial port support" + depends on HAS_DMA depends on ARCH_AT91 || AVR32 || COMPILE_TEST select SERIAL_CORE select SERIAL_MCTRL_GPIO if GPIOLIB -- cgit v0.10.2 From f8032cb4f574c0de5ac1d65d61e972957e6f1631 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 9 Nov 2015 10:31:15 +0100 Subject: serial: SERIAL_IMX_AUART should depend on HAS_DMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If NO_DMA=y: ERROR: "dma_unmap_sg" [drivers/tty/serial/imx.ko] undefined! ERROR: "dma_map_sg" [drivers/tty/serial/imx.ko] undefined! Add a dependency on HAS_DMA to fix this. Signed-off-by: Geert Uytterhoeven Acked-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index a1003ea..1ec4764 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -572,6 +572,7 @@ config BFIN_UART3_CTSRTS config SERIAL_IMX tristate "IMX serial port support" + depends on HAS_DMA depends on ARCH_MXC || COMPILE_TEST select SERIAL_CORE select RATIONAL -- cgit v0.10.2 From 29647c483658f1e3d2e0ec9ad64ebd23edeecdf5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 9 Nov 2015 10:31:16 +0100 Subject: serial: SERIAL_MXS_AUART should depend on HAS_DMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If NO_DMA=y: ERROR: "dma_unmap_sg" [drivers/tty/serial/mxs-auart.ko] undefined! ERROR: "dma_map_sg" [drivers/tty/serial/mxs-auart.ko] undefined! Add a dependency on HAS_DMA to fix this. Signed-off-by: Geert Uytterhoeven Acked-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 1ec4764..f0bbedf 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1411,8 +1411,9 @@ config SERIAL_PCH_UART_CONSOLE warnings and which allows logins in single user mode). config SERIAL_MXS_AUART - depends on ARCH_MXS || COMPILE_TEST tristate "MXS AUART support" + depends on HAS_DMA + depends on ARCH_MXS || COMPILE_TEST select SERIAL_CORE select SERIAL_MCTRL_GPIO if GPIOLIB help -- cgit v0.10.2 From 3ac4ae4736d404c436edf3b2ecfd941368f9e247 Mon Sep 17 00:00:00 2001 From: DengChao Date: Thu, 12 Nov 2015 21:45:47 +0800 Subject: serial:bfin-uart:Remove 'struct timeval' The bfin-uart code uses real time with struct timeval. This will cause problems on 32-bit architectures in 2038 when time_t overflows. Since the code just needs delta value of time, it is not necessary to record them in real time. This patch changes the code to use the monotonic time instead, replaces struct timeval and do_gettimeofday() with u64 and ktime_get_ns(). Signed-off-by: DengChao Reviewed-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index ae3cf94..293ecbb 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c @@ -213,7 +213,7 @@ static void bfin_serial_stop_rx(struct uart_port *port) static void bfin_serial_rx_chars(struct bfin_serial_port *uart) { unsigned int status, ch, flg; - static struct timeval anomaly_start = { .tv_sec = 0 }; + static u64 anomaly_start; status = UART_GET_LSR(uart); UART_CLEAR_LSR(uart); @@ -246,27 +246,24 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) * character time +/- some percent. So 1.5 sounds good. All other * Blackfin families operate properly. Woo. */ - if (anomaly_start.tv_sec) { - struct timeval curr; - suseconds_t usecs; + if (anomaly_start > 0) { + u64 curr, nsecs, threshold_ns; if ((~ch & (~ch + 1)) & 0xff) goto known_good_char; - do_gettimeofday(&curr); - if (curr.tv_sec - anomaly_start.tv_sec > 1) + curr = ktime_get_ns(); + nsecs = curr - anomaly_start; + if (nsecs >> 32) goto known_good_char; - usecs = 0; - if (curr.tv_sec != anomaly_start.tv_sec) - usecs += USEC_PER_SEC; - usecs += curr.tv_usec - anomaly_start.tv_usec; - - if (usecs > UART_GET_ANOMALY_THRESHOLD(uart)) + threshold_ns = UART_GET_ANOMALY_THRESHOLD(uart) + * NSEC_PER_USEC; + if (nsecs > threshold_ns) goto known_good_char; if (ch) - anomaly_start.tv_sec = 0; + anomaly_start = 0; else anomaly_start = curr; @@ -274,14 +271,14 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) known_good_char: status &= ~BI; - anomaly_start.tv_sec = 0; + anomaly_start = 0; } } if (status & BI) { if (ANOMALY_05000363) if (bfin_revid() < 5) - do_gettimeofday(&anomaly_start); + anomaly_start = ktime_get_ns(); uart->port.icount.brk++; if (uart_handle_break(&uart->port)) goto ignore_char; -- cgit v0.10.2 From d1b5c87fa8058a3f477ae05555916dd1cea934ad Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 16 Nov 2015 16:48:12 +0100 Subject: serial: remove NWP serial support The NWP serial driver is no longer needed, as the two users of this hardware have migrated to a much faster generation hardware, see https://en.wikipedia.org/wiki/QPACE2 for the replacement. Signed-off-by: Arnd Bergmann Cc: Benjamin Krill Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index f0bbedf..643fc50 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1099,7 +1099,7 @@ config SERIAL_NETX_CONSOLE config SERIAL_OF_PLATFORM tristate "Serial port on Open Firmware platform bus" depends on OF - depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL + depends on SERIAL_8250 help If you have a PowerPC based system that has serial ports on a platform specific bus, you should enable this option. @@ -1133,23 +1133,6 @@ config SERIAL_OMAP_CONSOLE your boot loader about how to pass options to the kernel at boot time.) -config SERIAL_OF_PLATFORM_NWPSERIAL - tristate "NWP serial port driver" - depends on PPC_DCR - select SERIAL_OF_PLATFORM - select SERIAL_CORE_CONSOLE - select SERIAL_CORE - help - This driver supports the cell network processor nwp serial - device. - -config SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE - bool "Console on NWP serial port" - depends on SERIAL_OF_PLATFORM_NWPSERIAL=y - select SERIAL_CORE_CONSOLE - help - Support for Console on the NWP serial ports. - config SERIAL_LANTIQ bool "Lantiq serial driver" depends on LANTIQ diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 5ab4111..ee88933 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -64,7 +64,6 @@ obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_MSM) += msm_serial.o obj-$(CONFIG_SERIAL_NETX) += netx-serial.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o -obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o diff --git a/drivers/tty/serial/nwpserial.c b/drivers/tty/serial/nwpserial.c deleted file mode 100644 index 5da7622..0000000 --- a/drivers/tty/serial/nwpserial.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Serial Port driver for a NWP uart device - * - * Copyright (C) 2008 IBM Corp., Benjamin Krill - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NWPSERIAL_NR 2 - -#define NWPSERIAL_STATUS_RXVALID 0x1 -#define NWPSERIAL_STATUS_TXFULL 0x2 - -struct nwpserial_port { - struct uart_port port; - dcr_host_t dcr_host; - unsigned int ier; - unsigned int mcr; -}; - -static DEFINE_MUTEX(nwpserial_mutex); -static struct nwpserial_port nwpserial_ports[NWPSERIAL_NR]; - -static void wait_for_bits(struct nwpserial_port *up, int bits) -{ - unsigned int status, tmout = 10000; - - /* Wait up to 10ms for the character(s) to be sent. */ - do { - status = dcr_read(up->dcr_host, UART_LSR); - - if (--tmout == 0) - break; - udelay(1); - } while ((status & bits) != bits); -} - -#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE -static void nwpserial_console_putchar(struct uart_port *port, int c) -{ - struct nwpserial_port *up; - up = container_of(port, struct nwpserial_port, port); - /* check if tx buffer is full */ - wait_for_bits(up, UART_LSR_THRE); - dcr_write(up->dcr_host, UART_TX, c); - up->port.icount.tx++; -} - -static void -nwpserial_console_write(struct console *co, const char *s, unsigned int count) -{ - struct nwpserial_port *up = &nwpserial_ports[co->index]; - unsigned long flags; - int locked = 1; - - if (oops_in_progress) - locked = spin_trylock_irqsave(&up->port.lock, flags); - else - spin_lock_irqsave(&up->port.lock, flags); - - /* save and disable interrupt */ - up->ier = dcr_read(up->dcr_host, UART_IER); - dcr_write(up->dcr_host, UART_IER, up->ier & ~UART_IER_RDI); - - uart_console_write(&up->port, s, count, nwpserial_console_putchar); - - /* wait for transmitter to become empty */ - while ((dcr_read(up->dcr_host, UART_LSR) & UART_LSR_THRE) == 0) - cpu_relax(); - - /* restore interrupt state */ - dcr_write(up->dcr_host, UART_IER, up->ier); - - if (locked) - spin_unlock_irqrestore(&up->port.lock, flags); -} - -static struct uart_driver nwpserial_reg; -static struct console nwpserial_console = { - .name = "ttySQ", - .write = nwpserial_console_write, - .device = uart_console_device, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &nwpserial_reg, -}; -#define NWPSERIAL_CONSOLE (&nwpserial_console) -#else -#define NWPSERIAL_CONSOLE NULL -#endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */ - -/**************************************************************************/ - -static int nwpserial_request_port(struct uart_port *port) -{ - return 0; -} - -static void nwpserial_release_port(struct uart_port *port) -{ - /* N/A */ -} - -static void nwpserial_config_port(struct uart_port *port, int flags) -{ - port->type = PORT_NWPSERIAL; -} - -static irqreturn_t nwpserial_interrupt(int irq, void *dev_id) -{ - struct nwpserial_port *up = dev_id; - struct tty_port *port = &up->port.state->port; - irqreturn_t ret; - unsigned int iir; - unsigned char ch; - - spin_lock(&up->port.lock); - - /* check if the uart was the interrupt source. */ - iir = dcr_read(up->dcr_host, UART_IIR); - if (!iir) { - ret = IRQ_NONE; - goto out; - } - - do { - up->port.icount.rx++; - ch = dcr_read(up->dcr_host, UART_RX); - if (up->port.ignore_status_mask != NWPSERIAL_STATUS_RXVALID) - tty_insert_flip_char(port, ch, TTY_NORMAL); - } while (dcr_read(up->dcr_host, UART_LSR) & UART_LSR_DR); - - spin_unlock(&up->port.lock); - tty_flip_buffer_push(port); - spin_lock(&up->port.lock); - - ret = IRQ_HANDLED; - - /* clear interrupt */ - dcr_write(up->dcr_host, UART_IIR, 1); -out: - spin_unlock(&up->port.lock); - return ret; -} - -static int nwpserial_startup(struct uart_port *port) -{ - struct nwpserial_port *up; - int err; - - up = container_of(port, struct nwpserial_port, port); - - /* disable flow control by default */ - up->mcr = dcr_read(up->dcr_host, UART_MCR) & ~UART_MCR_AFE; - dcr_write(up->dcr_host, UART_MCR, up->mcr); - - /* register interrupt handler */ - err = request_irq(up->port.irq, nwpserial_interrupt, - IRQF_SHARED, "nwpserial", up); - if (err) - return err; - - /* enable interrupts */ - up->ier = UART_IER_RDI; - dcr_write(up->dcr_host, UART_IER, up->ier); - - /* enable receiving */ - up->port.ignore_status_mask &= ~NWPSERIAL_STATUS_RXVALID; - - return 0; -} - -static void nwpserial_shutdown(struct uart_port *port) -{ - struct nwpserial_port *up; - up = container_of(port, struct nwpserial_port, port); - - /* disable receiving */ - up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID; - - /* disable interrupts from this port */ - up->ier = 0; - dcr_write(up->dcr_host, UART_IER, up->ier); - - /* free irq */ - free_irq(up->port.irq, up); -} - -static int nwpserial_verify_port(struct uart_port *port, - struct serial_struct *ser) -{ - return -EINVAL; -} - -static const char *nwpserial_type(struct uart_port *port) -{ - return port->type == PORT_NWPSERIAL ? "nwpserial" : NULL; -} - -static void nwpserial_set_termios(struct uart_port *port, - struct ktermios *termios, struct ktermios *old) -{ - struct nwpserial_port *up; - up = container_of(port, struct nwpserial_port, port); - - up->port.read_status_mask = NWPSERIAL_STATUS_RXVALID - | NWPSERIAL_STATUS_TXFULL; - - up->port.ignore_status_mask = 0; - /* ignore all characters if CREAD is not set */ - if ((termios->c_cflag & CREAD) == 0) - up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID; - - /* Copy back the old hardware settings */ - if (old) - tty_termios_copy_hw(termios, old); -} - -static void nwpserial_break_ctl(struct uart_port *port, int ctl) -{ - /* N/A */ -} - -static void nwpserial_stop_rx(struct uart_port *port) -{ - struct nwpserial_port *up; - up = container_of(port, struct nwpserial_port, port); - /* don't forward any more data (like !CREAD) */ - up->port.ignore_status_mask = NWPSERIAL_STATUS_RXVALID; -} - -static void nwpserial_putchar(struct nwpserial_port *up, unsigned char c) -{ - /* check if tx buffer is full */ - wait_for_bits(up, UART_LSR_THRE); - dcr_write(up->dcr_host, UART_TX, c); - up->port.icount.tx++; -} - -static void nwpserial_start_tx(struct uart_port *port) -{ - struct nwpserial_port *up; - struct circ_buf *xmit; - up = container_of(port, struct nwpserial_port, port); - xmit = &up->port.state->xmit; - - if (port->x_char) { - nwpserial_putchar(up, up->port.x_char); - port->x_char = 0; - } - - while (!(uart_circ_empty(xmit) || uart_tx_stopped(&up->port))) { - nwpserial_putchar(up, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); - } -} - -static unsigned int nwpserial_get_mctrl(struct uart_port *port) -{ - return 0; -} - -static void nwpserial_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - /* N/A */ -} - -static void nwpserial_stop_tx(struct uart_port *port) -{ - /* N/A */ -} - -static unsigned int nwpserial_tx_empty(struct uart_port *port) -{ - struct nwpserial_port *up; - unsigned long flags; - int ret; - up = container_of(port, struct nwpserial_port, port); - - spin_lock_irqsave(&up->port.lock, flags); - ret = dcr_read(up->dcr_host, UART_LSR); - spin_unlock_irqrestore(&up->port.lock, flags); - - return ret & UART_LSR_TEMT ? TIOCSER_TEMT : 0; -} - -static struct uart_ops nwpserial_pops = { - .tx_empty = nwpserial_tx_empty, - .set_mctrl = nwpserial_set_mctrl, - .get_mctrl = nwpserial_get_mctrl, - .stop_tx = nwpserial_stop_tx, - .start_tx = nwpserial_start_tx, - .stop_rx = nwpserial_stop_rx, - .break_ctl = nwpserial_break_ctl, - .startup = nwpserial_startup, - .shutdown = nwpserial_shutdown, - .set_termios = nwpserial_set_termios, - .type = nwpserial_type, - .release_port = nwpserial_release_port, - .request_port = nwpserial_request_port, - .config_port = nwpserial_config_port, - .verify_port = nwpserial_verify_port, -}; - -static struct uart_driver nwpserial_reg = { - .owner = THIS_MODULE, - .driver_name = "nwpserial", - .dev_name = "ttySQ", - .major = TTY_MAJOR, - .minor = 68, - .nr = NWPSERIAL_NR, - .cons = NWPSERIAL_CONSOLE, -}; - -int nwpserial_register_port(struct uart_port *port) -{ - struct nwpserial_port *up = NULL; - int ret = -1; - int i; - static int first = 1; - int dcr_len; - int dcr_base; - struct device_node *dn; - - mutex_lock(&nwpserial_mutex); - - dn = port->dev->of_node; - if (dn == NULL) - goto out; - - /* get dcr base. */ - dcr_base = dcr_resource_start(dn, 0); - - /* find matching entry */ - for (i = 0; i < NWPSERIAL_NR; i++) - if (nwpserial_ports[i].port.iobase == dcr_base) { - up = &nwpserial_ports[i]; - break; - } - - /* we didn't find a mtching entry, search for a free port */ - if (up == NULL) - for (i = 0; i < NWPSERIAL_NR; i++) - if (nwpserial_ports[i].port.type == PORT_UNKNOWN && - nwpserial_ports[i].port.iobase == 0) { - up = &nwpserial_ports[i]; - break; - } - - if (up == NULL) { - ret = -EBUSY; - goto out; - } - - if (first) - uart_register_driver(&nwpserial_reg); - first = 0; - - up->port.membase = port->membase; - up->port.irq = port->irq; - up->port.uartclk = port->uartclk; - up->port.fifosize = port->fifosize; - up->port.regshift = port->regshift; - up->port.iotype = port->iotype; - up->port.flags = port->flags; - up->port.mapbase = port->mapbase; - up->port.private_data = port->private_data; - - if (port->dev) - up->port.dev = port->dev; - - if (up->port.iobase != dcr_base) { - up->port.ops = &nwpserial_pops; - up->port.fifosize = 16; - - spin_lock_init(&up->port.lock); - - up->port.iobase = dcr_base; - dcr_len = dcr_resource_len(dn, 0); - - up->dcr_host = dcr_map(dn, dcr_base, dcr_len); - if (!DCR_MAP_OK(up->dcr_host)) { - printk(KERN_ERR "Cannot map DCR resources for NWPSERIAL"); - goto out; - } - } - - ret = uart_add_one_port(&nwpserial_reg, &up->port); - if (ret == 0) - ret = up->port.line; - -out: - mutex_unlock(&nwpserial_mutex); - - return ret; -} -EXPORT_SYMBOL(nwpserial_register_port); - -void nwpserial_unregister_port(int line) -{ - struct nwpserial_port *up = &nwpserial_ports[line]; - mutex_lock(&nwpserial_mutex); - uart_remove_one_port(&nwpserial_reg, &up->port); - - up->port.type = PORT_UNKNOWN; - - mutex_unlock(&nwpserial_mutex); -} -EXPORT_SYMBOL(nwpserial_unregister_port); - -#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE -static int __init nwpserial_console_init(void) -{ - struct nwpserial_port *up = NULL; - struct device_node *dn; - const char *name; - int dcr_base; - int dcr_len; - int i; - - /* search for a free port */ - for (i = 0; i < NWPSERIAL_NR; i++) - if (nwpserial_ports[i].port.type == PORT_UNKNOWN) { - up = &nwpserial_ports[i]; - break; - } - - if (up == NULL) - return -1; - - name = of_get_property(of_chosen, "linux,stdout-path", NULL); - if (name == NULL) - return -1; - - dn = of_find_node_by_path(name); - if (!dn) - return -1; - - spin_lock_init(&up->port.lock); - up->port.ops = &nwpserial_pops; - up->port.type = PORT_NWPSERIAL; - up->port.fifosize = 16; - - dcr_base = dcr_resource_start(dn, 0); - dcr_len = dcr_resource_len(dn, 0); - up->port.iobase = dcr_base; - - up->dcr_host = dcr_map(dn, dcr_base, dcr_len); - if (!DCR_MAP_OK(up->dcr_host)) { - printk("Cannot map DCR resources for SERIAL"); - return -1; - } - register_console(&nwpserial_console); - return 0; -} -console_initcall(nwpserial_console_init); -#endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */ diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 6d002ee..920468b 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -216,11 +216,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev) break; } #endif -#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL - case PORT_NWPSERIAL: - ret = nwpserial_register_port(&port); - break; -#endif default: /* need to add code for these */ case PORT_UNKNOWN: @@ -253,11 +248,6 @@ static int of_platform_serial_remove(struct platform_device *ofdev) serial8250_unregister_port(info->line); break; #endif -#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL - case PORT_NWPSERIAL: - nwpserial_unregister_port(info->line); - break; -#endif default: /* need to add code for these */ break; @@ -356,10 +346,6 @@ static const struct of_device_id of_platform_serial_table[] = { .data = (void *)PORT_XSCALE, }, { .compatible = "mrvl,pxa-uart", .data = (void *)PORT_XSCALE, }, -#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL - { .compatible = "ibm,qpace-nwp-serial", - .data = (void *)PORT_NWPSERIAL, }, -#endif { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, of_platform_serial_table); diff --git a/include/linux/nwpserial.h b/include/linux/nwpserial.h deleted file mode 100644 index 9acb215..0000000 --- a/include/linux/nwpserial.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Serial Port driver for a NWP uart device - * - * Copyright (C) 2008 IBM Corp., Benjamin Krill - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ -#ifndef _NWPSERIAL_H -#define _NWPSERIAL_H - -int nwpserial_register_port(struct uart_port *port); -void nwpserial_unregister_port(int line); - -#endif /* _NWPSERIAL_H */ diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 93ba148..3e5d757 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -176,7 +176,7 @@ #define PORT_S3C6400 84 -/* NWPSERIAL */ +/* NWPSERIAL, now removed */ #define PORT_NWPSERIAL 85 /* MAX3100 */ -- cgit v0.10.2 From 4e33870b3bb691996354a8f9e8f69458b4fc34d9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 16 Nov 2015 16:48:13 +0100 Subject: serial: of: CONFIG_SERIAL_8250 is always set The only other user of this code was the nwp-serial driver, but that is now gone, so we can remove a couple of #ifdef statments in this driver. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 920468b..d66fd24 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -21,10 +21,6 @@ #include #include -#ifdef CONFIG_SERIAL_8250_MODULE -#define CONFIG_SERIAL_8250 CONFIG_SERIAL_8250_MODULE -#endif - #include "8250/8250.h" struct of_serial_info { @@ -198,7 +194,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev) goto out; switch (port_type) { -#ifdef CONFIG_SERIAL_8250 case PORT_8250 ... PORT_MAX_8250: { struct uart_8250_port port8250; @@ -215,7 +210,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev) ret = serial8250_register_8250_port(&port8250); break; } -#endif default: /* need to add code for these */ case PORT_UNKNOWN: @@ -243,11 +237,9 @@ static int of_platform_serial_remove(struct platform_device *ofdev) { struct of_serial_info *info = platform_get_drvdata(ofdev); switch (info->type) { -#ifdef CONFIG_SERIAL_8250 case PORT_8250 ... PORT_MAX_8250: serial8250_unregister_port(info->line); break; -#endif default: /* need to add code for these */ break; @@ -260,7 +252,6 @@ static int of_platform_serial_remove(struct platform_device *ofdev) } #ifdef CONFIG_PM_SLEEP -#ifdef CONFIG_SERIAL_8250 static void of_serial_suspend_8250(struct of_serial_info *info) { struct uart_8250_port *port8250 = serial8250_get_port(info->line); @@ -281,15 +272,6 @@ static void of_serial_resume_8250(struct of_serial_info *info) serial8250_resume_port(info->line); } -#else -static inline void of_serial_suspend_8250(struct of_serial_info *info) -{ -} - -static inline void of_serial_resume_8250(struct of_serial_info *info) -{ -} -#endif static int of_serial_suspend(struct device *dev) { -- cgit v0.10.2 From afd7f88f157796e586fc99d62da13a54024e0731 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 16 Nov 2015 16:48:14 +0100 Subject: serial: 8250: move of_serial code to 8250 directory As the of-serial driver is now 8250 specific, we can move the file to a more appropriate place in teh 8250 subdirectory and adapt the Kconfig help text and file name. I'm leaving the CONFIG_SERIAL_OF_PLATFORM symbol unchanged to avoid breaking user configuration files unnecessarily. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c new file mode 100644 index 0000000..d66fd24 --- /dev/null +++ b/drivers/tty/serial/8250/8250_of.c @@ -0,0 +1,348 @@ +/* + * Serial Port driver for Open Firmware platform devices + * + * Copyright (C) 2006 Arnd Bergmann , IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "8250/8250.h" + +struct of_serial_info { + struct clk *clk; + int type; + int line; +}; + +#ifdef CONFIG_ARCH_TEGRA +void tegra_serial_handle_break(struct uart_port *p) +{ + unsigned int status, tmout = 10000; + + do { + status = p->serial_in(p, UART_LSR); + if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) + status = p->serial_in(p, UART_RX); + else + break; + if (--tmout == 0) + break; + udelay(1); + } while (1); +} +#else +static inline void tegra_serial_handle_break(struct uart_port *port) +{ +} +#endif + +/* + * Fill a struct uart_port for a given device node + */ +static int of_platform_serial_setup(struct platform_device *ofdev, + int type, struct uart_port *port, + struct of_serial_info *info) +{ + struct resource resource; + struct device_node *np = ofdev->dev.of_node; + u32 clk, spd, prop; + int ret; + + memset(port, 0, sizeof *port); + if (of_property_read_u32(np, "clock-frequency", &clk)) { + + /* Get clk rate through clk driver if present */ + info->clk = devm_clk_get(&ofdev->dev, NULL); + if (IS_ERR(info->clk)) { + dev_warn(&ofdev->dev, + "clk or clock-frequency not defined\n"); + return PTR_ERR(info->clk); + } + + ret = clk_prepare_enable(info->clk); + if (ret < 0) + return ret; + + clk = clk_get_rate(info->clk); + } + /* If current-speed was set, then try not to change it. */ + if (of_property_read_u32(np, "current-speed", &spd) == 0) + port->custom_divisor = clk / (16 * spd); + + ret = of_address_to_resource(np, 0, &resource); + if (ret) { + dev_warn(&ofdev->dev, "invalid address\n"); + goto out; + } + + spin_lock_init(&port->lock); + port->mapbase = resource.start; + port->mapsize = resource_size(&resource); + + /* Check for shifted address mapping */ + if (of_property_read_u32(np, "reg-offset", &prop) == 0) + port->mapbase += prop; + + /* Check for registers offset within the devices address range */ + if (of_property_read_u32(np, "reg-shift", &prop) == 0) + port->regshift = prop; + + /* Check for fifo size */ + if (of_property_read_u32(np, "fifo-size", &prop) == 0) + port->fifosize = prop; + + /* Check for a fixed line number */ + ret = of_alias_get_id(np, "serial"); + if (ret >= 0) + port->line = ret; + + port->irq = irq_of_parse_and_map(np, 0); + port->iotype = UPIO_MEM; + if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { + switch (prop) { + case 1: + port->iotype = UPIO_MEM; + break; + case 2: + port->iotype = UPIO_MEM16; + break; + case 4: + port->iotype = of_device_is_big_endian(np) ? + UPIO_MEM32BE : UPIO_MEM32; + break; + default: + dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n", + prop); + ret = -EINVAL; + goto out; + } + } + + port->type = type; + port->uartclk = clk; + port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP + | UPF_FIXED_PORT | UPF_FIXED_TYPE; + + if (of_find_property(np, "no-loopback-test", NULL)) + port->flags |= UPF_SKIP_TEST; + + port->dev = &ofdev->dev; + + switch (type) { + case PORT_TEGRA: + port->handle_break = tegra_serial_handle_break; + break; + + case PORT_RT2880: + port->iotype = UPIO_AU; + break; + } + + if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) && + (of_device_is_compatible(np, "fsl,ns16550") || + of_device_is_compatible(np, "fsl,16550-FIFO64"))) + port->handle_irq = fsl8250_handle_irq; + + return 0; +out: + if (info->clk) + clk_disable_unprepare(info->clk); + return ret; +} + +/* + * Try to register a serial port + */ +static const struct of_device_id of_platform_serial_table[]; +static int of_platform_serial_probe(struct platform_device *ofdev) +{ + const struct of_device_id *match; + struct of_serial_info *info; + struct uart_port port; + int port_type; + int ret; + + match = of_match_device(of_platform_serial_table, &ofdev->dev); + if (!match) + return -EINVAL; + + if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL)) + return -EBUSY; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (info == NULL) + return -ENOMEM; + + port_type = (unsigned long)match->data; + ret = of_platform_serial_setup(ofdev, port_type, &port, info); + if (ret) + goto out; + + switch (port_type) { + case PORT_8250 ... PORT_MAX_8250: + { + struct uart_8250_port port8250; + memset(&port8250, 0, sizeof(port8250)); + port8250.port = port; + + if (port.fifosize) + port8250.capabilities = UART_CAP_FIFO; + + if (of_property_read_bool(ofdev->dev.of_node, + "auto-flow-control")) + port8250.capabilities |= UART_CAP_AFE; + + ret = serial8250_register_8250_port(&port8250); + break; + } + default: + /* need to add code for these */ + case PORT_UNKNOWN: + dev_info(&ofdev->dev, "Unknown serial port found, ignored\n"); + ret = -ENODEV; + break; + } + if (ret < 0) + goto out; + + info->type = port_type; + info->line = ret; + platform_set_drvdata(ofdev, info); + return 0; +out: + kfree(info); + irq_dispose_mapping(port.irq); + return ret; +} + +/* + * Release a line + */ +static int of_platform_serial_remove(struct platform_device *ofdev) +{ + struct of_serial_info *info = platform_get_drvdata(ofdev); + switch (info->type) { + case PORT_8250 ... PORT_MAX_8250: + serial8250_unregister_port(info->line); + break; + default: + /* need to add code for these */ + break; + } + + if (info->clk) + clk_disable_unprepare(info->clk); + kfree(info); + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static void of_serial_suspend_8250(struct of_serial_info *info) +{ + struct uart_8250_port *port8250 = serial8250_get_port(info->line); + struct uart_port *port = &port8250->port; + + serial8250_suspend_port(info->line); + if (info->clk && (!uart_console(port) || console_suspend_enabled)) + clk_disable_unprepare(info->clk); +} + +static void of_serial_resume_8250(struct of_serial_info *info) +{ + struct uart_8250_port *port8250 = serial8250_get_port(info->line); + struct uart_port *port = &port8250->port; + + if (info->clk && (!uart_console(port) || console_suspend_enabled)) + clk_prepare_enable(info->clk); + + serial8250_resume_port(info->line); +} + +static int of_serial_suspend(struct device *dev) +{ + struct of_serial_info *info = dev_get_drvdata(dev); + + switch (info->type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_suspend_8250(info); + break; + default: + break; + } + + return 0; +} + +static int of_serial_resume(struct device *dev) +{ + struct of_serial_info *info = dev_get_drvdata(dev); + + switch (info->type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_resume_8250(info); + break; + default: + break; + } + + return 0; +} +#endif +static SIMPLE_DEV_PM_OPS(of_serial_pm_ops, of_serial_suspend, of_serial_resume); + +/* + * A few common types, add more as needed. + */ +static const struct of_device_id of_platform_serial_table[] = { + { .compatible = "ns8250", .data = (void *)PORT_8250, }, + { .compatible = "ns16450", .data = (void *)PORT_16450, }, + { .compatible = "ns16550a", .data = (void *)PORT_16550A, }, + { .compatible = "ns16550", .data = (void *)PORT_16550, }, + { .compatible = "ns16750", .data = (void *)PORT_16750, }, + { .compatible = "ns16850", .data = (void *)PORT_16850, }, + { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, + { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, }, + { .compatible = "ralink,rt2880-uart", .data = (void *)PORT_RT2880, }, + { .compatible = "altr,16550-FIFO32", + .data = (void *)PORT_ALTR_16550_F32, }, + { .compatible = "altr,16550-FIFO64", + .data = (void *)PORT_ALTR_16550_F64, }, + { .compatible = "altr,16550-FIFO128", + .data = (void *)PORT_ALTR_16550_F128, }, + { .compatible = "mrvl,mmp-uart", + .data = (void *)PORT_XSCALE, }, + { .compatible = "mrvl,pxa-uart", + .data = (void *)PORT_XSCALE, }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, of_platform_serial_table); + +static struct platform_driver of_platform_serial_driver = { + .driver = { + .name = "of_serial", + .of_match_table = of_platform_serial_table, + }, + .probe = of_platform_serial_probe, + .remove = of_platform_serial_remove, +}; + +module_platform_driver(of_platform_serial_driver); + +MODULE_AUTHOR("Arnd Bergmann "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Serial Port driver for Open Firmware platform devices"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 25da430..54f8af8 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -377,3 +377,12 @@ config SERIAL_8250_MID Selecting this option will enable handling of the extra features present on the UART found on Intel Medfield SOC and various other Intel platforms. + +config SERIAL_OF_PLATFORM + tristate "Devicetree based probing for 8250 ports" + depends on SERIAL_8250 && OF + help + This option is used for all 8250 compatible serial ports that + are probed through devicetree, including Open Firmware based + PowerPC systems and embedded systems on architectures using the + flattened device tree format. diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index e177f86..4ecb80d 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -28,5 +28,6 @@ obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o +obj-$(CONFIG_SERIAL_8250_OF) += 8250_of.o CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 643fc50..0bdf4d5 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1096,16 +1096,6 @@ config SERIAL_NETX_CONSOLE If you have enabled the serial port on the Hilscher NetX SoC you can make it the console by answering Y to this option. -config SERIAL_OF_PLATFORM - tristate "Serial port on Open Firmware platform bus" - depends on OF - depends on SERIAL_8250 - help - If you have a PowerPC based system that has serial ports - on a platform specific bus, you should enable this option. - Currently, only 8250 compatible ports are supported, but - others can easily be added. - config SERIAL_OMAP tristate "OMAP serial port support" depends on ARCH_OMAP2PLUS diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index ee88933..b391c9b 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -63,7 +63,6 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_MSM) += msm_serial.o obj-$(CONFIG_SERIAL_NETX) += netx-serial.o -obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c deleted file mode 100644 index d66fd24..0000000 --- a/drivers/tty/serial/of_serial.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Serial Port driver for Open Firmware platform devices - * - * Copyright (C) 2006 Arnd Bergmann , IBM Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "8250/8250.h" - -struct of_serial_info { - struct clk *clk; - int type; - int line; -}; - -#ifdef CONFIG_ARCH_TEGRA -void tegra_serial_handle_break(struct uart_port *p) -{ - unsigned int status, tmout = 10000; - - do { - status = p->serial_in(p, UART_LSR); - if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) - status = p->serial_in(p, UART_RX); - else - break; - if (--tmout == 0) - break; - udelay(1); - } while (1); -} -#else -static inline void tegra_serial_handle_break(struct uart_port *port) -{ -} -#endif - -/* - * Fill a struct uart_port for a given device node - */ -static int of_platform_serial_setup(struct platform_device *ofdev, - int type, struct uart_port *port, - struct of_serial_info *info) -{ - struct resource resource; - struct device_node *np = ofdev->dev.of_node; - u32 clk, spd, prop; - int ret; - - memset(port, 0, sizeof *port); - if (of_property_read_u32(np, "clock-frequency", &clk)) { - - /* Get clk rate through clk driver if present */ - info->clk = devm_clk_get(&ofdev->dev, NULL); - if (IS_ERR(info->clk)) { - dev_warn(&ofdev->dev, - "clk or clock-frequency not defined\n"); - return PTR_ERR(info->clk); - } - - ret = clk_prepare_enable(info->clk); - if (ret < 0) - return ret; - - clk = clk_get_rate(info->clk); - } - /* If current-speed was set, then try not to change it. */ - if (of_property_read_u32(np, "current-speed", &spd) == 0) - port->custom_divisor = clk / (16 * spd); - - ret = of_address_to_resource(np, 0, &resource); - if (ret) { - dev_warn(&ofdev->dev, "invalid address\n"); - goto out; - } - - spin_lock_init(&port->lock); - port->mapbase = resource.start; - port->mapsize = resource_size(&resource); - - /* Check for shifted address mapping */ - if (of_property_read_u32(np, "reg-offset", &prop) == 0) - port->mapbase += prop; - - /* Check for registers offset within the devices address range */ - if (of_property_read_u32(np, "reg-shift", &prop) == 0) - port->regshift = prop; - - /* Check for fifo size */ - if (of_property_read_u32(np, "fifo-size", &prop) == 0) - port->fifosize = prop; - - /* Check for a fixed line number */ - ret = of_alias_get_id(np, "serial"); - if (ret >= 0) - port->line = ret; - - port->irq = irq_of_parse_and_map(np, 0); - port->iotype = UPIO_MEM; - if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { - switch (prop) { - case 1: - port->iotype = UPIO_MEM; - break; - case 2: - port->iotype = UPIO_MEM16; - break; - case 4: - port->iotype = of_device_is_big_endian(np) ? - UPIO_MEM32BE : UPIO_MEM32; - break; - default: - dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n", - prop); - ret = -EINVAL; - goto out; - } - } - - port->type = type; - port->uartclk = clk; - port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP - | UPF_FIXED_PORT | UPF_FIXED_TYPE; - - if (of_find_property(np, "no-loopback-test", NULL)) - port->flags |= UPF_SKIP_TEST; - - port->dev = &ofdev->dev; - - switch (type) { - case PORT_TEGRA: - port->handle_break = tegra_serial_handle_break; - break; - - case PORT_RT2880: - port->iotype = UPIO_AU; - break; - } - - if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) && - (of_device_is_compatible(np, "fsl,ns16550") || - of_device_is_compatible(np, "fsl,16550-FIFO64"))) - port->handle_irq = fsl8250_handle_irq; - - return 0; -out: - if (info->clk) - clk_disable_unprepare(info->clk); - return ret; -} - -/* - * Try to register a serial port - */ -static const struct of_device_id of_platform_serial_table[]; -static int of_platform_serial_probe(struct platform_device *ofdev) -{ - const struct of_device_id *match; - struct of_serial_info *info; - struct uart_port port; - int port_type; - int ret; - - match = of_match_device(of_platform_serial_table, &ofdev->dev); - if (!match) - return -EINVAL; - - if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL)) - return -EBUSY; - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (info == NULL) - return -ENOMEM; - - port_type = (unsigned long)match->data; - ret = of_platform_serial_setup(ofdev, port_type, &port, info); - if (ret) - goto out; - - switch (port_type) { - case PORT_8250 ... PORT_MAX_8250: - { - struct uart_8250_port port8250; - memset(&port8250, 0, sizeof(port8250)); - port8250.port = port; - - if (port.fifosize) - port8250.capabilities = UART_CAP_FIFO; - - if (of_property_read_bool(ofdev->dev.of_node, - "auto-flow-control")) - port8250.capabilities |= UART_CAP_AFE; - - ret = serial8250_register_8250_port(&port8250); - break; - } - default: - /* need to add code for these */ - case PORT_UNKNOWN: - dev_info(&ofdev->dev, "Unknown serial port found, ignored\n"); - ret = -ENODEV; - break; - } - if (ret < 0) - goto out; - - info->type = port_type; - info->line = ret; - platform_set_drvdata(ofdev, info); - return 0; -out: - kfree(info); - irq_dispose_mapping(port.irq); - return ret; -} - -/* - * Release a line - */ -static int of_platform_serial_remove(struct platform_device *ofdev) -{ - struct of_serial_info *info = platform_get_drvdata(ofdev); - switch (info->type) { - case PORT_8250 ... PORT_MAX_8250: - serial8250_unregister_port(info->line); - break; - default: - /* need to add code for these */ - break; - } - - if (info->clk) - clk_disable_unprepare(info->clk); - kfree(info); - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static void of_serial_suspend_8250(struct of_serial_info *info) -{ - struct uart_8250_port *port8250 = serial8250_get_port(info->line); - struct uart_port *port = &port8250->port; - - serial8250_suspend_port(info->line); - if (info->clk && (!uart_console(port) || console_suspend_enabled)) - clk_disable_unprepare(info->clk); -} - -static void of_serial_resume_8250(struct of_serial_info *info) -{ - struct uart_8250_port *port8250 = serial8250_get_port(info->line); - struct uart_port *port = &port8250->port; - - if (info->clk && (!uart_console(port) || console_suspend_enabled)) - clk_prepare_enable(info->clk); - - serial8250_resume_port(info->line); -} - -static int of_serial_suspend(struct device *dev) -{ - struct of_serial_info *info = dev_get_drvdata(dev); - - switch (info->type) { - case PORT_8250 ... PORT_MAX_8250: - of_serial_suspend_8250(info); - break; - default: - break; - } - - return 0; -} - -static int of_serial_resume(struct device *dev) -{ - struct of_serial_info *info = dev_get_drvdata(dev); - - switch (info->type) { - case PORT_8250 ... PORT_MAX_8250: - of_serial_resume_8250(info); - break; - default: - break; - } - - return 0; -} -#endif -static SIMPLE_DEV_PM_OPS(of_serial_pm_ops, of_serial_suspend, of_serial_resume); - -/* - * A few common types, add more as needed. - */ -static const struct of_device_id of_platform_serial_table[] = { - { .compatible = "ns8250", .data = (void *)PORT_8250, }, - { .compatible = "ns16450", .data = (void *)PORT_16450, }, - { .compatible = "ns16550a", .data = (void *)PORT_16550A, }, - { .compatible = "ns16550", .data = (void *)PORT_16550, }, - { .compatible = "ns16750", .data = (void *)PORT_16750, }, - { .compatible = "ns16850", .data = (void *)PORT_16850, }, - { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, - { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, }, - { .compatible = "ralink,rt2880-uart", .data = (void *)PORT_RT2880, }, - { .compatible = "altr,16550-FIFO32", - .data = (void *)PORT_ALTR_16550_F32, }, - { .compatible = "altr,16550-FIFO64", - .data = (void *)PORT_ALTR_16550_F64, }, - { .compatible = "altr,16550-FIFO128", - .data = (void *)PORT_ALTR_16550_F128, }, - { .compatible = "mrvl,mmp-uart", - .data = (void *)PORT_XSCALE, }, - { .compatible = "mrvl,pxa-uart", - .data = (void *)PORT_XSCALE, }, - { /* end of list */ }, -}; -MODULE_DEVICE_TABLE(of, of_platform_serial_table); - -static struct platform_driver of_platform_serial_driver = { - .driver = { - .name = "of_serial", - .of_match_table = of_platform_serial_table, - }, - .probe = of_platform_serial_probe, - .remove = of_platform_serial_remove, -}; - -module_platform_driver(of_platform_serial_driver); - -MODULE_AUTHOR("Arnd Bergmann "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Serial Port driver for Open Firmware platform devices"); -- cgit v0.10.2 From 679e7c2999f963e542c6f4c3d3c9a0688b5d3587 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 27 Nov 2015 14:11:02 -0500 Subject: n_tty: Uninline tty_copy_to_user() Merge the multiple tty_copy_to_user() calls into a single copy sequence within tty_copy_to_user(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index c37c15d..b2b01d5 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -162,12 +162,23 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x, return put_user(x, ptr); } -static inline int tty_copy_to_user(struct tty_struct *tty, - void __user *to, - const void *from, - unsigned long n) +static int tty_copy_to_user(struct tty_struct *tty, void __user *to, + size_t tail, size_t n) { struct n_tty_data *ldata = tty->disc_data; + size_t size = N_TTY_BUF_SIZE - tail; + const void *from = read_buf_addr(ldata, tail); + int uncopied; + + if (n > size) { + tty_audit_add_data(tty, from, size, ldata->icanon); + uncopied = copy_to_user(to, from, size); + if (uncopied) + return uncopied; + to += size; + n -= size; + from = ldata->read_buf; + } tty_audit_add_data(tty, from, n, ldata->icanon); return copy_to_user(to, from, n); @@ -2074,7 +2085,6 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, } else if (eol != size) found = 1; - size = N_TTY_BUF_SIZE - tail; n = eol - tail; if (n > N_TTY_BUF_SIZE) n += N_TTY_BUF_SIZE; @@ -2086,17 +2096,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, eof_push = !n && ldata->read_tail != ldata->line_start; } - n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n", - __func__, eol, found, n, c, size, more); - - if (n > size) { - ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), size); - if (ret) - return -EFAULT; - ret = tty_copy_to_user(tty, *b + size, ldata->read_buf, n - size); - } else - ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), n); + n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n", + __func__, eol, found, n, c, tail, more); + ret = tty_copy_to_user(tty, *b, tail, n); if (ret) return -EFAULT; *b += n; -- cgit v0.10.2 From e661cf702003030daf2001cb88eb586300a18ee4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 27 Nov 2015 14:11:03 -0500 Subject: n_tty: Clarify copy_from_read_buf() Add a temporary for the computed source address and substitute where appropriate. No functional change. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index b2b01d5..bc613b8 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2014,11 +2014,11 @@ static int copy_from_read_buf(struct tty_struct *tty, n = min(head - ldata->read_tail, N_TTY_BUF_SIZE - tail); n = min(*nr, n); if (n) { - retval = copy_to_user(*b, read_buf_addr(ldata, tail), n); + const unsigned char *from = read_buf_addr(ldata, tail); + retval = copy_to_user(*b, from, n); n -= retval; - is_eof = n == 1 && read_buf(ldata, tail) == EOF_CHAR(tty); - tty_audit_add_data(tty, read_buf_addr(ldata, tail), n, - ldata->icanon); + is_eof = n == 1 && *from == EOF_CHAR(tty); + tty_audit_add_data(tty, from, n, ldata->icanon); smp_store_release(&ldata->read_tail, ldata->read_tail + n); /* Turn single EOF into zero-length read */ if (L_EXTPROC(tty) && ldata->icanon && is_eof && -- cgit v0.10.2 From b985e9e368f0db4fee940ad86197f413779d4b63 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 27 Nov 2015 14:11:04 -0500 Subject: n_tty: Reduce branching in canon_copy_from_read_buf() Instead of compare-and-set, just compute 'found'. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index bc613b8..f2f6425 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2080,10 +2080,9 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, if (eol == N_TTY_BUF_SIZE && more) { /* scan wrapped without finding set bit */ eol = find_next_bit(ldata->read_flags, more, 0); - if (eol != more) - found = 1; - } else if (eol != size) - found = 1; + found = eol != more; + } else + found = eol != size; n = eol - tail; if (n > N_TTY_BUF_SIZE) -- cgit v0.10.2 From debb7f64f9bab5cd0d06b7ce1695f15c5c9304d0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 16 Nov 2015 17:40:26 +0000 Subject: tty: amba-pl011: add register lookup table Add a register lookup table, which allows the register offsets to be adjusted on a per-port basis. Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 62b9cb2..29526a1 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -73,6 +73,34 @@ #define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE) #define UART_DUMMY_DR_RX (1 << 16) +static u16 pl011_std_offsets[REG_ARRAY_SIZE] = { + [REG_DR] = UART01x_DR, + [REG_ST_DMAWM] = ST_UART011_DMAWM, + [REG_ST_TIMEOUT] = ST_UART011_TIMEOUT, + [REG_FR] = UART01x_FR, + [REG_ST_LCRH_RX] = ST_UART011_LCRH_RX, + [REG_IBRD] = UART011_IBRD, + [REG_FBRD] = UART011_FBRD, + [REG_LCRH] = UART011_LCRH, + [REG_ST_LCRH_TX] = ST_UART011_LCRH_TX, + [REG_CR] = UART011_CR, + [REG_IFLS] = UART011_IFLS, + [REG_IMSC] = UART011_IMSC, + [REG_RIS] = UART011_RIS, + [REG_MIS] = UART011_MIS, + [REG_ICR] = UART011_ICR, + [REG_DMACR] = UART011_DMACR, + [REG_ST_XFCR] = ST_UART011_XFCR, + [REG_ST_XON1] = ST_UART011_XON1, + [REG_ST_XON2] = ST_UART011_XON2, + [REG_ST_XOFF1] = ST_UART011_XOFF1, + [REG_ST_XOFF2] = ST_UART011_XOFF2, + [REG_ST_ITCR] = ST_UART011_ITCR, + [REG_ST_ITIP] = ST_UART011_ITIP, + [REG_ST_ABCR] = ST_UART011_ABCR, + [REG_ST_ABIMSC] = ST_UART011_ABIMSC, +}; + /* There is by now at least one vendor with differing details, so handle it */ struct vendor_data { unsigned int ifls; @@ -164,6 +192,7 @@ struct pl011_dmatx_data { */ struct uart_amba_port { struct uart_port port; + const u16 *reg_offset; struct clk *clk; const struct vendor_data *vendor; unsigned int dmacr; /* dma control reg */ @@ -189,7 +218,7 @@ struct uart_amba_port { static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap, unsigned int reg) { - return reg; + return uap->reg_offset[reg]; } static unsigned int pl011_read(const struct uart_amba_port *uap, @@ -2397,6 +2426,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) if (IS_ERR(uap->clk)) return PTR_ERR(uap->clk); + uap->reg_offset = pl011_std_offsets; uap->vendor = vendor; uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; @@ -2478,6 +2508,7 @@ static int sbsa_uart_probe(struct platform_device *pdev) if (!uap) return -ENOMEM; + uap->reg_offset = pl011_std_offsets; uap->vendor = &vendor_sbsa; uap->fifosize = 32; uap->port.irq = platform_get_irq(pdev, 0); diff --git a/drivers/tty/serial/amba-pl011.h b/drivers/tty/serial/amba-pl011.h index b7eb1bc..0c6756d 100644 --- a/drivers/tty/serial/amba-pl011.h +++ b/drivers/tty/serial/amba-pl011.h @@ -2,31 +2,34 @@ #define AMBA_PL011_H enum { - REG_DR = UART01x_DR, - REG_ST_DMAWM = ST_UART011_DMAWM, - REG_ST_TIMEOUT = ST_UART011_TIMEOUT, - REG_FR = UART01x_FR, - REG_ST_LCRH_RX = ST_UART011_LCRH_RX, - REG_IBRD = UART011_IBRD, - REG_FBRD = UART011_FBRD, - REG_LCRH = UART011_LCRH, - REG_ST_LCRH_TX = ST_UART011_LCRH_TX, - REG_CR = UART011_CR, - REG_IFLS = UART011_IFLS, - REG_IMSC = UART011_IMSC, - REG_RIS = UART011_RIS, - REG_MIS = UART011_MIS, - REG_ICR = UART011_ICR, - REG_DMACR = UART011_DMACR, - REG_ST_XFCR = ST_UART011_XFCR, - REG_ST_XON1 = ST_UART011_XON1, - REG_ST_XON2 = ST_UART011_XON2, - REG_ST_XOFF1 = ST_UART011_XOFF1, - REG_ST_XOFF2 = ST_UART011_XOFF2, - REG_ST_ITCR = ST_UART011_ITCR, - REG_ST_ITIP = ST_UART011_ITIP, - REG_ST_ABCR = ST_UART011_ABCR, - REG_ST_ABIMSC = ST_UART011_ABIMSC, + REG_DR, + REG_ST_DMAWM, + REG_ST_TIMEOUT, + REG_FR, + REG_ST_LCRH_RX, + REG_IBRD, + REG_FBRD, + REG_LCRH, + REG_ST_LCRH_TX, + REG_CR, + REG_IFLS, + REG_IMSC, + REG_RIS, + REG_MIS, + REG_ICR, + REG_DMACR, + REG_ST_XFCR, + REG_ST_XON1, + REG_ST_XON2, + REG_ST_XOFF1, + REG_ST_XOFF2, + REG_ST_ITCR, + REG_ST_ITIP, + REG_ST_ABCR, + REG_ST_ABIMSC, + + /* The size of the array - must be last */ + REG_ARRAY_SIZE, }; #endif -- cgit v0.10.2 From 439403bde9fc9e655237d87fc44381f49025ea4f Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 16 Nov 2015 17:40:31 +0000 Subject: tty: amba-pl011: add register offset table to vendor data Add the register offset table to the vendor data, allowing vendor differences to be described in this table. Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 29526a1..4c12207 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -103,6 +103,7 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = { /* There is by now at least one vendor with differing details, so handle it */ struct vendor_data { + const u16 *reg_offset; unsigned int ifls; unsigned int lcrh_tx; unsigned int lcrh_rx; @@ -121,6 +122,7 @@ static unsigned int get_fifosize_arm(struct amba_device *dev) } static struct vendor_data vendor_arm = { + .reg_offset = pl011_std_offsets, .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, .lcrh_tx = REG_LCRH, .lcrh_rx = REG_LCRH, @@ -133,6 +135,7 @@ static struct vendor_data vendor_arm = { }; static struct vendor_data vendor_sbsa = { + .reg_offset = pl011_std_offsets, .oversampling = false, .dma_threshold = false, .cts_event_workaround = false, @@ -146,6 +149,7 @@ static unsigned int get_fifosize_st(struct amba_device *dev) } static struct vendor_data vendor_st = { + .reg_offset = pl011_std_offsets, .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, .lcrh_tx = REG_ST_LCRH_TX, .lcrh_rx = REG_ST_LCRH_RX, @@ -2426,7 +2430,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) if (IS_ERR(uap->clk)) return PTR_ERR(uap->clk); - uap->reg_offset = pl011_std_offsets; + uap->reg_offset = vendor->reg_offset; uap->vendor = vendor; uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; @@ -2508,7 +2512,7 @@ static int sbsa_uart_probe(struct platform_device *pdev) if (!uap) return -ENOMEM; - uap->reg_offset = pl011_std_offsets; + uap->reg_offset = vendor_sbsa.reg_offset; uap->vendor = &vendor_sbsa; uap->fifosize = 32; uap->port.irq = platform_get_irq(pdev, 0); -- cgit v0.10.2 From bf69ff8a24358521f113b5c13f271681a74dd2a9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 16 Nov 2015 17:40:36 +0000 Subject: tty: amba-pl011: add ST register offset table Add the ST variant register offset table to the driver. Currently, this is an identical copy of the standard version, but this will be modified in the following changes. Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 4c12207..c4adece 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -143,13 +143,41 @@ static struct vendor_data vendor_sbsa = { .fixed_options = true, }; +static u16 pl011_st_offsets[REG_ARRAY_SIZE] = { + [REG_DR] = UART01x_DR, + [REG_ST_DMAWM] = ST_UART011_DMAWM, + [REG_ST_TIMEOUT] = ST_UART011_TIMEOUT, + [REG_FR] = UART01x_FR, + [REG_ST_LCRH_RX] = ST_UART011_LCRH_RX, + [REG_IBRD] = UART011_IBRD, + [REG_FBRD] = UART011_FBRD, + [REG_LCRH] = UART011_LCRH, + [REG_ST_LCRH_TX] = ST_UART011_LCRH_TX, + [REG_CR] = UART011_CR, + [REG_IFLS] = UART011_IFLS, + [REG_IMSC] = UART011_IMSC, + [REG_RIS] = UART011_RIS, + [REG_MIS] = UART011_MIS, + [REG_ICR] = UART011_ICR, + [REG_DMACR] = UART011_DMACR, + [REG_ST_XFCR] = ST_UART011_XFCR, + [REG_ST_XON1] = ST_UART011_XON1, + [REG_ST_XON2] = ST_UART011_XON2, + [REG_ST_XOFF1] = ST_UART011_XOFF1, + [REG_ST_XOFF2] = ST_UART011_XOFF2, + [REG_ST_ITCR] = ST_UART011_ITCR, + [REG_ST_ITIP] = ST_UART011_ITIP, + [REG_ST_ABCR] = ST_UART011_ABCR, + [REG_ST_ABIMSC] = ST_UART011_ABIMSC, +}; + static unsigned int get_fifosize_st(struct amba_device *dev) { return 64; } static struct vendor_data vendor_st = { - .reg_offset = pl011_std_offsets, + .reg_offset = pl011_st_offsets, .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, .lcrh_tx = REG_ST_LCRH_TX, .lcrh_rx = REG_ST_LCRH_RX, -- cgit v0.10.2 From e4df9a8053f24b6f37cf11aca793a8deeca88caf Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 16 Nov 2015 17:40:41 +0000 Subject: tty: amba-pl011: clean up LCR register offsets As we can detect when the LCR register is split between TX and RX, we don't need three entries in the table to deal with this. Reduce this down to two entries by converting the REG_ST_LCRH_* entries to standard REG_LCRH_* and remove REG_LCRH. Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c4adece..88ff97e 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -78,11 +78,10 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = { [REG_ST_DMAWM] = ST_UART011_DMAWM, [REG_ST_TIMEOUT] = ST_UART011_TIMEOUT, [REG_FR] = UART01x_FR, - [REG_ST_LCRH_RX] = ST_UART011_LCRH_RX, + [REG_LCRH_RX] = UART011_LCRH, + [REG_LCRH_TX] = UART011_LCRH, [REG_IBRD] = UART011_IBRD, [REG_FBRD] = UART011_FBRD, - [REG_LCRH] = UART011_LCRH, - [REG_ST_LCRH_TX] = ST_UART011_LCRH_TX, [REG_CR] = UART011_CR, [REG_IFLS] = UART011_IFLS, [REG_IMSC] = UART011_IMSC, @@ -105,8 +104,6 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = { struct vendor_data { const u16 *reg_offset; unsigned int ifls; - unsigned int lcrh_tx; - unsigned int lcrh_rx; bool oversampling; bool dma_threshold; bool cts_event_workaround; @@ -124,8 +121,6 @@ static unsigned int get_fifosize_arm(struct amba_device *dev) static struct vendor_data vendor_arm = { .reg_offset = pl011_std_offsets, .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, - .lcrh_tx = REG_LCRH, - .lcrh_rx = REG_LCRH, .oversampling = false, .dma_threshold = false, .cts_event_workaround = false, @@ -148,11 +143,10 @@ static u16 pl011_st_offsets[REG_ARRAY_SIZE] = { [REG_ST_DMAWM] = ST_UART011_DMAWM, [REG_ST_TIMEOUT] = ST_UART011_TIMEOUT, [REG_FR] = UART01x_FR, - [REG_ST_LCRH_RX] = ST_UART011_LCRH_RX, + [REG_LCRH_RX] = ST_UART011_LCRH_RX, + [REG_LCRH_TX] = ST_UART011_LCRH_TX, [REG_IBRD] = UART011_IBRD, [REG_FBRD] = UART011_FBRD, - [REG_LCRH] = UART011_LCRH, - [REG_ST_LCRH_TX] = ST_UART011_LCRH_TX, [REG_CR] = UART011_CR, [REG_IFLS] = UART011_IFLS, [REG_IMSC] = UART011_IMSC, @@ -179,8 +173,6 @@ static unsigned int get_fifosize_st(struct amba_device *dev) static struct vendor_data vendor_st = { .reg_offset = pl011_st_offsets, .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, - .lcrh_tx = REG_ST_LCRH_TX, - .lcrh_rx = REG_ST_LCRH_RX, .oversampling = true, .dma_threshold = true, .cts_event_workaround = true, @@ -231,8 +223,6 @@ struct uart_amba_port { unsigned int im; /* interrupt mask */ unsigned int old_status; unsigned int fifosize; /* vendor-specific */ - unsigned int lcrh_tx; /* vendor-specific */ - unsigned int lcrh_rx; /* vendor-specific */ unsigned int old_cr; /* state during shutdown */ bool autorts; unsigned int fixed_baud; /* vendor-set fixed baud rate */ @@ -1540,12 +1530,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) unsigned int lcr_h; spin_lock_irqsave(&uap->port.lock, flags); - lcr_h = pl011_read(uap, uap->lcrh_tx); + lcr_h = pl011_read(uap, REG_LCRH_TX); if (break_state == -1) lcr_h |= UART01x_LCRH_BRK; else lcr_h &= ~UART01x_LCRH_BRK; - pl011_write(lcr_h, uap, uap->lcrh_tx); + pl011_write(lcr_h, uap, REG_LCRH_TX); spin_unlock_irqrestore(&uap->port.lock, flags); } @@ -1649,13 +1639,13 @@ static int pl011_hwinit(struct uart_port *port) static bool pl011_split_lcrh(const struct uart_amba_port *uap) { - return pl011_reg_to_offset(uap, uap->lcrh_rx) != - pl011_reg_to_offset(uap, uap->lcrh_tx); + return pl011_reg_to_offset(uap, REG_LCRH_RX) != + pl011_reg_to_offset(uap, REG_LCRH_TX); } static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) { - pl011_write(lcr_h, uap, uap->lcrh_rx); + pl011_write(lcr_h, uap, REG_LCRH_RX); if (pl011_split_lcrh(uap)) { int i; /* @@ -1664,7 +1654,7 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) */ for (i = 0; i < 10; ++i) pl011_write(0xff, uap, REG_MIS); - pl011_write(lcr_h, uap, uap->lcrh_tx); + pl011_write(lcr_h, uap, REG_LCRH_TX); } } @@ -1789,9 +1779,9 @@ static void pl011_disable_uart(struct uart_amba_port *uap) /* * disable break condition and fifos */ - pl011_shutdown_channel(uap, uap->lcrh_rx); + pl011_shutdown_channel(uap, REG_LCRH_RX); if (pl011_split_lcrh(uap)) - pl011_shutdown_channel(uap, uap->lcrh_tx); + pl011_shutdown_channel(uap, REG_LCRH_TX); } static void pl011_disable_interrupts(struct uart_amba_port *uap) @@ -1992,7 +1982,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, /* * ----------v----------v----------v----------v----- - * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER + * NOTE: REG_LCRH_TX and REG_LCRH_RX MUST BE WRITTEN AFTER * REG_FBRD & REG_IBRD. * ----------^----------^----------^----------^----- */ @@ -2197,7 +2187,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud, if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) { unsigned int lcr_h, ibrd, fbrd; - lcr_h = pl011_read(uap, uap->lcrh_tx); + lcr_h = pl011_read(uap, REG_LCRH_TX); *parity = 'n'; if (lcr_h & UART01x_LCRH_PEN) { @@ -2460,8 +2450,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->reg_offset = vendor->reg_offset; uap->vendor = vendor; - uap->lcrh_rx = vendor->lcrh_rx; - uap->lcrh_tx = vendor->lcrh_tx; uap->fifosize = vendor->get_fifosize(dev); uap->port.irq = dev->irq[0]; uap->port.ops = &amba_pl011_pops; diff --git a/drivers/tty/serial/amba-pl011.h b/drivers/tty/serial/amba-pl011.h index 0c6756d..411c60e 100644 --- a/drivers/tty/serial/amba-pl011.h +++ b/drivers/tty/serial/amba-pl011.h @@ -6,11 +6,10 @@ enum { REG_ST_DMAWM, REG_ST_TIMEOUT, REG_FR, - REG_ST_LCRH_RX, + REG_LCRH_RX, + REG_LCRH_TX, REG_IBRD, REG_FBRD, - REG_LCRH, - REG_ST_LCRH_TX, REG_CR, REG_IFLS, REG_IMSC, -- cgit v0.10.2 From 10004a66240d7660179ccff9ac301926e783c76c Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 16 Nov 2015 17:40:47 +0000 Subject: tty: amba-pl011: remove ST micro registers from standard table Remove the ST micro registers from the standard table. These registers should never be accessed in non-ST micro variants. Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 88ff97e..e0f9e3e 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -75,8 +75,6 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = { [REG_DR] = UART01x_DR, - [REG_ST_DMAWM] = ST_UART011_DMAWM, - [REG_ST_TIMEOUT] = ST_UART011_TIMEOUT, [REG_FR] = UART01x_FR, [REG_LCRH_RX] = UART011_LCRH, [REG_LCRH_TX] = UART011_LCRH, @@ -89,15 +87,6 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = { [REG_MIS] = UART011_MIS, [REG_ICR] = UART011_ICR, [REG_DMACR] = UART011_DMACR, - [REG_ST_XFCR] = ST_UART011_XFCR, - [REG_ST_XON1] = ST_UART011_XON1, - [REG_ST_XON2] = ST_UART011_XON2, - [REG_ST_XOFF1] = ST_UART011_XOFF1, - [REG_ST_XOFF2] = ST_UART011_XOFF2, - [REG_ST_ITCR] = ST_UART011_ITCR, - [REG_ST_ITIP] = ST_UART011_ITIP, - [REG_ST_ABCR] = ST_UART011_ABCR, - [REG_ST_ABIMSC] = ST_UART011_ABIMSC, }; /* There is by now at least one vendor with differing details, so handle it */ -- cgit v0.10.2 From 84c3e03bdd1146191b7222ed62a08512199a45c7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 16 Nov 2015 17:40:52 +0000 Subject: tty: amba-pl011: add support for 32-bit register access Add support for 32-bit register accesses to the AMBA PL011 UART. This is needed for ZTE UARTs, which require 32-bit accesses as opposed to the more normal 16-bit accesses. Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index e0f9e3e..c8165b6 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -93,6 +93,7 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = { struct vendor_data { const u16 *reg_offset; unsigned int ifls; + bool access_32b; bool oversampling; bool dma_threshold; bool cts_event_workaround; @@ -214,6 +215,7 @@ struct uart_amba_port { unsigned int fifosize; /* vendor-specific */ unsigned int old_cr; /* state during shutdown */ bool autorts; + bool access_32b; unsigned int fixed_baud; /* vendor-set fixed baud rate */ char type[12]; #ifdef CONFIG_DMA_ENGINE @@ -235,13 +237,20 @@ static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap, static unsigned int pl011_read(const struct uart_amba_port *uap, unsigned int reg) { - return readw(uap->port.membase + pl011_reg_to_offset(uap, reg)); + void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg); + + return uap->access_32b ? readl(addr) : readw(addr); } static void pl011_write(unsigned int val, const struct uart_amba_port *uap, unsigned int reg) { - writew(val, uap->port.membase + pl011_reg_to_offset(uap, reg)); + void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg); + + if (uap->access_32b) + writel(val, addr); + else + writew(val, addr); } /* @@ -2438,6 +2447,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) return PTR_ERR(uap->clk); uap->reg_offset = vendor->reg_offset; + uap->access_32b = vendor->access_32b; uap->vendor = vendor; uap->fifosize = vendor->get_fifosize(dev); uap->port.irq = dev->irq[0]; @@ -2518,6 +2528,7 @@ static int sbsa_uart_probe(struct platform_device *pdev) return -ENOMEM; uap->reg_offset = vendor_sbsa.reg_offset; + uap->access_32b = vendor_sbsa.access_32b; uap->vendor = &vendor_sbsa; uap->fifosize = 32; uap->port.irq = platform_get_irq(pdev, 0); -- cgit v0.10.2 From 7ec758718920e5e5876d0d02ece6855128c8eb1e Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 16 Nov 2015 17:40:57 +0000 Subject: tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL) Add (incomplete) support for the ZTE UART to the AMBA PL011 driver. This is similar to the ARM and ST variants, except it has a different register address layout, and requires 32-bit accesses to the registers. Use the newly introduced register tables and access size support to cope with these differences. Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c8165b6..295f0be 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -171,6 +171,29 @@ static struct vendor_data vendor_st = { .get_fifosize = get_fifosize_st, }; +static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = { + [REG_DR] = ZX_UART011_DR, + [REG_FR] = ZX_UART011_FR, + [REG_LCRH_RX] = ZX_UART011_LCRH, + [REG_LCRH_TX] = ZX_UART011_LCRH, + [REG_IBRD] = ZX_UART011_IBRD, + [REG_FBRD] = ZX_UART011_FBRD, + [REG_CR] = ZX_UART011_CR, + [REG_IFLS] = ZX_UART011_IFLS, + [REG_IMSC] = ZX_UART011_IMSC, + [REG_RIS] = ZX_UART011_RIS, + [REG_MIS] = ZX_UART011_MIS, + [REG_ICR] = ZX_UART011_ICR, + [REG_DMACR] = ZX_UART011_DMACR, +}; + +static struct vendor_data vendor_zte = { + .reg_offset = pl011_zte_offsets, + .access_32b = true, + .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, + .get_fifosize = get_fifosize_arm, +}; + /* Deals with DMA transactions */ struct pl011_sgbuf { diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h index 0ddb5c0..d76a19b 100644 --- a/include/linux/amba/serial.h +++ b/include/linux/amba/serial.h @@ -65,6 +65,24 @@ #define ST_UART011_ABCR 0x100 /* Autobaud control register. */ #define ST_UART011_ABIMSC 0x15C /* Autobaud interrupt mask/clear register. */ +/* + * ZTE UART register offsets. This UART has a radically different address + * allocation from the ARM and ST variants, so we list all registers here. + * We assume unlisted registers do not exist. + */ +#define ZX_UART011_DR 0x04 +#define ZX_UART011_FR 0x14 +#define ZX_UART011_IBRD 0x24 +#define ZX_UART011_FBRD 0x28 +#define ZX_UART011_LCRH 0x30 +#define ZX_UART011_CR 0x34 +#define ZX_UART011_IFLS 0x38 +#define ZX_UART011_IMSC 0x40 +#define ZX_UART011_RIS 0x44 +#define ZX_UART011_MIS 0x48 +#define ZX_UART011_ICR 0x4c +#define ZX_UART011_DMACR 0x50 + #define UART011_DR_OE (1 << 11) #define UART011_DR_BE (1 << 10) #define UART011_DR_PE (1 << 9) -- cgit v0.10.2 From f5ce6edd22cff94e7b4a17f26cad43e60ae3d080 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 16 Nov 2015 17:41:02 +0000 Subject: tty: amba-pl011: switch to using relaxed IO accessors Using relaxed IO accessors allows GCC to better optimise this code as we eliminate the heavy memory barriers - for example, GCC can now cache the address of a register across a read-modify-write sequence, rather than reloading the base address, offset and access size flag. Signed-off-by: Russell King Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 295f0be..3b24aea 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -262,7 +262,7 @@ static unsigned int pl011_read(const struct uart_amba_port *uap, { void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg); - return uap->access_32b ? readl(addr) : readw(addr); + return uap->access_32b ? readl_relaxed(addr) : readw_relaxed(addr); } static void pl011_write(unsigned int val, const struct uart_amba_port *uap, @@ -271,9 +271,9 @@ static void pl011_write(unsigned int val, const struct uart_amba_port *uap, void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg); if (uap->access_32b) - writel(val, addr); + writel_relaxed(val, addr); else - writew(val, addr); + writew_relaxed(val, addr); } /* -- cgit v0.10.2 From 1bc1f17b7f1ca320b389622e3c7fbf4ee8991f61 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 18 Nov 2015 14:41:11 +0000 Subject: ARM: meson: serial: release region on port release The meson_uart_release_port() unmaps the register area but does not release it. The meson_uart_request_port() calls devm_request_mem_region so the release should call devm_release_mem_region() for that area so that anyt subsequent use of these calls will work. This fixes an issue where the addition of reset code before registering the uart stops the console from working. Signed-off-by: Ben Dooks Tested-by: Carlo Caione Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 0fc83c9..b9f0829 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -367,9 +367,26 @@ static int meson_uart_verify_port(struct uart_port *port, return ret; } +static int meson_uart_res_size(struct uart_port *port) +{ + struct platform_device *pdev = to_platform_device(port->dev); + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(port->dev, "cannot obtain I/O memory region"); + return -ENODEV; + } + + return resource_size(res); +} + static void meson_uart_release_port(struct uart_port *port) { + int size = meson_uart_res_size(port); + if (port->flags & UPF_IOREMAP) { + devm_release_mem_region(port->dev, port->mapbase, size); devm_iounmap(port->dev, port->membase); port->membase = NULL; } @@ -377,16 +394,10 @@ static void meson_uart_release_port(struct uart_port *port) static int meson_uart_request_port(struct uart_port *port) { - struct platform_device *pdev = to_platform_device(port->dev); - struct resource *res; - int size; + int size = meson_uart_res_size(port); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "cannot obtain I/O memory region"); - return -ENODEV; - } - size = resource_size(res); + if (size < 0) + return size; if (!devm_request_mem_region(port->dev, port->mapbase, size, dev_name(port->dev))) { -- cgit v0.10.2 From 00661dd855b5b174aa176a9ab9437d86ef4f8f1a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 18 Nov 2015 14:41:12 +0000 Subject: ARM: meson: serial: don't reset port on uart startup When the uart startup entry is called, do not reset the port as this could cause issues with anything left in the FIFO from a previous operation such as a console write. Move the hardware reset to probe time and simply clear the errors before enabling the port. This fixes the issue where the console could become corrupted as there where characters left in the output or output fifo when a user process such as systemd would open/close the uart to transmit characters. For example, you get: [ 3.252263] systemd[1]: Dete instead of: [ 3.338801] systemd[1]: Detected architecture arm. Signed-off-by: Ben Dooks Tested-by: Carlo Caione Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index b9f0829..b87eb97 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -241,10 +241,9 @@ static const char *meson_uart_type(struct uart_port *port) return (port->type == PORT_MESON) ? "meson_uart" : NULL; } -static int meson_uart_startup(struct uart_port *port) +static void meson_uart_reset(struct uart_port *port) { u32 val; - int ret = 0; val = readl(port->membase + AML_UART_CONTROL); val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR); @@ -252,6 +251,18 @@ static int meson_uart_startup(struct uart_port *port) val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR); writel(val, port->membase + AML_UART_CONTROL); +} + +static int meson_uart_startup(struct uart_port *port) +{ + u32 val; + int ret = 0; + + val = readl(port->membase + AML_UART_CONTROL); + val |= AML_UART_CLR_ERR; + writel(val, port->membase + AML_UART_CONTROL); + val &= ~AML_UART_CLR_ERR; + writel(val, port->membase + AML_UART_CONTROL); val |= (AML_UART_RX_EN | AML_UART_TX_EN); writel(val, port->membase + AML_UART_CONTROL); @@ -581,6 +592,12 @@ static int meson_uart_probe(struct platform_device *pdev) meson_ports[pdev->id] = port; platform_set_drvdata(pdev, port); + /* reset port before registering (and possibly registering console) */ + if (meson_uart_request_port(port) >= 0) { + meson_uart_reset(port); + meson_uart_release_port(port); + } + ret = uart_add_one_port(&meson_uart_driver, port); if (ret) meson_ports[pdev->id] = NULL; -- cgit v0.10.2 From 88679739012cda64b1a45ee9dea16d04380dba71 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 18 Nov 2015 14:41:13 +0000 Subject: ARM: meson: serial: tx_empty fails to check for transmitter busy The tx_empty() uart_op should only return empty if both the transmit fifo and the transmit state-machine are both idle. Add a test for the hardware's XMIT_BUSY flag. Note, this is possibly related to an issue where the port is being shutdown with paritally transmitted characters in it. Signed-off-by: Ben Dooks Reported-by: Edward Cragg Tested-by: Carlo Caione Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index b87eb97..54d1b95 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -57,6 +57,7 @@ #define AML_UART_RX_EMPTY BIT(20) #define AML_UART_TX_FULL BIT(21) #define AML_UART_TX_EMPTY BIT(22) +#define AML_UART_XMIT_BUSY BIT(25) #define AML_UART_ERR (AML_UART_PARITY_ERR | \ AML_UART_FRAME_ERR | \ AML_UART_TX_FIFO_WERR) @@ -100,7 +101,8 @@ static unsigned int meson_uart_tx_empty(struct uart_port *port) u32 val; val = readl(port->membase + AML_UART_STATUS); - return (val & AML_UART_TX_EMPTY) ? TIOCSER_TEMT : 0; + val &= (AML_UART_TX_EMPTY | AML_UART_XMIT_BUSY); + return (val == AML_UART_TX_EMPTY) ? TIOCSER_TEMT : 0; } static void meson_uart_stop_tx(struct uart_port *port) -- cgit v0.10.2 From 41788f054920d591c2d44838b73457e9d33ebd2c Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 18 Nov 2015 14:41:14 +0000 Subject: ARM: meson: serial: ensure console port uart enabled Ensure the UART's transmitter is enabled when meson_console_putchar is called. If not, then the console output is corrupt (the hardware seems to try and send /something/ even if the TX is disabled). This fixes corrupt console output on events such as trying to reboot the system since the console tx may be called after drivers shutdown method has been called. Signed-off-by: Ben Dooks Reported-by: Edward Cragg Tested-by: Carlo Caione Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 54d1b95..c7bad2b 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -472,6 +472,7 @@ static void meson_serial_console_write(struct console *co, const char *s, struct uart_port *port; unsigned long flags; int locked; + u32 val; port = meson_ports[co->index]; if (!port) @@ -487,6 +488,9 @@ static void meson_serial_console_write(struct console *co, const char *s, locked = 1; } + val = readl(port->membase + AML_UART_CONTROL); + writel(val | AML_UART_TX_EN, port->membase + AML_UART_CONTROL); + uart_console_write(port, s, count, meson_console_putchar); if (locked) -- cgit v0.10.2 From 855ddcab352c15b8c4d0bd93759f821250c601fb Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 18 Nov 2015 14:41:15 +0000 Subject: ARM: meson: serial: only disable tx irq on stop Since disabling the transmit state machine still allows characters to be transmitted when written to the UART write FIFO, simply disable the transmit interrupt when the UART port is stopped. This has not shown an improvement with the console issues when running systemd, but seems like it should be done. Signed-off-by: Ben Dooks Reported-by: Edward Cragg Tested-by: Carlo Caione Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index c7bad2b..9327efd 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -110,7 +110,7 @@ static void meson_uart_stop_tx(struct uart_port *port) u32 val; val = readl(port->membase + AML_UART_CONTROL); - val &= ~AML_UART_TX_EN; + val &= ~AML_UART_TX_INT_EN; writel(val, port->membase + AML_UART_CONTROL); } @@ -133,7 +133,7 @@ static void meson_uart_shutdown(struct uart_port *port) spin_lock_irqsave(&port->lock, flags); val = readl(port->membase + AML_UART_CONTROL); - val &= ~(AML_UART_RX_EN | AML_UART_TX_EN); + val &= ~AML_UART_RX_EN; val &= ~(AML_UART_RX_INT_EN | AML_UART_TX_INT_EN); writel(val, port->membase + AML_UART_CONTROL); -- cgit v0.10.2 From f1f5c1400f7907a1b52be94cabe8992b480785cf Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 18 Nov 2015 14:41:16 +0000 Subject: ARM: meson: serial: use meson_uart_tx_empty() to wait for empty Use the meson_uart_tx_empty() instead of a direct read of the status register. This is easier to read and will ensure the UART's transmit state machine is idle when trying to update the baud rate. Signed-off-by: Ben Dooks Tested-by: Carlo Caione Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 9327efd..d3f2c96 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -285,7 +285,7 @@ static void meson_uart_change_speed(struct uart_port *port, unsigned long baud) { u32 val; - while (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_EMPTY)) + while (!meson_uart_tx_empty(port)) cpu_relax(); val = readl(port->membase + AML_UART_REG5); -- cgit v0.10.2 From 2561f068d91bbb1bd132b439c9023120c0b28cf4 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 18 Nov 2015 14:41:17 +0000 Subject: ARM: meson: serial: disable rx/tx irqs during console write As an attempt to stop issues with bad console output, ensure that both the rx and tx interrupts are disabled during the console write to avoid any problems with console and non-console being called together. This should help with the SMP case as it should stop other cores being signalled during the console write. Signed-off-by: Ben Dooks Tested-by: Carlo Caione Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index d3f2c96..12436cc 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -472,7 +472,7 @@ static void meson_serial_console_write(struct console *co, const char *s, struct uart_port *port; unsigned long flags; int locked; - u32 val; + u32 val, tmp; port = meson_ports[co->index]; if (!port) @@ -489,9 +489,12 @@ static void meson_serial_console_write(struct console *co, const char *s, } val = readl(port->membase + AML_UART_CONTROL); - writel(val | AML_UART_TX_EN, port->membase + AML_UART_CONTROL); + val |= AML_UART_TX_EN; + tmp = val & ~(AML_UART_TX_INT_EN | AML_UART_RX_INT_EN); + writel(tmp, port->membase + AML_UART_CONTROL); uart_console_write(port, s, count, meson_console_putchar); + writel(val, port->membase + AML_UART_CONTROL); if (locked) spin_unlock(&port->lock); -- cgit v0.10.2 From f1dd05c82985f9c476969598fd97cc680f18e86b Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 18 Nov 2015 14:41:18 +0000 Subject: ARM: meson: serial: ensure tx irq on if more work to do The tx_stop() call turns the interrupt off, but the tx_start() does not check if the interrupt is enabled. Switch it back on if there is more work to do. Signed-off-by: Ben Dooks Tested-by: Carlo Caione Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 12436cc..6c36526 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -144,6 +144,7 @@ static void meson_uart_start_tx(struct uart_port *port) { struct circ_buf *xmit = &port->state->xmit; unsigned int ch; + u32 val; if (uart_tx_stopped(port)) { meson_uart_stop_tx(port); @@ -167,6 +168,12 @@ static void meson_uart_start_tx(struct uart_port *port) port->icount.tx++; } + if (!uart_circ_empty(xmit)) { + val = readl(port->membase + AML_UART_CONTROL); + val |= AML_UART_TX_INT_EN; + writel(val, port->membase + AML_UART_CONTROL); + } + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); } -- cgit v0.10.2 From 39469654db20a14915a7fb33ca2ec67547011ece Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 18 Nov 2015 14:41:19 +0000 Subject: ARM: meson: serial: check for tx-irq enabled in irq code Ensure that if the interrupt handler is entered then only try and do tx work if the tx irq is enabled. Signed-off-by: Ben Dooks Tested-by: Carlo Caione Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 6c36526..b12a37b 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -237,8 +237,10 @@ static irqreturn_t meson_uart_interrupt(int irq, void *dev_id) if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY)) meson_receive_chars(port); - if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_FULL)) - meson_uart_start_tx(port); + if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_FULL)) { + if (readl(port->membase + AML_UART_CONTROL) & AML_UART_TX_INT_EN) + meson_uart_start_tx(port); + } spin_unlock(&port->lock); -- cgit v0.10.2 From dd42bf1197144ede075a9d4793123f7689e164bc Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 27 Nov 2015 14:30:21 -0500 Subject: tty: Prevent ldisc drivers from re-using stale tty fields Line discipline drivers may mistakenly misuse ldisc-related fields when initializing. For example, a failure to initialize tty->receive_room in the N_GIGASET_M101 line discipline was recently found and fixed [1]. Now, the N_X25 line discipline has been discovered accessing the previous line discipline's already-freed private data [2]. Harden the ldisc interface against misuse by initializing revelant tty fields before instancing the new line discipline. [1] commit fd98e9419d8d622a4de91f76b306af6aa627aa9c Author: Tilman Schmidt Date: Tue Jul 14 00:37:13 2015 +0200 isdn/gigaset: reset tty->receive_room when attaching ser_gigaset [2] Report from Sasha Levin [ 634.336761] ================================================================== [ 634.338226] BUG: KASAN: use-after-free in x25_asy_open_tty+0x13d/0x490 at addr ffff8800a743efd0 [ 634.339558] Read of size 4 by task syzkaller_execu/8981 [ 634.340359] ============================================================================= [ 634.341598] BUG kmalloc-512 (Not tainted): kasan: bad access detected ... [ 634.405018] Call Trace: [ 634.405277] dump_stack (lib/dump_stack.c:52) [ 634.405775] print_trailer (mm/slub.c:655) [ 634.406361] object_err (mm/slub.c:662) [ 634.406824] kasan_report_error (mm/kasan/report.c:138 mm/kasan/report.c:236) [ 634.409581] __asan_report_load4_noabort (mm/kasan/report.c:279) [ 634.411355] x25_asy_open_tty (drivers/net/wan/x25_asy.c:559 (discriminator 1)) [ 634.413997] tty_ldisc_open.isra.2 (drivers/tty/tty_ldisc.c:447) [ 634.414549] tty_set_ldisc (drivers/tty/tty_ldisc.c:567) [ 634.415057] tty_ioctl (drivers/tty/tty_io.c:2646 drivers/tty/tty_io.c:2879) [ 634.423524] do_vfs_ioctl (fs/ioctl.c:43 fs/ioctl.c:607) [ 634.427491] SyS_ioctl (fs/ioctl.c:622 fs/ioctl.c:613) [ 634.427945] entry_SYSCALL_64_fastpath (arch/x86/entry/entry_64.S:188) Cc: Tilman Schmidt Cc: Sasha Levin Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 9ec1250..a054d03 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -417,6 +417,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); * they are not on hot paths so a little discipline won't do * any harm. * + * The line discipline-related tty_struct fields are reset to + * prevent the ldisc driver from re-using stale information for + * the new ldisc instance. + * * Locking: takes termios_rwsem */ @@ -425,6 +429,9 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) down_write(&tty->termios_rwsem); tty->termios.c_line = num; up_write(&tty->termios_rwsem); + + tty->disc_data = NULL; + tty->receive_room = 0; } /** -- cgit v0.10.2 From 0ff4230584320b2153752ba54e2e8edbd6addf2c Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Thu, 10 Dec 2015 13:26:21 +0200 Subject: serial: 8250_mid: fix broken DMA dependency In order to enable HSU DMA PCI driver, the HSU DMA Engine must be enabled. This add a check for that. Reported-by: kbuild test robot Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 54f8af8..b03cb517 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -371,7 +371,7 @@ config SERIAL_8250_MID tristate "Support for serial ports on Intel MID platforms" depends on SERIAL_8250 && PCI select HSU_DMA if SERIAL_8250_DMA - select HSU_DMA_PCI if X86_INTEL_MID + select HSU_DMA_PCI if (HSU_DMA && X86_INTEL_MID) select RATIONAL help Selecting this option will enable handling of the extra features -- cgit v0.10.2 From 858965d909db32fb567a06916bbebdb8951cd39e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 27 Nov 2015 21:29:24 -0500 Subject: serial: Fix UPIO_MEM comment The original semantics of UPIO_MEM did not include the notion of bitness and endianness; different drivers used UPIO_MEM to refer to their original mmio bitness/endianness. For example, for the 8250 driver this is 8-bit LE but for the amba-pl011 driver this is 16-bit LE. Since UPIO_* values are userspace ABI via TIOCGSERIAL/TIOCSSERIAL ioctls, the original meaning of UPIIO_MEM must remain as it was: the original mmio stride/width/endianness of the driver. Signed-off-by: Peter Hurley Acked-by: Timur Tabi Signed-off-by: Greg Kroah-Hartman diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 35aa87b..e03d6ba 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -145,7 +145,7 @@ struct uart_port { #define UPIO_PORT (SERIAL_IO_PORT) /* 8b I/O port access */ #define UPIO_HUB6 (SERIAL_IO_HUB6) /* Hub6 ISA card */ -#define UPIO_MEM (SERIAL_IO_MEM) /* 8b MMIO access */ +#define UPIO_MEM (SERIAL_IO_MEM) /* driver-specific */ #define UPIO_MEM32 (SERIAL_IO_MEM32) /* 32b little endian */ #define UPIO_AU (SERIAL_IO_AU) /* Au1x00 and RT288x type IO */ #define UPIO_TSI (SERIAL_IO_TSI) /* Tsi108/109 type IO */ -- cgit v0.10.2 From ba4f10ae1b731a7c2ceff49977e6df336805b839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frederik=20V=C3=B6lkel?= Date: Fri, 11 Dec 2015 11:36:01 +0100 Subject: drivers: tty: 68328serial.c: Add missing spaces(checkpatch) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds missing spaces reported by checkpatch. Signed-off-by: Frederik Völkel Signed-off-by: Lukas Braun Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index 0140ba4..4cdd805 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -274,8 +274,8 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx) #endif ch = GET_FIELD(rx, URX_RXDATA); - if(info->is_cons) { - if(URX_BREAK & rx) { /* whee, break received */ + if (info->is_cons) { + if (URX_BREAK & rx) { /* whee, break received */ return; #ifdef CONFIG_MAGIC_SYSRQ } else if (ch == 0x10) { /* ^P */ @@ -302,7 +302,7 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx) tty_insert_flip_char(&info->tport, ch, flag); #ifndef CONFIG_XCOPILOT_BUGS - } while((rx = uart->urx.w) & URX_DATA_READY); + } while ((rx = uart->urx.w) & URX_DATA_READY); #endif tty_schedule_flip(&info->tport); @@ -330,7 +330,7 @@ static void transmit_chars(struct m68k_serial *info, struct tty_struct *tty) info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); info->xmit_cnt--; - if(info->xmit_cnt <= 0) { + if (info->xmit_cnt <= 0) { /* All done for now... TX ints off */ uart->ustcnt &= ~USTCNT_TX_INTR_MASK; goto clear_and_return; @@ -452,45 +452,45 @@ struct { } #ifndef CONFIG_M68VZ328 hw_baud_table[18] = { - {0,0}, /* 0 */ - {0,0}, /* 50 */ - {0,0}, /* 75 */ - {0,0}, /* 110 */ - {0,0}, /* 134 */ - {0,0}, /* 150 */ - {0,0}, /* 200 */ - {7,0x26}, /* 300 */ - {6,0x26}, /* 600 */ - {5,0x26}, /* 1200 */ - {0,0}, /* 1800 */ - {4,0x26}, /* 2400 */ - {3,0x26}, /* 4800 */ - {2,0x26}, /* 9600 */ - {1,0x26}, /* 19200 */ - {0,0x26}, /* 38400 */ - {1,0x38}, /* 57600 */ - {0,0x38}, /* 115200 */ + {0, 0}, /* 0 */ + {0, 0}, /* 50 */ + {0, 0}, /* 75 */ + {0, 0}, /* 110 */ + {0, 0}, /* 134 */ + {0, 0}, /* 150 */ + {0, 0}, /* 200 */ + {7, 0x26}, /* 300 */ + {6, 0x26}, /* 600 */ + {5, 0x26}, /* 1200 */ + {0, 0}, /* 1800 */ + {4, 0x26}, /* 2400 */ + {3, 0x26}, /* 4800 */ + {2, 0x26}, /* 9600 */ + {1, 0x26}, /* 19200 */ + {0, 0x26}, /* 38400 */ + {1, 0x38}, /* 57600 */ + {0, 0x38}, /* 115200 */ }; #else hw_baud_table[18] = { - {0,0}, /* 0 */ - {0,0}, /* 50 */ - {0,0}, /* 75 */ - {0,0}, /* 110 */ - {0,0}, /* 134 */ - {0,0}, /* 150 */ - {0,0}, /* 200 */ - {0,0}, /* 300 */ - {7,0x26}, /* 600 */ - {6,0x26}, /* 1200 */ - {0,0}, /* 1800 */ - {5,0x26}, /* 2400 */ - {4,0x26}, /* 4800 */ - {3,0x26}, /* 9600 */ - {2,0x26}, /* 19200 */ - {1,0x26}, /* 38400 */ - {0,0x26}, /* 57600 */ - {1,0x38}, /* 115200 */ + {0, 0}, /* 0 */ + {0, 0}, /* 50 */ + {0, 0}, /* 75 */ + {0, 0}, /* 110 */ + {0, 0}, /* 134 */ + {0, 0}, /* 150 */ + {0, 0}, /* 200 */ + {0, 0}, /* 300 */ + {7, 0x26}, /* 600 */ + {6, 0x26}, /* 1200 */ + {0, 0}, /* 1800 */ + {5, 0x26}, /* 2400 */ + {4, 0x26}, /* 4800 */ + {3, 0x26}, /* 9600 */ + {2, 0x26}, /* 19200 */ + {1, 0x26}, /* 38400 */ + {0, 0x26}, /* 57600 */ + {1, 0x38}, /* 115200 */ }; #endif /* rate = 1036800 / ((65 - prescale) * (1<name, "rs_flush_chars")) return; #ifndef USE_INTS - for(;;) { + for (;;) { #endif /* Enable transmitter */ @@ -700,7 +700,7 @@ static int rs_write(struct tty_struct * tty, /* Enable transmitter */ local_irq_disable(); #ifndef USE_INTS - while(info->xmit_cnt) { + while (info->xmit_cnt) { #endif uart->ustcnt |= USTCNT_TXEN; @@ -1180,7 +1180,7 @@ rs68328_init(void) local_irq_save(flags); - for(i=0;itport); @@ -1263,7 +1263,7 @@ int m68328_console_setup(struct console *cp, char *arg) return(-1); if (arg) - n = simple_strtoul(arg,NULL,0); + n = simple_strtoul(arg, NULL, 0); for (i = 0; i < ARRAY_SIZE(baud_table); i++) if (baud_table[i] == n) -- cgit v0.10.2 From 4b7bb2b288d32abd854c41a54ba1da2be462f43b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frederik=20V=C3=B6lkel?= Date: Fri, 11 Dec 2015 11:36:02 +0100 Subject: drivers: tty: 68328serial.c: remove unnecessary spaces(checkpatch) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes unnecessary spaces reported by checkpatch. Signed-off-by: Frederik Völkel Signed-off-by: Lukas Braun Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index 4cdd805..b26cbae 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -538,7 +538,7 @@ static void change_speed(struct m68k_serial *info, struct tty_struct *tty) #ifdef CONFIG_SERIAL_68328_RTS_CTS if (cflag & CRTSCTS) { - uart->utx.w &= ~ UTX_NOCTS; + uart->utx.w &= ~UTX_NOCTS; } else { uart->utx.w |= UTX_NOCTS; } @@ -1198,7 +1198,7 @@ rs68328_init(void) printk(" is a builtin MC68328 UART\n"); #ifdef CONFIG_M68VZ328 - if (i > 0 ) + if (i > 0) PJSEL &= 0xCF; /* PSW enable second port output */ #endif @@ -1298,7 +1298,7 @@ void m68328_console_write (struct console *co, const char *str, while (count--) { if (*str == '\n') rs_put_char('\r'); - rs_put_char( *str++ ); + rs_put_char(*str++); } } -- cgit v0.10.2 From e836ed7a2f549b605d10d5ff7b2ea72f2f024d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frederik=20V=C3=B6lkel?= Date: Fri, 11 Dec 2015 11:36:03 +0100 Subject: drivers: tty: 68328serial.c: Do not initialize statics to 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes an initialization of a static to 0 as checkpatch suggests. Signed-off-by: Frederik Völkel Signed-off-by: Lukas Braun Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index b26cbae..b6d7230c 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -157,7 +157,7 @@ static void change_speed(struct m68k_serial *info, struct tty_struct *tty); #endif -static int m68328_console_initted = 0; +static int m68328_console_initted; static int m68328_console_baud = CONSOLE_BAUD_RATE; static int m68328_console_cbaud = DEFAULT_CBAUD; -- cgit v0.10.2 From 2ababf9e791180a997ab367dfa97c1a7085bd170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frederik=20V=C3=B6lkel?= Date: Fri, 11 Dec 2015 11:36:04 +0100 Subject: drivers: tty: 68328serial.c: Fix "foo * bar" should be "foo *bar" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes checkpatch errors "foo * bar" should be "foo *bar". Signed-off-by: Frederik Völkel Signed-off-by: Lukas Braun Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index b6d7230c..8d58517 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -659,9 +659,9 @@ static void rs_flush_chars(struct tty_struct *tty) local_irq_restore(flags); } -extern void console_printn(const char * b, int count); +extern void console_printn(const char *b, int count); -static int rs_write(struct tty_struct * tty, +static int rs_write(struct tty_struct *tty, const unsigned char *buf, int count) { int c, total = 0; @@ -767,7 +767,7 @@ static void rs_flush_buffer(struct tty_struct *tty) * incoming characters should be throttled. * ------------------------------------------------------------ */ -static void rs_throttle(struct tty_struct * tty) +static void rs_throttle(struct tty_struct *tty) { struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; @@ -780,7 +780,7 @@ static void rs_throttle(struct tty_struct * tty) /* Turn off RTS line (do this atomic) */ } -static void rs_unthrottle(struct tty_struct * tty) +static void rs_unthrottle(struct tty_struct *tty) { struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; @@ -803,8 +803,8 @@ static void rs_unthrottle(struct tty_struct * tty) * ------------------------------------------------------------ */ -static int get_serial_info(struct m68k_serial * info, - struct serial_struct * retinfo) +static int get_serial_info(struct m68k_serial *info, + struct serial_struct *retinfo) { struct serial_struct tmp; @@ -827,7 +827,7 @@ static int get_serial_info(struct m68k_serial * info, } static int set_serial_info(struct m68k_serial *info, struct tty_struct *tty, - struct serial_struct * new_info) + struct serial_struct *new_info) { struct tty_port *port = &info->tport; struct serial_struct new_serial; @@ -883,7 +883,7 @@ check_and_exit: * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. */ -static int get_lsr_info(struct m68k_serial * info, unsigned int *value) +static int get_lsr_info(struct m68k_serial *info, unsigned int *value) { #ifdef CONFIG_SERIAL_68328_RTS_CTS m68328_uart *uart = &uart_addr[info->line]; @@ -904,7 +904,7 @@ static int get_lsr_info(struct m68k_serial * info, unsigned int *value) /* * This routine sends a break character out the serial port. */ -static void send_break(struct m68k_serial * info, unsigned int duration) +static void send_break(struct m68k_serial *info, unsigned int duration) { m68328_uart *uart = &uart_addr[info->line]; unsigned long flags; @@ -922,7 +922,7 @@ static void send_break(struct m68k_serial * info, unsigned int duration) static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { - struct m68k_serial * info = (struct m68k_serial *)tty->driver_data; + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; int retval; if (serial_paranoia_check(info, tty->name, "rs_ioctl")) @@ -992,9 +992,9 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * that IRQ if nothing is left in the chain. * ------------------------------------------------------------ */ -static void rs_close(struct tty_struct *tty, struct file * filp) +static void rs_close(struct tty_struct *tty, struct file *filp) { - struct m68k_serial * info = (struct m68k_serial *)tty->driver_data; + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; struct tty_port *port = &info->tport; m68328_uart *uart = &uart_addr[info->line]; unsigned long flags; @@ -1079,7 +1079,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) */ void rs_hangup(struct tty_struct *tty) { - struct m68k_serial * info = (struct m68k_serial *)tty->driver_data; + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; if (serial_paranoia_check(info, tty->name, "rs_hangup")) return; @@ -1098,7 +1098,7 @@ void rs_hangup(struct tty_struct *tty) * the IRQ chain. It also performs the serial-specific * initialization for the tty structure. */ -int rs_open(struct tty_struct *tty, struct file * filp) +int rs_open(struct tty_struct *tty, struct file *filp) { struct m68k_serial *info; int retval; -- cgit v0.10.2 From 5cbb457e35f76a5a7b0dac30a07447e94a770057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frederik=20V=C3=B6lkel?= Date: Fri, 11 Dec 2015 11:36:05 +0100 Subject: drivers: tty: 68328serial.c: Remove parentheses after return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes parentheses after return as checkpatch suggests. Signed-off-by: Frederik Völkel Signed-off-by: Lukas Braun Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index 8d58517..0982c1a 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -1279,7 +1279,7 @@ int m68328_console_setup(struct console *cp, char *arg) } m68328_set_baud(); /* make sure baud rate changes */ - return(0); + return 0; } -- cgit v0.10.2 From 4f71a2e0a282611e55bacb60b564eaef5d16c27b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 13 Dec 2015 11:30:02 +0100 Subject: serial: mctrl_gpio: export mctrl_gpio_disable_ms and mctrl_gpio_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To be able to make use of the mctrl-gpio helper from a module these functions must be exported. This was forgotten in the commit introducing support interrupt handling for these functions (while it was done for mctrl_gpio_enable_ms, *sigh*). Fixes: ce59e48fdbad ("serial: mctrl_gpio: implement interrupt handling") Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c index 3eb57eb..226ad23 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.c +++ b/drivers/tty/serial/serial_mctrl_gpio.c @@ -193,6 +193,7 @@ struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx) return gpios; } +EXPORT_SYMBOL_GPL(mctrl_gpio_init); void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios) { @@ -247,3 +248,4 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) disable_irq(gpios->irq[i]); } } +EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms); -- cgit v0.10.2 From 58362d5be35216f196b4a4d16aa2c6ef938087f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 13 Dec 2015 11:30:03 +0100 Subject: serial: imx: implement handshaking using gpios with the mctrl_gpio helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 0bdf4d5..d27a0c6 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -576,6 +576,7 @@ config SERIAL_IMX depends on ARCH_MXC || COMPILE_TEST select SERIAL_CORE select RATIONAL + select SERIAL_MCTRL_GPIO if GPIOLIB help If you have a machine based on a Motorola IMX CPU you can enable its onboard serial port by enabling this option. diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 591f1c2..9362f54c 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -44,6 +44,8 @@ #include #include +#include "serial_mctrl_gpio.h" + /* Register definitions */ #define URXD0 0x0 /* Receiver Register */ #define URTX0 0x40 /* Transmitter Register */ @@ -209,6 +211,8 @@ struct imx_port { struct clk *clk_per; const struct imx_uart_data *devdata; + struct mctrl_gpios *gpios; + /* DMA fields */ unsigned int dma_is_inited:1; unsigned int dma_is_enabled:1; @@ -311,6 +315,26 @@ static void imx_port_ucrs_restore(struct uart_port *port, } #endif +static void imx_port_rts_active(struct imx_port *sport, unsigned long *ucr2) +{ + *ucr2 &= ~UCR2_CTSC; + *ucr2 |= UCR2_CTS; + + mctrl_gpio_set(sport->gpios, sport->port.mctrl | TIOCM_RTS); +} + +static void imx_port_rts_inactive(struct imx_port *sport, unsigned long *ucr2) +{ + *ucr2 &= ~(UCR2_CTSC | UCR2_CTS); + + mctrl_gpio_set(sport->gpios, sport->port.mctrl & ~TIOCM_RTS); +} + +static void imx_port_rts_auto(struct imx_port *sport, unsigned long *ucr2) +{ + *ucr2 |= UCR2_CTSC; +} + /* * interrupts disabled on entry */ @@ -334,9 +358,9 @@ static void imx_stop_tx(struct uart_port *port) readl(port->membase + USR2) & USR2_TXDC) { temp = readl(port->membase + UCR2); if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) - temp &= ~UCR2_CTS; + imx_port_rts_inactive(sport, &temp); else - temp |= UCR2_CTS; + imx_port_rts_active(sport, &temp); writel(temp, port->membase + UCR2); temp = readl(port->membase + UCR4); @@ -378,6 +402,8 @@ static void imx_enable_ms(struct uart_port *port) struct imx_port *sport = (struct imx_port *)port; mod_timer(&sport->timer, jiffies); + + mctrl_gpio_enable_ms(sport->gpios); } static void imx_dma_tx(struct imx_port *sport); @@ -537,14 +563,14 @@ static void imx_start_tx(struct uart_port *port) unsigned long temp; if (port->rs485.flags & SER_RS485_ENABLED) { - /* enable transmitter and shifter empty irq */ temp = readl(port->membase + UCR2); if (port->rs485.flags & SER_RS485_RTS_ON_SEND) - temp &= ~UCR2_CTS; + imx_port_rts_inactive(sport, &temp); else - temp |= UCR2_CTS; + imx_port_rts_active(sport, &temp); writel(temp, port->membase + UCR2); + /* enable transmitter and shifter empty irq */ temp = readl(port->membase + UCR4); temp |= UCR4_TCEN; writel(temp, port->membase + UCR4); @@ -759,9 +785,8 @@ static unsigned int imx_tx_empty(struct uart_port *port) /* * We have a modem side uart, so the meanings of RTS and CTS are inverted. */ -static unsigned int imx_get_mctrl(struct uart_port *port) +static unsigned int imx_get_hwmctrl(struct imx_port *sport) { - struct imx_port *sport = (struct imx_port *)port; unsigned int tmp = TIOCM_DSR; unsigned usr1 = readl(sport->port.membase + USR1); @@ -779,6 +804,16 @@ static unsigned int imx_get_mctrl(struct uart_port *port) return tmp; } +static unsigned int imx_get_mctrl(struct uart_port *port) +{ + struct imx_port *sport = (struct imx_port *)port; + unsigned int ret = imx_get_hwmctrl(sport); + + mctrl_gpio_get(sport->gpios, &ret); + + return ret; +} + static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct imx_port *sport = (struct imx_port *)port; @@ -801,6 +836,8 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) if (mctrl & TIOCM_LOOP) temp |= UTS_LOOP; writel(temp, sport->port.membase + uts_reg(sport)); + + mctrl_gpio_set(sport->gpios, mctrl); } /* @@ -830,7 +867,7 @@ static void imx_mctrl_check(struct imx_port *sport) { unsigned int status, changed; - status = imx_get_mctrl(&sport->port); + status = imx_get_hwmctrl(sport); changed = status ^ sport->old_status; if (changed == 0) @@ -1218,6 +1255,8 @@ static void imx_shutdown(struct uart_port *port) imx_uart_dma_exit(sport); } + mctrl_gpio_disable_ms(sport->gpios); + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR2); temp &= ~(UCR2_TXEN); @@ -1295,9 +1334,10 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, { struct imx_port *sport = (struct imx_port *)port; unsigned long flags; - unsigned int ucr2, old_ucr1, old_ucr2, baud, quot; + unsigned long ucr2, old_ucr1, old_ucr2; + unsigned int baud, quot; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; - unsigned int div, ufcr; + unsigned long div, ufcr; unsigned long num, denom; uint64_t tdiv64; @@ -1326,19 +1366,25 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, * it under manual control and keep transmitter * disabled. */ - if (!(port->rs485.flags & - SER_RS485_RTS_AFTER_SEND)) - ucr2 |= UCR2_CTS; + if (port->rs485.flags & + SER_RS485_RTS_AFTER_SEND) + imx_port_rts_inactive(sport, &ucr2); + else + imx_port_rts_active(sport, &ucr2); } else { - ucr2 |= UCR2_CTSC; + imx_port_rts_auto(sport, &ucr2); } } else { termios->c_cflag &= ~CRTSCTS; } - } else if (port->rs485.flags & SER_RS485_ENABLED) + } else if (port->rs485.flags & SER_RS485_ENABLED) { /* disable transmitter */ - if (!(port->rs485.flags & SER_RS485_RTS_AFTER_SEND)) - ucr2 |= UCR2_CTS; + if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) + imx_port_rts_inactive(sport, &ucr2); + else + imx_port_rts_active(sport, &ucr2); + } + if (termios->c_cflag & CSTOPB) ucr2 |= UCR2_STPB; @@ -1579,11 +1625,10 @@ static int imx_rs485_config(struct uart_port *port, /* disable transmitter */ temp = readl(sport->port.membase + UCR2); - temp &= ~UCR2_CTSC; if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND) - temp &= ~UCR2_CTS; + imx_port_rts_inactive(sport, &temp); else - temp |= UCR2_CTS; + imx_port_rts_active(sport, &temp); writel(temp, sport->port.membase + UCR2); } @@ -1956,6 +2001,10 @@ static int serial_imx_probe(struct platform_device *pdev) sport->timer.function = imx_timeout; sport->timer.data = (unsigned long)sport; + sport->gpios = mctrl_gpio_init(&sport->port, 0); + if (IS_ERR(sport->gpios)) + return PTR_ERR(sport->gpios); + sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(sport->clk_ipg)) { ret = PTR_ERR(sport->clk_ipg); -- cgit v0.10.2 From a9ec81f4ed5c05dbbc671e5fa39de0540eb0495f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 14 Sep 2015 15:14:23 +0300 Subject: serial: sh-sci: Drop the interface clock As no platform defines an interface clock the SCI driver always falls back to a clock named "peripheral_clk". - On SH platforms that clock is the base clock for the SCI functional clock and has the same frequency, - On ARM platforms that clock doesn't exist, and clk_get() will return the default clock for the device. We can thus make the functional clock mandatory and drop the interface clock. EPROBE_DEFER is handled for clocks that may be referenced from DT (i.e. "fck", and the deprecated "sci_ick"). Cc: devicetree@vger.kernel.org Signed-off-by: Laurent Pinchart Acked-by: Simon Horman [geert: Handle EPROBE_DEFER, reformat description, break long comment line] Signed-off-by: Geert Uytterhoeven Acked-by: Rob Herring Acked-by: Greg Kroah-Hartman diff --git a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt index 73f825e..2c9e6b8 100644 --- a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt +++ b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt @@ -42,7 +42,7 @@ Required properties: - clocks: Must contain a phandle and clock-specifier pair for each entry in clock-names. - - clock-names: Must contain "sci_ick" for the SCIx UART interface clock. + - clock-names: Must contain "fck" for the SCIx UART functional clock. Note: Each enabled SCIx UART should have an alias correctly numbered in the "aliases" node. @@ -63,7 +63,7 @@ Example: interrupt-parent = <&gic>; interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7790_CLK_SCIFA0>; - clock-names = "sci_ick"; + clock-names = "fck"; dmas = <&dmac0 0x21>, <&dmac0 0x22>; dma-names = "tx", "rx"; }; diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 960e50a..cc6fa55 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -92,8 +92,6 @@ struct sci_port { struct timer_list break_timer; int break_flag; - /* Interface clock */ - struct clk *iclk; /* Function clock */ struct clk *fclk; @@ -457,9 +455,8 @@ static void sci_port_enable(struct sci_port *sci_port) pm_runtime_get_sync(sci_port->port.dev); - clk_prepare_enable(sci_port->iclk); - sci_port->port.uartclk = clk_get_rate(sci_port->iclk); clk_prepare_enable(sci_port->fclk); + sci_port->port.uartclk = clk_get_rate(sci_port->fclk); } static void sci_port_disable(struct sci_port *sci_port) @@ -476,7 +473,6 @@ static void sci_port_disable(struct sci_port *sci_port) sci_port->break_flag = 0; clk_disable_unprepare(sci_port->fclk); - clk_disable_unprepare(sci_port->iclk); pm_runtime_put_sync(sci_port->port.dev); } @@ -1622,7 +1618,7 @@ static int sci_notifier(struct notifier_block *self, struct uart_port *port = &sci_port->port; spin_lock_irqsave(&port->lock, flags); - port->uartclk = clk_get_rate(sci_port->iclk); + port->uartclk = clk_get_rate(sci_port->fclk); spin_unlock_irqrestore(&port->lock, flags); } @@ -2241,6 +2237,42 @@ static struct uart_ops sci_uart_ops = { #endif }; +static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) +{ + /* Get the SCI functional clock. It's called "fck" on ARM. */ + sci_port->fclk = clk_get(dev, "fck"); + if (PTR_ERR(sci_port->fclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (!IS_ERR(sci_port->fclk)) + return 0; + + /* + * But it used to be called "sci_ick", and we need to maintain DT + * backward compatibility. + */ + sci_port->fclk = clk_get(dev, "sci_ick"); + if (PTR_ERR(sci_port->fclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (!IS_ERR(sci_port->fclk)) + return 0; + + /* SH has historically named the clock "sci_fck". */ + sci_port->fclk = clk_get(dev, "sci_fck"); + if (!IS_ERR(sci_port->fclk)) + return 0; + + /* + * Not all SH platforms declare a clock lookup entry for SCI devices, + * in which case we need to get the global "peripheral_clk" clock. + */ + sci_port->fclk = clk_get(dev, "peripheral_clk"); + if (!IS_ERR(sci_port->fclk)) + return 0; + + dev_err(dev, "failed to get functional clock\n"); + return PTR_ERR(sci_port->fclk); +} + static int sci_init_single(struct platform_device *dev, struct sci_port *sci_port, unsigned int index, struct plat_sci_port *p, bool early) @@ -2333,22 +2365,9 @@ static int sci_init_single(struct platform_device *dev, sci_port->sampling_rate = p->sampling_rate; if (!early) { - sci_port->iclk = clk_get(&dev->dev, "sci_ick"); - if (IS_ERR(sci_port->iclk)) { - sci_port->iclk = clk_get(&dev->dev, "peripheral_clk"); - if (IS_ERR(sci_port->iclk)) { - dev_err(&dev->dev, "can't get iclk\n"); - return PTR_ERR(sci_port->iclk); - } - } - - /* - * The function clock is optional, ignore it if we can't - * find it. - */ - sci_port->fclk = clk_get(&dev->dev, "sci_fck"); - if (IS_ERR(sci_port->fclk)) - sci_port->fclk = NULL; + ret = sci_init_clocks(sci_port, &dev->dev); + if (ret < 0) + return ret; port->dev = &dev->dev; @@ -2405,7 +2424,6 @@ static int sci_init_single(struct platform_device *dev, static void sci_cleanup_single(struct sci_port *port) { - clk_put(port->iclk); clk_put(port->fclk); pm_runtime_disable(port->port.dev); -- cgit v0.10.2 From 598604ff22109a025af8d5038664ebeb2402afdc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 11 Dec 2015 12:48:15 +0100 Subject: serial: sh-sci: Add fallback compatibility strings Add fallback compatibility strings for R-Car Gen1, Gen2, and Gen3. This is in keeping with the fallback scheme being adopted wherever appropriate for drivers for Renesas SoCs. Signed-off-by: Geert Uytterhoeven diff --git a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt index 2c9e6b8..7091213 100644 --- a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt +++ b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt @@ -2,7 +2,7 @@ Required properties: - - compatible: Must contain one of the following: + - compatible: Must contain one or more of the following: - "renesas,scif-r7s72100" for R7S72100 (RZ/A1H) SCIF compatible UART. - "renesas,scifa-r8a73a4" for R8A73A4 (R-Mobile APE6) SCIFA compatible UART. @@ -27,6 +27,14 @@ Required properties: - "renesas,hscif-r8a7795" for R8A7795 (R-Car H3) HSCIF compatible UART. - "renesas,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA compatible UART. - "renesas,scifb-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFB compatible UART. + - "renesas,rcar-gen1-scif" for R-Car Gen1 SCIF compatible UART, + - "renesas,rcar-gen2-scif" for R-Car Gen2 SCIF compatible UART, + - "renesas,rcar-gen3-scif" for R-Car Gen3 SCIF compatible UART, + - "renesas,rcar-gen2-scifa" for R-Car Gen2 SCIFA compatible UART, + - "renesas,rcar-gen2-scifb" for R-Car Gen2 SCIFB compatible UART, + - "renesas,rcar-gen1-hscif" for R-Car Gen1 HSCIF compatible UART, + - "renesas,rcar-gen2-hscif" for R-Car Gen2 HSCIF compatible UART, + - "renesas,rcar-gen3-hscif" for R-Car Gen3 HSCIF compatible UART, - "renesas,scif" for generic SCIF compatible UART. - "renesas,scifa" for generic SCIFA compatible UART. - "renesas,scifb" for generic SCIFB compatible UART. @@ -34,8 +42,8 @@ Required properties: - "renesas,sci" for generic SCI compatible UART. When compatible with the generic version, nodes must list the - SoC-specific version corresponding to the platform first followed by the - generic version. + SoC-specific version corresponding to the platform first, followed by the + family-specific and/or generic versions. - reg: Base address and length of the I/O registers used by the UART. - interrupts: Must contain an interrupt-specifier for the SCIx interrupt. @@ -58,7 +66,8 @@ Example: }; scifa0: serial@e6c40000 { - compatible = "renesas,scifa-r8a7790", "renesas,scifa"; + compatible = "renesas,scifa-r8a7790", + "renesas,rcar-gen2-scifa", "renesas,scifa"; reg = <0 0xe6c40000 0 64>; interrupt-parent = <&gic>; interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>; -- cgit v0.10.2 From 9a040c9f2170e0e6d092fc7cf8289a4466b8d8d6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 12 Nov 2015 13:44:29 +0100 Subject: serial: sh-sci: Update DT binding documentation for external clock input Amend the DT bindings to include the optional external clock on (H)SCI(F) and some SCIFA, where this pin can serve as a clock input, depending on board wiring. Clarify the use of the divided functional clock as a source for the sampling clock. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt index 7091213..31cc063 100644 --- a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt +++ b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt @@ -51,6 +51,11 @@ Required properties: - clocks: Must contain a phandle and clock-specifier pair for each entry in clock-names. - clock-names: Must contain "fck" for the SCIx UART functional clock. + Apart from the divided functional clock, there may be other possible + sources for the sampling clock, depending on SCIx variant. + On (H)SCI(F) and some SCIFA, an additional clock may be specified: + - "hsck" for the optional external clock input (on HSCIF), + - "sck" for the optional external clock input (on other variants). Note: Each enabled SCIx UART should have an alias correctly numbered in the "aliases" node. -- cgit v0.10.2 From 176ae5f674ebd2049f99e97eb8319200f1d211b6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 26 Oct 2015 09:43:22 +0100 Subject: serial: sh-sci: Update DT binding documentation for BRG support Amend the DT bindings to include the optional clock sources for the Baud Rate Generator for External Clock (BRG), as found on some SCIF variants and on HSCIF. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt index 31cc063..f4ad30e 100644 --- a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt +++ b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt @@ -56,6 +56,12 @@ Required properties: On (H)SCI(F) and some SCIFA, an additional clock may be specified: - "hsck" for the optional external clock input (on HSCIF), - "sck" for the optional external clock input (on other variants). + On UARTs equipped with a Baud Rate Generator for External Clock (BRG) + (some SCIF and HSCIF), additional clocks may be specified: + - "brg_int" for the optional internal clock source for the frequency + divider (typically the (AXI or SHwy) bus clock), + - "scif_clk" for the optional external clock source for the frequency + divider (SCIF_CLK). Note: Each enabled SCIx UART should have an alias correctly numbered in the "aliases" node. -- cgit v0.10.2 From dcafbb47bdfde32b9f3c275aa4b435c120d02f15 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 3 Nov 2015 18:14:10 +0100 Subject: serial: sh-sci: Drop useless check for zero sampling_rate sci_port.sampling_rate is always non-zero, except for HSCIF, which uses sci_baud_calc_hscif() instead of sci_scbrr_calc(). Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index cc6fa55..dfee7a2 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1863,13 +1863,7 @@ static void sci_shutdown(struct uart_port *port) static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned long freq) { - if (s->sampling_rate) - return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1; - - /* Warn, but use a safe default */ - WARN_ON(1); - - return ((freq + 16 * bps) / (32 * bps) - 1); + return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1; } /* calculate frame length from SMR */ -- cgit v0.10.2 From 2095fc76953aeec2a091d321426daca3534fca12 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 12 Nov 2015 13:39:49 +0100 Subject: serial: sh-sci: Grammar s/Get ... for/Get ... from/ Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index dfee7a2..5ec1a70 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2645,7 +2645,7 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) if (!p) return NULL; - /* Get the line number for the aliases node. */ + /* Get the line number from the aliases node. */ id = of_alias_get_id(np, "serial"); if (id < 0) { dev_err(&pdev->dev, "failed to get alias id (%d)\n", id); -- cgit v0.10.2 From 495bb47c5dfe92bedce92fd5f3a3a0258d72ac36 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 10 Dec 2015 16:02:17 +0100 Subject: serial: sh-sci: Use existing local variable in sci_parse_dt() Signed-off-by: Geert Uytterhoeven diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 5ec1a70..3607719 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2635,7 +2635,7 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) if (!IS_ENABLED(CONFIG_OF) || !np) return NULL; - match = of_match_node(of_sci_match, pdev->dev.of_node); + match = of_match_node(of_sci_match, np); if (!match) return NULL; -- cgit v0.10.2 From bdcb3826976e60204cce52470c01bb9541e547b3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 13 Nov 2015 09:48:34 +0100 Subject: serial: sh-sci: Drop unused frame_len parameter for sci_baud_calc_hscif() As F is assumed to be zero in the receive margin formula, frame_len is not used. Remove it, together with the sci_baud_calc_frame_len() helper function. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 3607719..05ac153 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1866,26 +1866,9 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1; } -/* calculate frame length from SMR */ -static int sci_baud_calc_frame_len(unsigned int smr_val) -{ - int len = 10; - - if (smr_val & SCSMR_CHR) - len--; - if (smr_val & SCSMR_PE) - len++; - if (smr_val & SCSMR_STOP) - len++; - - return len; -} - - /* calculate sample rate, BRR, and clock select for HSCIF */ -static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, - int *brr, unsigned int *srr, - unsigned int *cks, int frame_len) +static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, + unsigned int *srr, unsigned int *cks) { int sr, c, br, err, recv_margin; int min_err = 1000; /* 100% */ @@ -1987,9 +1970,8 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, baud = uart_get_baud_rate(port, termios, old, 0, max_baud); if (likely(baud && port->uartclk)) { if (s->cfg->type == PORT_HSCIF) { - int frame_len = sci_baud_calc_frame_len(smr_val); sci_baud_calc_hscif(baud, port->uartclk, &t, &srr, - &cks, frame_len); + &cks); } else { t = sci_scbrr_calc(s, baud, port->uartclk); for (cks = 0; t >= 256 && cks <= 3; cks++) -- cgit v0.10.2 From a67969b5fd366d488ffa1defd5256e8c3a87434d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 18 Nov 2015 16:20:44 +0100 Subject: serial: sh-sci: Don't overwrite clock selection in serial_console_write() Blindly writing the default configuration value into the SCSCR register may change the clock selection bits, breaking the serial console if the current driver settings differ from the default settings. Keep the current clock selection bits to prevent this from happening on e.g. r8a7791/koelsch when support for the BRG will be added. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 05ac153..136ad2f 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2420,7 +2420,7 @@ static void serial_console_write(struct console *co, const char *s, { struct sci_port *sci_port = &sci_ports[co->index]; struct uart_port *port = &sci_port->port; - unsigned short bits, ctrl; + unsigned short bits, ctrl, ctrl_temp; unsigned long flags; int locked = 1; @@ -2432,9 +2432,11 @@ static void serial_console_write(struct console *co, const char *s, else spin_lock(&port->lock); - /* first save the SCSCR then disable the interrupts */ + /* first save SCSCR then disable interrupts, keep clock source */ ctrl = serial_port_in(port, SCSCR); - serial_port_out(port, SCSCR, sci_port->cfg->scscr); + ctrl_temp = (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) | + (ctrl & (SCSCR_CKE1 | SCSCR_CKE0)); + serial_port_out(port, SCSCR, ctrl_temp); uart_console_write(port, s, count, serial_console_putchar); -- cgit v0.10.2 From f4de472ef2ff8937b04d5da9d885c78fcbd4c171 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 26 Oct 2015 09:56:20 +0100 Subject: serial: sh-sci: Convert from clk_get() to devm_clk_get() Transfer clock cleanup handling to the core device management code. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 136ad2f..b9eb4b5 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2216,7 +2216,7 @@ static struct uart_ops sci_uart_ops = { static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) { /* Get the SCI functional clock. It's called "fck" on ARM. */ - sci_port->fclk = clk_get(dev, "fck"); + sci_port->fclk = devm_clk_get(dev, "fck"); if (PTR_ERR(sci_port->fclk) == -EPROBE_DEFER) return -EPROBE_DEFER; if (!IS_ERR(sci_port->fclk)) @@ -2226,14 +2226,14 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) * But it used to be called "sci_ick", and we need to maintain DT * backward compatibility. */ - sci_port->fclk = clk_get(dev, "sci_ick"); + sci_port->fclk = devm_clk_get(dev, "sci_ick"); if (PTR_ERR(sci_port->fclk) == -EPROBE_DEFER) return -EPROBE_DEFER; if (!IS_ERR(sci_port->fclk)) return 0; /* SH has historically named the clock "sci_fck". */ - sci_port->fclk = clk_get(dev, "sci_fck"); + sci_port->fclk = devm_clk_get(dev, "sci_fck"); if (!IS_ERR(sci_port->fclk)) return 0; @@ -2241,7 +2241,7 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) * Not all SH platforms declare a clock lookup entry for SCI devices, * in which case we need to get the global "peripheral_clk" clock. */ - sci_port->fclk = clk_get(dev, "peripheral_clk"); + sci_port->fclk = devm_clk_get(dev, "peripheral_clk"); if (!IS_ERR(sci_port->fclk)) return 0; @@ -2400,8 +2400,6 @@ static int sci_init_single(struct platform_device *dev, static void sci_cleanup_single(struct sci_port *port) { - clk_put(port->fclk); - pm_runtime_disable(port->port.dev); } -- cgit v0.10.2 From 95a2703e36530c09a9416321ec21c062f3e91d01 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 13 Nov 2015 16:56:08 +0100 Subject: serial: sh-sci: Make unsigned values in sci_baud_calc_hscif() unsigned Move the -1 offset of br to the assignment to *brr, so br cannot become negative anymore, and update the clamp() call. Now all unsigned values in sci_baud_calc_hscif() can become unsigned. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index b9eb4b5..77e0a58 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1870,7 +1870,8 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, unsigned int *srr, unsigned int *cks) { - int sr, c, br, err, recv_margin; + unsigned int sr, br, c; + int err, recv_margin; int min_err = 1000; /* 100% */ int recv_max_margin = 0; @@ -1880,9 +1881,9 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ br = DIV_ROUND_CLOSEST(freq, (sr * - (1 << (2 * c + 1)) * bps)) - 1; - br = clamp(br, 0, 255); - err = DIV_ROUND_CLOSEST(freq, ((br + 1) * bps * sr * + (1 << (2 * c + 1)) * bps)); + br = clamp(br, 1U, 256U); + err = DIV_ROUND_CLOSEST(freq, (br * bps * sr * (1 << (2 * c + 1)) / 1000)) - 1000; /* Calc recv margin @@ -1908,7 +1909,7 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, else continue; - *brr = br; + *brr = br - 1; *srr = sr - 1; *cks = c; } -- cgit v0.10.2 From de01e6cd0b100bac088b1d59a7040ebe2af64f1c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 13 Nov 2015 17:04:56 +0100 Subject: serial: sh-sci: Avoid overflow in sci_baud_calc_hscif() If bps >= 1048576, the multiplication of the predivider and "bps" will overflow, and both br and err will contain bogus values. Skip the current and all higher clock select predividers when overflow is detected. Simplify the calculations using intermediates while we're at it. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 77e0a58..c490c51 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1870,7 +1870,7 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, unsigned int *srr, unsigned int *cks) { - unsigned int sr, br, c; + unsigned int sr, br, prediv, scrate, c; int err, recv_margin; int min_err = 1000; /* 100% */ int recv_max_margin = 0; @@ -1880,12 +1880,25 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, for (sr = 8; sr <= 32; sr++) { for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ - br = DIV_ROUND_CLOSEST(freq, (sr * - (1 << (2 * c + 1)) * bps)); + prediv = sr * (1 << (2 * c + 1)); + + /* + * We need to calculate: + * + * br = freq / (prediv * bps) clamped to [1..256] + * err = (freq / (br * prediv * bps / 1000)) - 1000 + * + * Watch out for overflow when calculating the desired + * sampling clock rate! + */ + if (bps > UINT_MAX / prediv) + break; + + scrate = prediv * bps; + br = DIV_ROUND_CLOSEST(freq, scrate); br = clamp(br, 1U, 256U); - err = DIV_ROUND_CLOSEST(freq, (br * bps * sr * - (1 << (2 * c + 1)) / 1000)) - - 1000; + err = DIV_ROUND_CLOSEST(freq, (br * scrate) / 1000) - + 1000; /* Calc recv margin * M: Receive margin (%) * N: Ratio of bit rate to clock (N = sampling rate) -- cgit v0.10.2 From 881a7489f463e59a44417ad89ecb4ea21b2b86cd Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 16 Nov 2015 15:54:47 +0100 Subject: serial: sh-sci: Improve bit rate error calculation for HSCIF The algorithm to find the best parameters for the requested bit rate calculates the relative bit rate error, using "(br * scrate) / 1000". For small "br * scrate", this has two problems: - The quotient may be zero, leading to a division by zero error, - This may introduce a large rounding error. Switch from relative to absolute bit rate error calculation to fix this. The default baud rate generator values can be removed, as there will always be one set of values that gives the smallest absolute error. Print the best set of values when debugging. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index c490c51..306497e 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1867,12 +1867,13 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, } /* calculate sample rate, BRR, and clock select for HSCIF */ -static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, +static void sci_baud_calc_hscif(struct sci_port *s, unsigned int bps, + unsigned long freq, int *brr, unsigned int *srr, unsigned int *cks) { unsigned int sr, br, prediv, scrate, c; int err, recv_margin; - int min_err = 1000; /* 100% */ + int min_err = INT_MAX; int recv_max_margin = 0; /* Find the combination of sample rate and clock select with the @@ -1886,7 +1887,7 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, * We need to calculate: * * br = freq / (prediv * bps) clamped to [1..256] - * err = (freq / (br * prediv * bps / 1000)) - 1000 + * err = freq / (br * prediv) - bps * * Watch out for overflow when calculating the desired * sampling clock rate! @@ -1897,8 +1898,7 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, scrate = prediv * bps; br = DIV_ROUND_CLOSEST(freq, scrate); br = clamp(br, 1U, 256U); - err = DIV_ROUND_CLOSEST(freq, (br * scrate) / 1000) - - 1000; + err = DIV_ROUND_CLOSEST(freq, br * prediv) - bps; /* Calc recv margin * M: Receive margin (%) * N: Ratio of bit rate to clock (N = sampling rate) @@ -1928,13 +1928,8 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, } } - if (min_err == 1000) { - WARN_ON(1); - /* use defaults */ - *brr = 255; - *srr = 15; - *cks = 0; - } + dev_dbg(s->port.dev, "BRR: %u%+d bps using N %u SR %u cks %u\n", bps, + min_err, *brr, *srr + 1, *cks); } static void sci_reset(struct uart_port *port) @@ -1984,7 +1979,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, baud = uart_get_baud_rate(port, termios, old, 0, max_baud); if (likely(baud && port->uartclk)) { if (s->cfg->type == PORT_HSCIF) { - sci_baud_calc_hscif(baud, port->uartclk, &t, &srr, + sci_baud_calc_hscif(s, baud, port->uartclk, &t, &srr, &cks); } else { t = sci_scbrr_calc(s, baud, port->uartclk); -- cgit v0.10.2 From 6c51332dfc23fc7c2c58244e35d36744db202077 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 16 Nov 2015 16:33:22 +0100 Subject: serial: sh-sci: Avoid calculating the receive margin for HSCIF When assuming D = 0.5 and F = 0, maximizing the receive margin M is equivalent to maximizing the sample rate N. Hence there's no need to calculate the receive margin, as we can obtain the same result by iterating over all possible sample rates in reverse order, and skipping parameter sets that don't provide a lower bit rate error. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 306497e..c3a1936 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1872,13 +1872,24 @@ static void sci_baud_calc_hscif(struct sci_port *s, unsigned int bps, unsigned int *srr, unsigned int *cks) { unsigned int sr, br, prediv, scrate, c; - int err, recv_margin; - int min_err = INT_MAX; - int recv_max_margin = 0; + int err, min_err = INT_MAX; - /* Find the combination of sample rate and clock select with the - smallest deviation from the desired baud rate. */ - for (sr = 8; sr <= 32; sr++) { + /* + * Find the combination of sample rate and clock select with the + * smallest deviation from the desired baud rate. + * Prefer high sample rates to maximise the receive margin. + * + * M: Receive margin (%) + * N: Ratio of bit rate to clock (N = sampling rate) + * D: Clock duty (D = 0 to 1.0) + * L: Frame length (L = 9 to 12) + * F: Absolute value of clock frequency deviation + * + * M = |(0.5 - 1 / 2 * N) - ((L - 0.5) * F) - + * (|D - 0.5| / N * (1 + F))| + * NOTE: Usually, treat D for 0.5, F is 0 by this calculation. + */ + for (sr = 32; sr >= 8; sr--) { for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ prediv = sr * (1 << (2 * c + 1)); @@ -1898,36 +1909,22 @@ static void sci_baud_calc_hscif(struct sci_port *s, unsigned int bps, scrate = prediv * bps; br = DIV_ROUND_CLOSEST(freq, scrate); br = clamp(br, 1U, 256U); + err = DIV_ROUND_CLOSEST(freq, br * prediv) - bps; - /* Calc recv margin - * M: Receive margin (%) - * N: Ratio of bit rate to clock (N = sampling rate) - * D: Clock duty (D = 0 to 1.0) - * L: Frame length (L = 9 to 12) - * F: Absolute value of clock frequency deviation - * - * M = |(0.5 - 1 / 2 * N) - ((L - 0.5) * F) - - * (|D - 0.5| / N * (1 + F))| - * NOTE: Usually, treat D for 0.5, F is 0 by this - * calculation. - */ - recv_margin = abs((500 - - DIV_ROUND_CLOSEST(1000, sr << 1)) / 10); - if (abs(min_err) > abs(err)) { - min_err = err; - recv_max_margin = recv_margin; - } else if ((min_err == err) && - (recv_margin > recv_max_margin)) - recv_max_margin = recv_margin; - else + if (abs(err) >= abs(min_err)) continue; + min_err = err; *brr = br - 1; *srr = sr - 1; *cks = c; + + if (!err) + goto found; } } +found: dev_dbg(s->port.dev, "BRR: %u%+d bps using N %u SR %u cks %u\n", bps, min_err, *brr, *srr + 1, *cks); } -- cgit v0.10.2 From b4a5c459088b724734573a550c9da42a9a19c9d0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 16 Nov 2015 17:22:16 +0100 Subject: serial: sh-sci: Merge sci_scbrr_calc() and sci_baud_calc_hscif() For low bit rates, the for-loop that reduces the divider returned by sci_scbrr_calc() and picks the clock select value may terminate without finding suitable values, leading to out-of-range divider and clock select values. sci_baud_calc_hscif() doesn't suffer from this problem, as it correctly uses clamp(). Since there are only two relevant differences between HSCIF and other variants w.r.t. bit rate configuration (fixed vs. variable sample rate, and an additional factor of two), sci_scbrr_calc() and sci_baud_calc_hscif() can be merged, fixing the issue with out-of-range values. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index c3a1936..d89d4b7 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1860,20 +1860,24 @@ static void sci_shutdown(struct uart_port *port) sci_free_irq(s); } -static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, - unsigned long freq) +/* calculate sample rate, BRR, and clock select */ +static void sci_scbrr_calc(struct sci_port *s, unsigned int bps, + unsigned long freq, int *brr, unsigned int *srr, + unsigned int *cks) { - return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1; -} - -/* calculate sample rate, BRR, and clock select for HSCIF */ -static void sci_baud_calc_hscif(struct sci_port *s, unsigned int bps, - unsigned long freq, int *brr, - unsigned int *srr, unsigned int *cks) -{ - unsigned int sr, br, prediv, scrate, c; + unsigned int min_sr, max_sr, shift, sr, br, prediv, scrate, c; int err, min_err = INT_MAX; + if (s->sampling_rate) { + min_sr = max_sr = s->sampling_rate; + shift = 0; + } else { + /* HSCIF has a variable sample rate */ + min_sr = 8; + max_sr = 32; + shift = 1; + } + /* * Find the combination of sample rate and clock select with the * smallest deviation from the desired baud rate. @@ -1889,10 +1893,10 @@ static void sci_baud_calc_hscif(struct sci_port *s, unsigned int bps, * (|D - 0.5| / N * (1 + F))| * NOTE: Usually, treat D for 0.5, F is 0 by this calculation. */ - for (sr = 32; sr >= 8; sr--) { + for (sr = max_sr; sr >= min_sr; sr--) { for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ - prediv = sr * (1 << (2 * c + 1)); + prediv = sr * (1 << (2 * c + shift)); /* * We need to calculate: @@ -1974,16 +1978,8 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, max_baud = port->uartclk ? port->uartclk / 16 : 115200; baud = uart_get_baud_rate(port, termios, old, 0, max_baud); - if (likely(baud && port->uartclk)) { - if (s->cfg->type == PORT_HSCIF) { - sci_baud_calc_hscif(s, baud, port->uartclk, &t, &srr, - &cks); - } else { - t = sci_scbrr_calc(s, baud, port->uartclk); - for (cks = 0; t >= 256 && cks <= 3; cks++) - t >>= 2; - } - } + if (likely(baud && port->uartclk)) + sci_scbrr_calc(s, baud, port->uartclk, &t, &srr, &cks); sci_port_enable(s); -- cgit v0.10.2 From ff8b275f1f0927621cf543c2a6f02761052c360d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 19 Nov 2015 14:35:09 +0100 Subject: serial: sh-sci: Take into account sampling rate for max baud rate The maximum baud rate depends on the sampling rate. HSCIF has a variable sampling rate and sets s->sampling_rate to zero, hence use the minimum sampling rate of 8. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index d89d4b7..5b12075 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1975,7 +1975,10 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, * that the previous boot loader has enabled required clocks and * setup the baud rate generator hardware for us already. */ - max_baud = port->uartclk ? port->uartclk / 16 : 115200; + if (port->uartclk) + max_baud = port->uartclk / max(s->sampling_rate, 8U); + else + max_baud = 115200; baud = uart_get_baud_rate(port, termios, old, 0, max_baud); if (likely(baud && port->uartclk)) -- cgit v0.10.2 From b8bbd6b2923279f1c9c74d59638b38a1eace78e8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 12 Nov 2015 13:36:06 +0100 Subject: serial: sh-sci: Add BRG register definitions Add register definitions for the Baud Rate Generator for External Clock (BRG), as found in some SCIF and in HSCIF, including a new regtype for the "SH-4(A)"-derived SCIF variant with BRG. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 5b12075..fb5eac2 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -161,6 +161,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -183,6 +185,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -204,6 +208,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = { 0x30, 16 }, [SCPDR] = { 0x34, 16 }, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -225,6 +231,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = { 0x30, 16 }, [SCPDR] = { 0x34, 16 }, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -247,6 +255,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -268,6 +278,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -289,6 +301,32 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, + }, + + /* + * Common SCIF definitions for ports with a Baud Rate Generator for + * External Clock (BRG). + */ + [SCIx_SH4_SCIF_BRG_REGTYPE] = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCTFDR] = sci_reg_invalid, + [SCRFDR] = sci_reg_invalid, + [SCSPTR] = { 0x20, 16 }, + [SCLSR] = { 0x24, 16 }, + [HSSRR] = sci_reg_invalid, + [SCPCR] = sci_reg_invalid, + [SCPDR] = sci_reg_invalid, + [SCDL] = { 0x30, 16 }, + [SCCKS] = { 0x34, 16 }, }, /* @@ -310,6 +348,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = { 0x40, 16 }, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = { 0x30, 16 }, + [SCCKS] = { 0x34, 16 }, }, /* @@ -332,6 +372,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -354,6 +396,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -376,6 +420,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, }; diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index bf69bbd..fb17602 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -27,6 +27,8 @@ enum { HSSRR, /* Sampling Rate Register */ SCPCR, /* Serial Port Control Register */ SCPDR, /* Serial Port Data Register */ + SCDL, /* BRG Frequency Division Register */ + SCCKS, /* BRG Clock Select Register */ SCIx_NR_REGS, }; @@ -109,6 +111,14 @@ enum { #define SCPDR_RTSD BIT(4) /* Serial Port RTS Output Pin Data */ #define SCPDR_CTSD BIT(3) /* Serial Port CTS Input Pin Data */ +/* + * BRG Clock Select Register (Some SCIF and HSCIF) + * The Baud Rate Generator for external clock can provide a clock source for + * the sampling clock. It outputs either its frequency divided clock, or the + * (undivided) (H)SCK external clock. + */ +#define SCCKS_CKS BIT(15) /* Select (H)SCK (1) or divided SC_CLK (0) */ +#define SCCKS_XIN BIT(14) /* SC_CLK uses bus clock (1) or SCIF_CLK (0) */ #define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND) #define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF) diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 7c536ac..9f2bfd0 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -32,6 +32,7 @@ enum { SCIx_SH2_SCIF_FIFODATA_REGTYPE, SCIx_SH3_SCIF_REGTYPE, SCIx_SH4_SCIF_REGTYPE, + SCIx_SH4_SCIF_BRG_REGTYPE, SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, SCIx_SH4_SCIF_FIFODATA_REGTYPE, SCIx_SH7705_SCIF_REGTYPE, -- cgit v0.10.2 From bd2238fb84df6054d966364d07e0414b54ef8e19 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Nov 2015 16:09:23 +0100 Subject: serial: sh-sci: Replace struct sci_port_info by type/regtype encoding Store the encoded port and register types directly in of_device_id.data, instead of using a pointer to a structure. This saves memory and simplifies the source code, especially when adding more compatible entries later. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index fb5eac2..13c6abe9 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2614,42 +2614,27 @@ static int sci_remove(struct platform_device *dev) return 0; } -struct sci_port_info { - unsigned int type; - unsigned int regtype; -}; + +#define SCI_OF_DATA(type, regtype) (void *)((type) << 16 | (regtype)) +#define SCI_OF_TYPE(data) ((unsigned long)(data) >> 16) +#define SCI_OF_REGTYPE(data) ((unsigned long)(data) & 0xffff) static const struct of_device_id of_sci_match[] = { { .compatible = "renesas,scif", - .data = &(const struct sci_port_info) { - .type = PORT_SCIF, - .regtype = SCIx_SH4_SCIF_REGTYPE, - }, + .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_REGTYPE), }, { .compatible = "renesas,scifa", - .data = &(const struct sci_port_info) { - .type = PORT_SCIFA, - .regtype = SCIx_SCIFA_REGTYPE, - }, + .data = SCI_OF_DATA(PORT_SCIFA, SCIx_SCIFA_REGTYPE), }, { .compatible = "renesas,scifb", - .data = &(const struct sci_port_info) { - .type = PORT_SCIFB, - .regtype = SCIx_SCIFB_REGTYPE, - }, + .data = SCI_OF_DATA(PORT_SCIFB, SCIx_SCIFB_REGTYPE), }, { .compatible = "renesas,hscif", - .data = &(const struct sci_port_info) { - .type = PORT_HSCIF, - .regtype = SCIx_HSCIF_REGTYPE, - }, + .data = SCI_OF_DATA(PORT_HSCIF, SCIx_HSCIF_REGTYPE), }, { .compatible = "renesas,sci", - .data = &(const struct sci_port_info) { - .type = PORT_SCI, - .regtype = SCIx_SCI_REGTYPE, - }, + .data = SCI_OF_DATA(PORT_SCI, SCIx_SCI_REGTYPE), }, { /* Terminator */ }, @@ -2661,7 +2646,6 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) { struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; - const struct sci_port_info *info; struct plat_sci_port *p; int id; @@ -2672,8 +2656,6 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) if (!match) return NULL; - info = match->data; - p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL); if (!p) return NULL; @@ -2688,8 +2670,8 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) *dev_id = id; p->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; - p->type = info->type; - p->regtype = info->regtype; + p->type = SCI_OF_TYPE(match->data); + p->regtype = SCI_OF_REGTYPE(match->data); p->scscr = SCSCR_RE | SCSCR_TE; return p; -- cgit v0.10.2 From f443ff80d02d74be6c3930e325a6573eb06347ea Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Nov 2015 16:16:54 +0100 Subject: serial: sh-sci: Correct SCIF type on RZ/A1H The "renesas,scif" compatible value is currently used for the SCIF variant in all Renesas SoCs of the R-Car and RZ families. However, the variant used in the RZ family is not the common "SH-4(A)" variant, but the "SH-2(A) with FIFO data count register" variant, as it has the "Serial Extension Mode Register" (SCEMR), just like on sh7203, sh7263, sh7264, and sh7269. Use the (already documented) SoC-specific "renesas,scif-r7s72100" compatible value to differentiate. The "renesas,scif" compatible value can still be used as a common denominator for SCIF variants with the "SH-4(A)" register layout (i.e. ignoring the SCEMR register). Note that currently both variants are treated the same, but this may change if support for the SCEMR register is ever added. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 13c6abe9..5b8504b 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2620,6 +2620,12 @@ static int sci_remove(struct platform_device *dev) #define SCI_OF_REGTYPE(data) ((unsigned long)(data) & 0xffff) static const struct of_device_id of_sci_match[] = { + /* SoC-specific types */ + { + .compatible = "renesas,scif-r7s72100", + .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH2_SCIF_FIFODATA_REGTYPE), + }, + /* Generic types */ { .compatible = "renesas,scif", .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_REGTYPE), -- cgit v0.10.2 From 9ed44bb209d0ece90abb6b4279d8b18e17680476 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Nov 2015 18:57:23 +0100 Subject: serial: sh-sci: Correct SCIF type on R-Car for BRG The "renesas,scif" compatible value is currently used for the SCIF variant in all Renesas SoCs of the R-Car family. However, the variant used in the R-Car family is not the common "SH-4(A)" variant, but a derivative with added "Baud Rate Generator for External Clock" (BRG), which is also present in sh7734. Use the family-specific SCIF compatible values for R-Car Gen1, Gen2, and Gen3 SoCs to differentiate. The "renesas,scif" compatible value can still be used as a common denominator for SCIF variants with the "SH-4(A)" register layout (i.e. ignoring the "Serial Extension Mode Register" (SCEMR) and the new BRG-specific registers). Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 5b8504b..a202e4e 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2625,6 +2625,17 @@ static const struct of_device_id of_sci_match[] = { .compatible = "renesas,scif-r7s72100", .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH2_SCIF_FIFODATA_REGTYPE), }, + /* Family-specific types */ + { + .compatible = "renesas,rcar-gen1-scif", + .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), + }, { + .compatible = "renesas,rcar-gen2-scif", + .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), + }, { + .compatible = "renesas,rcar-gen3-scif", + .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), + }, /* Generic types */ { .compatible = "renesas,scif", -- cgit v0.10.2 From f4998e55b8987428aa86de02c934fb6e0988d9a3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 26 Oct 2015 09:58:16 +0100 Subject: serial: sh-sci: Prepare for multiple sampling clock sources Refactor the clock and baud rate parameter code to ease adding support for multiple sampling clock sources. sci_scbrr_calc() now returns the bit rate error, so it can be compared to the bit rate error using other sampling clock sources. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index a202e4e..fa3fd87 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2,6 +2,7 @@ * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) * * Copyright (C) 2002 - 2011 Paul Mundt + * Copyright (C) 2015 Glider bvba * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007). * * based off of the old drivers/char/sh-sci.c by: @@ -76,6 +77,11 @@ enum { ((port)->irqs[SCIx_ERI_IRQ] && \ ((port)->irqs[SCIx_RXI_IRQ] < 0)) +enum SCI_CLKS { + SCI_FCK, /* Functional Clock */ + SCI_NUM_CLKS +}; + struct sci_port { struct uart_port port; @@ -92,8 +98,9 @@ struct sci_port { struct timer_list break_timer; int break_flag; - /* Function clock */ - struct clk *fclk; + /* Clocks */ + struct clk *clks[SCI_NUM_CLKS]; + unsigned long clk_rates[SCI_NUM_CLKS]; int irqs[SCIx_NR_IRQS]; char *irqstr[SCIx_NR_IRQS]; @@ -496,17 +503,24 @@ static int sci_probe_regmap(struct plat_sci_port *cfg) static void sci_port_enable(struct sci_port *sci_port) { + unsigned int i; + if (!sci_port->port.dev) return; pm_runtime_get_sync(sci_port->port.dev); - clk_prepare_enable(sci_port->fclk); - sci_port->port.uartclk = clk_get_rate(sci_port->fclk); + for (i = 0; i < SCI_NUM_CLKS; i++) { + clk_prepare_enable(sci_port->clks[i]); + sci_port->clk_rates[i] = clk_get_rate(sci_port->clks[i]); + } + sci_port->port.uartclk = sci_port->clk_rates[SCI_FCK]; } static void sci_port_disable(struct sci_port *sci_port) { + unsigned int i; + if (!sci_port->port.dev) return; @@ -518,7 +532,8 @@ static void sci_port_disable(struct sci_port *sci_port) del_timer_sync(&sci_port->break_timer); sci_port->break_flag = 0; - clk_disable_unprepare(sci_port->fclk); + for (i = SCI_NUM_CLKS; i-- > 0; ) + clk_disable_unprepare(sci_port->clks[i]); pm_runtime_put_sync(sci_port->port.dev); } @@ -1657,6 +1672,7 @@ static int sci_notifier(struct notifier_block *self, { struct sci_port *sci_port; unsigned long flags; + unsigned int i; sci_port = container_of(self, struct sci_port, freq_transition); @@ -1664,7 +1680,9 @@ static int sci_notifier(struct notifier_block *self, struct uart_port *port = &sci_port->port; spin_lock_irqsave(&port->lock, flags); - port->uartclk = clk_get_rate(sci_port->fclk); + for (i = 0; i < SCI_NUM_CLKS; i++) + sci_port->clk_rates[i] = + clk_get_rate(sci_port->clks[i]); spin_unlock_irqrestore(&port->lock, flags); } @@ -1907,11 +1925,12 @@ static void sci_shutdown(struct uart_port *port) } /* calculate sample rate, BRR, and clock select */ -static void sci_scbrr_calc(struct sci_port *s, unsigned int bps, - unsigned long freq, int *brr, unsigned int *srr, - unsigned int *cks) +static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, + unsigned int *brr, unsigned int *srr, + unsigned int *cks) { unsigned int min_sr, max_sr, shift, sr, br, prediv, scrate, c; + unsigned long freq = s->clk_rates[SCI_FCK]; int err, min_err = INT_MAX; if (s->sampling_rate) { @@ -1977,6 +1996,7 @@ static void sci_scbrr_calc(struct sci_port *s, unsigned int bps, found: dev_dbg(s->port.dev, "BRR: %u%+d bps using N %u SR %u cks %u\n", bps, min_err, *brr, *srr + 1, *cks); + return min_err; } static void sci_reset(struct uart_port *port) @@ -1998,11 +2018,14 @@ static void sci_reset(struct uart_port *port) static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { + unsigned int baud, smr_val = 0, scr_val = 0, i; + unsigned int brr = 255, cks = 0, srr = 15; + unsigned int brr1 = 255, cks1 = 0, srr1 = 15; struct sci_port *s = to_sci_port(port); const struct plat_sci_reg *reg; - unsigned int baud, smr_val = 0, max_baud, cks = 0; - int t = -1; - unsigned int srr = 15; + int min_err = INT_MAX, err; + unsigned long max_freq = 0; + int best_clk = -1; if ((termios->c_cflag & CSIZE) == CS7) smr_val |= SCSMR_CHR; @@ -2021,35 +2044,64 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, * that the previous boot loader has enabled required clocks and * setup the baud rate generator hardware for us already. */ - if (port->uartclk) - max_baud = port->uartclk / max(s->sampling_rate, 8U); - else - max_baud = 115200; + if (!port->uartclk) { + baud = uart_get_baud_rate(port, termios, old, 0, 115200); + goto done; + } - baud = uart_get_baud_rate(port, termios, old, 0, max_baud); - if (likely(baud && port->uartclk)) - sci_scbrr_calc(s, baud, port->uartclk, &t, &srr, &cks); + for (i = 0; i < SCI_NUM_CLKS; i++) + max_freq = max(max_freq, s->clk_rates[i]); + + baud = uart_get_baud_rate(port, termios, old, 0, + max_freq / max(s->sampling_rate, 8U)); + if (!baud) + goto done; + + /* + * There can be multiple sources for the sampling clock. Find the one + * that gives us the smallest deviation from the desired baud rate. + */ + + /* Divided Functional Clock using standard Bit Rate Register */ + err = sci_scbrr_calc(s, baud, &brr1, &srr1, &cks1); + if (abs(err) < abs(min_err)) { + best_clk = SCI_FCK; + min_err = err; + brr = brr1; + srr = srr1; + cks = cks1; + } + +done: + if (best_clk >= 0) + dev_dbg(port->dev, "Using clk %pC for %u%+d bps\n", + s->clks[best_clk], baud, min_err); sci_port_enable(s); sci_reset(port); - smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS; - uart_update_timeout(port, termios->c_cflag, baud); - dev_dbg(port->dev, "%s: SMR %x, cks %x, t %x, SCSCR %x\n", - __func__, smr_val, cks, t, s->cfg->scscr); - - if (t >= 0) { - serial_port_out(port, SCSMR, (smr_val & ~SCSMR_CKS) | cks); - serial_port_out(port, SCBRR, t); - reg = sci_getreg(port, HSSRR); - if (reg->size) + if (best_clk >= 0) { + smr_val |= cks; + dev_dbg(port->dev, "SMR 0x%x BRR %u SRR %u\n", smr_val, brr, + srr); + serial_port_out(port, SCSMR, smr_val); + serial_port_out(port, SCBRR, brr); + if (sci_getreg(port, HSSRR)->size) serial_port_out(port, HSSRR, srr | HSCIF_SRE); - udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */ - } else + + /* Wait one bit interval */ + udelay((1000000 + (baud - 1)) / baud); + } else { + /* Don't touch the bit rate configuration */ + scr_val = s->cfg->scscr & (SCSCR_CKE1 | SCSCR_CKE0); + smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS; + dev_dbg(port->dev, "SCR 0x%x SMR 0x%x\n", scr_val, smr_val); + serial_port_out(port, SCSCR, scr_val); serial_port_out(port, SCSMR, smr_val); + } sci_init_pins(port, termios->c_cflag); @@ -2074,7 +2126,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, serial_port_out(port, SCFCR, ctrl); } - serial_port_out(port, SCSCR, s->cfg->scscr); + scr_val |= s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0); + dev_dbg(port->dev, "SCSCR 0x%x\n", scr_val); + serial_port_out(port, SCSCR, scr_val); #ifdef CONFIG_SERIAL_SH_SCI_DMA /* @@ -2266,38 +2320,58 @@ static struct uart_ops sci_uart_ops = { static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) { - /* Get the SCI functional clock. It's called "fck" on ARM. */ - sci_port->fclk = devm_clk_get(dev, "fck"); - if (PTR_ERR(sci_port->fclk) == -EPROBE_DEFER) - return -EPROBE_DEFER; - if (!IS_ERR(sci_port->fclk)) - return 0; + const char *clk_names[] = { + [SCI_FCK] = "fck", + }; + struct clk *clk; + unsigned int i; - /* - * But it used to be called "sci_ick", and we need to maintain DT - * backward compatibility. - */ - sci_port->fclk = devm_clk_get(dev, "sci_ick"); - if (PTR_ERR(sci_port->fclk) == -EPROBE_DEFER) - return -EPROBE_DEFER; - if (!IS_ERR(sci_port->fclk)) - return 0; + for (i = 0; i < SCI_NUM_CLKS; i++) { + clk = devm_clk_get(dev, clk_names[i]); + if (PTR_ERR(clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; - /* SH has historically named the clock "sci_fck". */ - sci_port->fclk = devm_clk_get(dev, "sci_fck"); - if (!IS_ERR(sci_port->fclk)) - return 0; + if (IS_ERR(clk) && i == SCI_FCK) { + /* + * "fck" used to be called "sci_ick", and we need to + * maintain DT backward compatibility. + */ + clk = devm_clk_get(dev, "sci_ick"); + if (PTR_ERR(clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; - /* - * Not all SH platforms declare a clock lookup entry for SCI devices, - * in which case we need to get the global "peripheral_clk" clock. - */ - sci_port->fclk = devm_clk_get(dev, "peripheral_clk"); - if (!IS_ERR(sci_port->fclk)) - return 0; + if (!IS_ERR(clk)) + goto found; - dev_err(dev, "failed to get functional clock\n"); - return PTR_ERR(sci_port->fclk); + /* SH has historically named the clock "sci_fck". */ + clk = devm_clk_get(dev, "sci_fck"); + if (!IS_ERR(clk)) + goto found; + + /* + * Not all SH platforms declare a clock lookup entry + * for SCI devices, in which case we need to get the + * global "peripheral_clk" clock. + */ + clk = devm_clk_get(dev, "peripheral_clk"); + if (!IS_ERR(clk)) + goto found; + + dev_err(dev, "failed to get %s (%ld)\n", clk_names[i], + PTR_ERR(clk)); + return PTR_ERR(clk); + } + +found: + if (IS_ERR(clk)) + dev_dbg(dev, "failed to get %s (%ld)\n", clk_names[i], + PTR_ERR(clk)); + else + dev_dbg(dev, "clk %s is %pC rate %pCr\n", clk_names[i], + clk, clk); + sci_port->clks[i] = IS_ERR(clk) ? NULL : clk; + } + return 0; } static int sci_init_single(struct platform_device *dev, -- cgit v0.10.2 From 6af27bf299e2d66ade25f278f0c13d51007e9879 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 18 Nov 2015 11:12:26 +0100 Subject: serial: sh-sci: Add support for optional external (H)SCK input Add support for using the SCIx clock pin "(H)SCK" as an external clock input on (H)SCI(F), providing the sampling clock. Note that this feature is not yet supported on the select SCIFA variants that also have it (e.g. sh7723, sh7724, and r8a7740). On (H)SCIF variants with an External Baud Rate Generator (BRG), the BRG Clock Select Register must be configured for the external clock. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index fa3fd87..2291624 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -79,6 +79,7 @@ enum { enum SCI_CLKS { SCI_FCK, /* Functional Clock */ + SCI_SCK, /* Optional External Clock */ SCI_NUM_CLKS }; @@ -1924,6 +1925,39 @@ static void sci_shutdown(struct uart_port *port) sci_free_irq(s); } +static int sci_sck_calc(struct sci_port *s, unsigned int bps, + unsigned int *srr) +{ + unsigned long freq = s->clk_rates[SCI_SCK]; + unsigned int min_sr, max_sr, sr; + int err, min_err = INT_MAX; + + if (s->sampling_rate) { + /* SCI(F) has a fixed sampling rate */ + min_sr = max_sr = s->sampling_rate / 2; + } else { + /* HSCIF has a variable 1/(8..32) sampling rate */ + min_sr = 8; + max_sr = 32; + } + + for (sr = max_sr; sr >= min_sr; sr--) { + err = DIV_ROUND_CLOSEST(freq, sr) - bps; + if (abs(err) >= abs(min_err)) + continue; + + min_err = err; + *srr = sr - 1; + + if (!err) + break; + } + + dev_dbg(s->port.dev, "SCK: %u%+d bps using SR %u\n", bps, min_err, + *srr + 1); + return min_err; +} + /* calculate sample rate, BRR, and clock select */ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned int *brr, unsigned int *srr, @@ -2019,7 +2053,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int baud, smr_val = 0, scr_val = 0, i; - unsigned int brr = 255, cks = 0, srr = 15; + unsigned int brr = 255, cks = 0, srr = 15, sccks = 0; unsigned int brr1 = 255, cks1 = 0, srr1 = 15; struct sci_port *s = to_sci_port(port); const struct plat_sci_reg *reg; @@ -2062,10 +2096,26 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, * that gives us the smallest deviation from the desired baud rate. */ + /* Optional Undivided External Clock */ + if (s->clk_rates[SCI_SCK] && port->type != PORT_SCIFA && + port->type != PORT_SCIFB) { + err = sci_sck_calc(s, baud, &srr1); + if (abs(err) < abs(min_err)) { + best_clk = SCI_SCK; + scr_val = SCSCR_CKE1; + sccks = SCCKS_CKS; + min_err = err; + srr = srr1; + if (!err) + goto done; + } + } + /* Divided Functional Clock using standard Bit Rate Register */ err = sci_scbrr_calc(s, baud, &brr1, &srr1, &cks1); if (abs(err) < abs(min_err)) { best_clk = SCI_FCK; + scr_val = 0; min_err = err; brr = brr1; srr = srr1; @@ -2079,14 +2129,23 @@ done: sci_port_enable(s); + /* + * Program the optional External Baud Rate Generator (BRG) first. + * It controls the mux to select (H)SCK or frequency divided clock. + */ + if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) + serial_port_out(port, SCCKS, sccks); + sci_reset(port); uart_update_timeout(port, termios->c_cflag, baud); if (best_clk >= 0) { smr_val |= cks; - dev_dbg(port->dev, "SMR 0x%x BRR %u SRR %u\n", smr_val, brr, - srr); + dev_dbg(port->dev, + "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x SRR %u\n", + scr_val, smr_val, brr, sccks, srr); + serial_port_out(port, SCSCR, scr_val); serial_port_out(port, SCSMR, smr_val); serial_port_out(port, SCBRR, brr); if (sci_getreg(port, HSSRR)->size) @@ -2322,10 +2381,14 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) { const char *clk_names[] = { [SCI_FCK] = "fck", + [SCI_SCK] = "sck", }; struct clk *clk; unsigned int i; + if (sci_port->cfg->type == PORT_HSCIF) + clk_names[SCI_SCK] = "hsck"; + for (i = 0; i < SCI_NUM_CLKS; i++) { clk = devm_clk_get(dev, clk_names[i]); if (PTR_ERR(clk) == -EPROBE_DEFER) -- cgit v0.10.2 From 1270f86517f342f455dc146b1b321a18d3a274f9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 18 Nov 2015 11:25:53 +0100 Subject: serial: sh-sci: Add support for optional BRG on (H)SCIF Add support for using the Baud Rate Generator for External Clock (BRG), as found on some SCIF and HSCIF variants, to provide the sampling clock. This can improve baud rate range and accuracy. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 2291624..4ff5d0c 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -80,6 +80,8 @@ enum { enum SCI_CLKS { SCI_FCK, /* Functional Clock */ SCI_SCK, /* Optional External Clock */ + SCI_BRG_INT, /* Optional BRG Internal Clock Source */ + SCI_SCIF_CLK, /* Optional BRG External Clock Source */ SCI_NUM_CLKS }; @@ -1958,6 +1960,43 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps, return min_err; } +static int sci_brg_calc(struct sci_port *s, unsigned int bps, + unsigned long freq, unsigned int *dlr, + unsigned int *srr) +{ + unsigned int min_sr, max_sr, sr, dl; + int err, min_err = INT_MAX; + + if (s->sampling_rate) { + /* SCIF has a fixed sampling rate */ + min_sr = max_sr = s->sampling_rate / 2; + } else { + /* HSCIF has a variable 1/(8..32) sampling rate */ + min_sr = 8; + max_sr = 32; + } + + for (sr = max_sr; sr >= min_sr; sr--) { + dl = DIV_ROUND_CLOSEST(freq, sr * bps); + dl = clamp(dl, 1U, 65535U); + + err = DIV_ROUND_CLOSEST(freq, sr * dl) - bps; + if (abs(err) >= abs(min_err)) + continue; + + min_err = err; + *dlr = dl; + *srr = sr - 1; + + if (!err) + break; + } + + dev_dbg(s->port.dev, "BRG: %u%+d bps using DL %u SR %u\n", bps, + min_err, *dlr, *srr + 1); + return min_err; +} + /* calculate sample rate, BRR, and clock select */ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned int *brr, unsigned int *srr, @@ -2053,8 +2092,8 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int baud, smr_val = 0, scr_val = 0, i; - unsigned int brr = 255, cks = 0, srr = 15, sccks = 0; - unsigned int brr1 = 255, cks1 = 0, srr1 = 15; + unsigned int brr = 255, cks = 0, srr = 15, dl = 0, sccks = 0; + unsigned int brr1 = 255, cks1 = 0, srr1 = 15, dl1 = 0; struct sci_port *s = to_sci_port(port); const struct plat_sci_reg *reg; int min_err = INT_MAX, err; @@ -2111,6 +2150,38 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, } } + /* Optional BRG Frequency Divided External Clock */ + if (s->clk_rates[SCI_SCIF_CLK] && sci_getreg(port, SCDL)->size) { + err = sci_brg_calc(s, baud, s->clk_rates[SCI_SCIF_CLK], &dl1, + &srr1); + if (abs(err) < abs(min_err)) { + best_clk = SCI_SCIF_CLK; + scr_val = SCSCR_CKE1; + sccks = 0; + min_err = err; + dl = dl1; + srr = srr1; + if (!err) + goto done; + } + } + + /* Optional BRG Frequency Divided Internal Clock */ + if (s->clk_rates[SCI_BRG_INT] && sci_getreg(port, SCDL)->size) { + err = sci_brg_calc(s, baud, s->clk_rates[SCI_BRG_INT], &dl1, + &srr1); + if (abs(err) < abs(min_err)) { + best_clk = SCI_BRG_INT; + scr_val = SCSCR_CKE1; + sccks = SCCKS_XIN; + min_err = err; + dl = dl1; + srr = srr1; + if (!min_err) + goto done; + } + } + /* Divided Functional Clock using standard Bit Rate Register */ err = sci_scbrr_calc(s, baud, &brr1, &srr1, &cks1); if (abs(err) < abs(min_err)) { @@ -2133,8 +2204,10 @@ done: * Program the optional External Baud Rate Generator (BRG) first. * It controls the mux to select (H)SCK or frequency divided clock. */ - if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) + if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) { + serial_port_out(port, SCDL, dl); serial_port_out(port, SCCKS, sccks); + } sci_reset(port); @@ -2143,8 +2216,8 @@ done: if (best_clk >= 0) { smr_val |= cks; dev_dbg(port->dev, - "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x SRR %u\n", - scr_val, smr_val, brr, sccks, srr); + "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x DL %u SRR %u\n", + scr_val, smr_val, brr, sccks, dl, srr); serial_port_out(port, SCSCR, scr_val); serial_port_out(port, SCSMR, smr_val); serial_port_out(port, SCBRR, brr); @@ -2382,6 +2455,8 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) const char *clk_names[] = { [SCI_FCK] = "fck", [SCI_SCK] = "sck", + [SCI_BRG_INT] = "brg_int", + [SCI_SCIF_CLK] = "scif_clk", }; struct clk *clk; unsigned int i; -- cgit v0.10.2 From fa3d39bf25558262675334f26fada57bd75c4e2e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 14 Sep 2015 15:14:24 +0300 Subject: sh: Rename sci_ick and sci_fck clock to fck The SCI driver requires a functional clock named "fck" and falls back to "sci_ick" or "sci_fck" when the "fck" clock doesn't exist. To allow removal of the fallback code rename the sci_ick and sci_fck clocks to fck for all SH platforms. Signed-off-by: Laurent Pinchart Acked-by: Simon Horman Signed-off-by: Geert Uytterhoeven diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7264.c b/arch/sh/kernel/cpu/sh2a/clock-sh7264.c index 8638fba..7e06e39 100644 --- a/arch/sh/kernel/cpu/sh2a/clock-sh7264.c +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7264.c @@ -115,7 +115,14 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), /* MSTP clocks */ - CLKDEV_CON_ID("sci_ick", &mstp_clks[MSTP77]), + CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP77]), + CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP77]), + CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP77]), + CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP77]), + CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP77]), + CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP77]), + CLKDEV_ICK_ID("fck", "sh-sci.6", &mstp_clks[MSTP77]), + CLKDEV_ICK_ID("fck", "sh-sci.7", &mstp_clks[MSTP77]), CLKDEV_CON_ID("vdc3", &mstp_clks[MSTP74]), CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]), CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]), diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7269.c b/arch/sh/kernel/cpu/sh2a/clock-sh7269.c index f8a5c2a..663a97b 100644 --- a/arch/sh/kernel/cpu/sh2a/clock-sh7269.c +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7269.c @@ -150,14 +150,14 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]), /* MSTP clocks */ - CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP47]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP46]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP45]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP44]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP43]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP42]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.6", &mstp_clks[MSTP41]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.7", &mstp_clks[MSTP40]), + CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP47]), + CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP46]), + CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP45]), + CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP44]), + CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP43]), + CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP42]), + CLKDEV_ICK_ID("fck", "sh-sci.6", &mstp_clks[MSTP41]), + CLKDEV_ICK_ID("fck", "sh-sci.7", &mstp_clks[MSTP40]), CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]), CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]), CLKDEV_ICK_ID("fck", "sh-mtu2", &mstp_clks[MSTP35]), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index 9edc06c..a907ee2 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -232,10 +232,10 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]), CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP004]), + CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP007]), + CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP006]), + CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP005]), + CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP004]), CLKDEV_CON_ID("sio0", &mstp_clks[MSTP003]), CLKDEV_CON_ID("siof0", &mstp_clks[MSTP002]), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index 955b9ad..ac98541 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -230,9 +230,9 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]), CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]), + CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP007]), + CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP006]), + CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP005]), CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]), CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index ccbcab5..fe84422 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -267,12 +267,12 @@ static struct clk_lookup lookups[] = { CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[HWBLK_TMU0]), CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[HWBLK_TMU1]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[HWBLK_SCIF3]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[HWBLK_SCIF4]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[HWBLK_SCIF5]), + CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]), + CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]), + CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]), + CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[HWBLK_SCIF3]), + CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[HWBLK_SCIF4]), + CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[HWBLK_SCIF5]), CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]), }; diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7734.c b/arch/sh/kernel/cpu/sh4a/clock-sh7734.c index 7f54bf2..354dcac 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7734.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7734.c @@ -194,12 +194,12 @@ static struct clk_lookup lookups[] = { /* MSTP32 clocks */ CLKDEV_DEV_ID("i2c-sh7734.0", &mstp_clks[MSTP030]), CLKDEV_DEV_ID("i2c-sh7734.1", &mstp_clks[MSTP029]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP026]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP024]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP023]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP022]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP021]), + CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP026]), + CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]), + CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP024]), + CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP023]), + CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP022]), + CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP021]), CLKDEV_CON_ID("hscif", &mstp_clks[MSTP019]), CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]), CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP015]), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c index e40ec2c..b10af2a 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c @@ -125,9 +125,9 @@ static struct clk_lookup lookups[] = { CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP113]), CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP114]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP112]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP111]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]), + CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP112]), + CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP111]), + CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP110]), CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP103]), CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP102]), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index 8eb6e62..1aafd54 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c @@ -132,12 +132,12 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), /* MSTP32 clocks */ - CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]), + CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP029]), + CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP028]), + CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP027]), + CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP026]), + CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]), + CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP024]), CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]), CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index 5e50e7e..ac3dcfe 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c @@ -139,12 +139,12 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), /* MSTP32 clocks */ - CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]), + CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP029]), + CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP028]), + CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP027]), + CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP026]), + CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]), + CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP024]), CLKDEV_CON_ID("ssi3_fck", &mstp_clks[MSTP023]), CLKDEV_CON_ID("ssi2_fck", &mstp_clks[MSTP022]), diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c index 605221d..b1bdbc3 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c @@ -114,10 +114,10 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), /* MSTP32 clocks */ - CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]), + CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP027]), + CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP026]), + CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]), + CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP024]), CLKDEV_CON_ID("h8ex_fck", &mstp_clks[MSTP003]), CLKDEV_CON_ID("csm_fck", &mstp_clks[MSTP002]), -- cgit v0.10.2 From 6441d314b4d898d871f21196fb5e6e4f82caedc7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 14 Sep 2015 15:14:25 +0300 Subject: sh: Remove sci_ick clock alias The sh-sci driver falls back to the peripheral clock if the sci_ick clock doesn't exist. There's thus no need to create an alias for the peripheral clock named sci_ick. Signed-off-by: Laurent Pinchart Acked-by: Simon Horman Signed-off-by: Geert Uytterhoeven diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index 8525a67..786c076 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c @@ -63,7 +63,6 @@ int __init __deprecated cpg_clk_init(void) clk_add_alias("fck", "sh-mtu2", "peripheral_clk", NULL); clk_add_alias("fck", "sh-cmt-16.0", "peripheral_clk", NULL); clk_add_alias("fck", "sh-cmt-32.0", "peripheral_clk", NULL); - clk_add_alias("sci_ick", NULL, "peripheral_clk", NULL); return ret; } -- cgit v0.10.2 From 0a036681888f417e365e0b2935ff6f3f0273f843 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Nov 2015 18:59:28 +0100 Subject: sh: sh7734: Correct SCIF type for BRG The SCIF variant in the sh7734 SoC is not the common "SH-4(A)" variant, but a derivative with added "Baud Rate Generator for External Clock" (BRG). Correct the regtype value in platform data to fix this. Signed-off-by: Geert Uytterhoeven diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7734.c b/arch/sh/kernel/cpu/sh4a/setup-sh7734.c index f617bcb..69b8a50 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7734.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7734.c @@ -28,7 +28,7 @@ static struct plat_sci_port scif0_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .type = PORT_SCIF, - .regtype = SCIx_SH4_SCIF_REGTYPE, + .regtype = SCIx_SH4_SCIF_BRG_REGTYPE, }; static struct resource scif0_resources[] = { @@ -50,7 +50,7 @@ static struct plat_sci_port scif1_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .type = PORT_SCIF, - .regtype = SCIx_SH4_SCIF_REGTYPE, + .regtype = SCIx_SH4_SCIF_BRG_REGTYPE, }; static struct resource scif1_resources[] = { @@ -72,7 +72,7 @@ static struct plat_sci_port scif2_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .type = PORT_SCIF, - .regtype = SCIx_SH4_SCIF_REGTYPE, + .regtype = SCIx_SH4_SCIF_BRG_REGTYPE, }; static struct resource scif2_resources[] = { @@ -94,7 +94,7 @@ static struct plat_sci_port scif3_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE, .type = PORT_SCIF, - .regtype = SCIx_SH4_SCIF_REGTYPE, + .regtype = SCIx_SH4_SCIF_BRG_REGTYPE, }; static struct resource scif3_resources[] = { @@ -116,7 +116,7 @@ static struct plat_sci_port scif4_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .type = PORT_SCIF, - .regtype = SCIx_SH4_SCIF_REGTYPE, + .regtype = SCIx_SH4_SCIF_BRG_REGTYPE, }; static struct resource scif4_resources[] = { @@ -138,7 +138,7 @@ static struct plat_sci_port scif5_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .type = PORT_SCIF, - .regtype = SCIx_SH4_SCIF_REGTYPE, + .regtype = SCIx_SH4_SCIF_BRG_REGTYPE, }; static struct resource scif5_resources[] = { -- cgit v0.10.2 From 192d367f218d0cd94aa9b5059992e4aa19ec5b36 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 14 Sep 2015 15:14:36 +0300 Subject: serial: sh-sci: Drop the sci_fck clock fallback All platforms that used to define an sci_fck clock have now switched to the fck name. Remove the fallback code. Signed-off-by: Laurent Pinchart Acked-by: Simon Horman Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 4ff5d0c..6571f4d 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2481,11 +2481,6 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) if (!IS_ERR(clk)) goto found; - /* SH has historically named the clock "sci_fck". */ - clk = devm_clk_get(dev, "sci_fck"); - if (!IS_ERR(clk)) - goto found; - /* * Not all SH platforms declare a clock lookup entry * for SCI devices, in which case we need to get the -- cgit v0.10.2 From cdf091ca2c3d6875e5f0fca28de4a6ca2f5273e6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 4 Jan 2016 15:37:41 -0600 Subject: tty: amba-pl011: fix earlycon register offsets The REG_x macros are indices into a table, not register offsets. Since earlycon does not have access to the vendor data, we can currently only support standard ARM PL011 devices. Signed-off-by: Russell King Tested-by: Huang Shijie Signed-off-by: Timur Tabi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 3b24aea..a7d7ab0 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2301,10 +2301,10 @@ static struct console amba_console = { static void pl011_putc(struct uart_port *port, int c) { - while (readl(port->membase + REG_FR) & UART01x_FR_TXFF) + while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF) ; - writeb(c, port->membase + REG_DR); - while (readl(port->membase + REG_FR) & UART01x_FR_BUSY) + writeb(c, port->membase + UART01x_DR); + while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY) ; } -- cgit v0.10.2 From 3b78fae793c027140cfe635ef216bf60aa6498f4 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 4 Jan 2016 15:37:42 -0600 Subject: tty: amba-pl011: use iotype instead of access_32b to track 32-bit I/O Instead of defining a new field in the uart_amba_port structure, use the existing iotype field of the uart_port structure, which is intended for this purpose. If we need to use 32-bit register access, we set iotype to UPIO_MEM32, otherwise we set it to UPIO_MEM. For early console, specify the "mmio32" option on the kernel command-line. Example: earlycon=pl011,mmio32,0x3ced1000 Signed-off-by: Timur Tabi Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 054e11d..654c547 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1003,10 +1003,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. unspecified, the h/w is not initialized. pl011, + pl011,mmio32, Start an early, polled-mode console on a pl011 serial port at the specified address. The pl011 serial port must already be setup and configured. Options are not - yet supported. + yet supported. If 'mmio32' is specified, then only + the driver will use only 32-bit accessors to read/write + the device registers. msm_serial, Start an early, polled-mode console on an msm serial diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index a7d7ab0..c0da0cc 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -238,7 +238,6 @@ struct uart_amba_port { unsigned int fifosize; /* vendor-specific */ unsigned int old_cr; /* state during shutdown */ bool autorts; - bool access_32b; unsigned int fixed_baud; /* vendor-set fixed baud rate */ char type[12]; #ifdef CONFIG_DMA_ENGINE @@ -262,7 +261,8 @@ static unsigned int pl011_read(const struct uart_amba_port *uap, { void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg); - return uap->access_32b ? readl_relaxed(addr) : readw_relaxed(addr); + return (uap->port.iotype == UPIO_MEM32) ? + readl_relaxed(addr) : readw_relaxed(addr); } static void pl011_write(unsigned int val, const struct uart_amba_port *uap, @@ -270,7 +270,7 @@ static void pl011_write(unsigned int val, const struct uart_amba_port *uap, { void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg); - if (uap->access_32b) + if (uap->port.iotype == UPIO_MEM32) writel_relaxed(val, addr); else writew_relaxed(val, addr); @@ -2303,7 +2303,10 @@ static void pl011_putc(struct uart_port *port, int c) { while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF) ; - writeb(c, port->membase + UART01x_DR); + if (port->iotype == UPIO_MEM32) + writel(c, port->membase + UART01x_DR); + else + writeb(c, port->membase + UART01x_DR); while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY) ; } @@ -2416,7 +2419,6 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, uap->port.dev = dev; uap->port.mapbase = mmiobase->start; uap->port.membase = base; - uap->port.iotype = UPIO_MEM; uap->port.fifosize = uap->fifosize; uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.line = index; @@ -2470,9 +2472,9 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) return PTR_ERR(uap->clk); uap->reg_offset = vendor->reg_offset; - uap->access_32b = vendor->access_32b; uap->vendor = vendor; uap->fifosize = vendor->get_fifosize(dev); + uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM; uap->port.irq = dev->irq[0]; uap->port.ops = &amba_pl011_pops; @@ -2551,9 +2553,9 @@ static int sbsa_uart_probe(struct platform_device *pdev) return -ENOMEM; uap->reg_offset = vendor_sbsa.reg_offset; - uap->access_32b = vendor_sbsa.access_32b; uap->vendor = &vendor_sbsa; uap->fifosize = 32; + uap->port.iotype = vendor_sbsa.access_32b ? UPIO_MEM32 : UPIO_MEM; uap->port.irq = platform_get_irq(pdev, 0); uap->port.ops = &sbsa_uart_pops; uap->fixed_baud = baudrate; -- cgit v0.10.2 From c93a59938c11f447ff2964ab3c317311778edf66 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 18 Dec 2015 15:00:49 +0200 Subject: serial: 8250: of: Fix the driver and actually compile the 8250_of The 8250_of never compiled since in the Kconfig we have SERIAL_OF_PLATFORM but in the makefile we expect to have SERIAL_8250_OF... When the 8250_of.c is actually compiled we will have two errors: missing linux/nwpserial.h and 8250/8250.h. Fix those as well at the same time when enable the compilation of the driver. Signed-off-by: Peter Ujfalusi Fixes: afd7f88f1577 ("serial: 8250: move of_serial code to 8250 directory") Reported-by: Guenter Roeck CC: Arnd Bergmann Acked-by: Arnd Bergmann Acked-by: Jon Hunter Tested-by: Jon Hunter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index d66fd24..33021c1 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -18,10 +18,9 @@ #include #include #include -#include #include -#include "8250/8250.h" +#include "8250.h" struct of_serial_info { struct clk *clk; diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 4ecb80d..b9b9bca 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -28,6 +28,6 @@ obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o -obj-$(CONFIG_SERIAL_8250_OF) += 8250_of.o +obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt -- cgit v0.10.2 From ff1cab374ad98f4b9f408525ca9c08992b4ed784 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 5 Jan 2016 19:36:37 +0100 Subject: serial: sh-sci: Remove cpufreq notifier to fix crash/deadlock The BSP team noticed that there is spin/mutex lock issue on sh-sci when CPUFREQ is used. The issue is that the notifier function may call mutex_lock() while the spinlock is held, which can lead to a BUG(). This may happen if CPUFREQ is changed while another CPU calls clk_get_rate(). Taking the spinlock was added to the notifier function in commit e552de2413edad1a ("sh-sci: add platform device private data"), to protect the list of serial ports against modification during traversal. At that time the Common Clock Framework didn't exist yet, and clk_get_rate() just returned clk->rate without taking a mutex. Note that since commit d535a2305facf9b4 ("serial: sh-sci: Require a device per port mapping."), there's no longer a list of serial ports to traverse, and taking the spinlock became superfluous. To fix the issue, just remove the cpufreq notifier: 1. The notifier doesn't work correctly: all it does is update stored clock rates; it does not update the divider in the hardware. The divider will only be updated when calling sci_set_termios(). I believe this was broken back in 2004, when the old drivers/char/sh-sci.c driver (where the notifier did update the divider) was replaced by drivers/serial/sh-sci.c (where the notifier just updated port->uartclk). Cfr. full-history-linux commits 6f8deaef2e9675d9 ("[PATCH] sh: port sh-sci driver to the new API") and 3f73fe878dc9210a ("[PATCH] Remove old sh-sci driver"). 2. On modern SoCs, the sh-sci parent clock rate is no longer related to the CPU clock rate anyway, so using a cpufreq notifier is futile. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 5f2a03a..4646a9f 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -124,8 +123,6 @@ struct sci_port { struct timer_list rx_timer; unsigned int rx_timeout; #endif - - struct notifier_block freq_transition; }; #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS @@ -1666,32 +1663,6 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) return ret; } -/* - * Here we define a transition notifier so that we can update all of our - * ports' baud rate when the peripheral clock changes. - */ -static int sci_notifier(struct notifier_block *self, - unsigned long phase, void *p) -{ - struct sci_port *sci_port; - unsigned long flags; - unsigned int i; - - sci_port = container_of(self, struct sci_port, freq_transition); - - if (phase == CPUFREQ_POSTCHANGE) { - struct uart_port *port = &sci_port->port; - - spin_lock_irqsave(&port->lock, flags); - for (i = 0; i < SCI_NUM_CLKS; i++) - sci_port->clk_rates[i] = - clk_get_rate(sci_port->clks[i]); - spin_unlock_irqrestore(&port->lock, flags); - } - - return NOTIFY_OK; -} - static const struct sci_irq_desc { const char *desc; irq_handler_t handler; @@ -2811,9 +2782,6 @@ static int sci_remove(struct platform_device *dev) { struct sci_port *port = platform_get_drvdata(dev); - cpufreq_unregister_notifier(&port->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); - uart_remove_one_port(&sci_uart_driver, &port->port); sci_cleanup_single(port); @@ -2965,16 +2933,6 @@ static int sci_probe(struct platform_device *dev) if (ret) return ret; - sp->freq_transition.notifier_call = sci_notifier; - - ret = cpufreq_register_notifier(&sp->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); - if (unlikely(ret < 0)) { - uart_remove_one_port(&sci_uart_driver, &sp->port); - sci_cleanup_single(sp); - return ret; - } - #ifdef CONFIG_SH_STANDARD_BIOS sh_bios_gdb_detach(); #endif -- cgit v0.10.2 From 041497eb721ddbdc1e690316976dd8ba7bc136a2 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 17 Dec 2015 10:05:46 -0500 Subject: drivers/tty/serial: delete unused MODULE_DEVICE_TABLE from atmel_serial.c In commit c39dfebc7798956fd2140ae6321786ff35da30c3 ("drivers/tty/serial: make serial/atmel_serial.c explicitly non-modular") we removed the code relating to modular support since it currently only supports built in. However, when redoing my build coverage for mips allmodconfig, which sets CONFIG_OF, I noticed a remaining line that needs to be removed, else we will get a build failure for an undefined module macro. Unfortunately this didn't appear for any of the other arch I tested more frequently, such as ARM. Since MODULE_DEVICE_TABLE is a no-op for non-modular code, we can just remove the offending line. Fixes: c39dfebc7798 ("drivers/tty/serial: make serial/atmel_serial.c explicitly non-modular") Cc: Nicolas Ferre Cc: Jiri Slaby Reported-by: Sudip Mukherjee Signed-off-by: Paul Gortmaker Acked-by: Nicolas Ferre Acked-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 50e785a..1c0884d 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -188,8 +188,6 @@ static const struct of_device_id atmel_serial_dt_ids[] = { { .compatible = "atmel,at91sam9260-usart" }, { /* sentinel */ } }; - -MODULE_DEVICE_TABLE(of, atmel_serial_dt_ids); #endif static inline struct atmel_uart_port * -- cgit v0.10.2