diff options
Diffstat (limited to 'drivers/tty/serial/st-asc.c')
| -rw-r--r-- | drivers/tty/serial/st-asc.c | 85 |
1 files changed, 44 insertions, 41 deletions
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index aa471c9c24d9..6ed9a327702b 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -250,7 +250,7 @@ static void asc_receive_chars(struct uart_port *port) struct tty_port *tport = &port->state->port; unsigned long status, mode; unsigned long c = 0; - char flag; + u8 flag; bool ignore_pe = false; /* @@ -319,7 +319,7 @@ static irqreturn_t asc_interrupt(int irq, void *ptr) struct uart_port *port = ptr; u32 status; - spin_lock(&port->lock); + uart_port_lock(port); status = asc_in(port, ASC_STA); @@ -334,7 +334,7 @@ static irqreturn_t asc_interrupt(int irq, void *ptr) asc_transmit_chars(port); } - spin_unlock(&port->lock); + uart_port_unlock(port); return IRQ_HANDLED; } @@ -387,9 +387,9 @@ static unsigned int asc_get_mctrl(struct uart_port *port) /* There are probably characters waiting to be transmitted. */ static void asc_start_tx(struct uart_port *port) { - struct circ_buf *xmit = &port->state->xmit; + struct tty_port *tport = &port->state->port; - if (!uart_circ_empty(xmit)) + if (!kfifo_is_empty(&tport->xmit_fifo)) asc_enable_tx_interrupts(port); } @@ -452,10 +452,10 @@ static void asc_pm(struct uart_port *port, unsigned int state, * we can come to turning it off. Note this is not called with * the port spinlock held. */ - spin_lock_irqsave(&port->lock, flags); + uart_port_lock_irqsave(port, &flags); ctl = asc_in(port, ASC_CTL) & ~ASC_CTL_RUN; asc_out(port, ASC_CTL, ctl); - spin_unlock_irqrestore(&port->lock, flags); + uart_port_unlock_irqrestore(port, flags); clk_disable_unprepare(ascport->clk); break; } @@ -465,6 +465,7 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios, const struct ktermios *old) { struct asc_port *ascport = to_asc_port(port); + bool manual_rts, toggle_rts = false; struct gpio_desc *gpiod; unsigned int baud; u32 ctrl_val; @@ -480,7 +481,7 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios, baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); cflag = termios->c_cflag; - spin_lock_irqsave(&port->lock, flags); + uart_port_lock_irqsave(port, &flags); /* read control register */ ctrl_val = asc_in(port, ASC_CTL); @@ -518,25 +519,13 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios, /* If flow-control selected, stop handling RTS manually */ if (ascport->rts) { - devm_gpiod_put(port->dev, ascport->rts); - ascport->rts = NULL; - - pinctrl_select_state(ascport->pinctrl, - ascport->states[DEFAULT]); + toggle_rts = true; + manual_rts = false; } } else { /* If flow-control disabled, it's safe to handle RTS manually */ - if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL]) { - pinctrl_select_state(ascport->pinctrl, - ascport->states[NO_HW_FLOWCTRL]); - - gpiod = devm_gpiod_get(port->dev, "rts", GPIOD_OUT_LOW); - if (!IS_ERR(gpiod)) { - gpiod_set_consumer_name(gpiod, - port->dev->of_node->name); - ascport->rts = gpiod; - } - } + if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL]) + manual_rts = toggle_rts = true; } if ((baud < 19200) && !ascport->force_m1) { @@ -594,7 +583,26 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios, /* write final value and enable port */ asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN)); - spin_unlock_irqrestore(&port->lock, flags); + uart_port_unlock_irqrestore(port, flags); + + if (toggle_rts) { + if (manual_rts) { + pinctrl_select_state(ascport->pinctrl, + ascport->states[NO_HW_FLOWCTRL]); + + gpiod = devm_gpiod_get(port->dev, "rts", GPIOD_OUT_LOW); + if (!IS_ERR(gpiod)) { + gpiod_set_consumer_name(gpiod, + port->dev->of_node->name); + ascport->rts = gpiod; + } + } else { + devm_gpiod_put(port->dev, ascport->rts); + ascport->rts = NULL; + pinctrl_select_state(ascport->pinctrl, + ascport->states[DEFAULT]); + } + } } static const char *asc_type(struct uart_port *port) @@ -691,8 +699,7 @@ static int asc_init_port(struct asc_port *ascport, port->irq = platform_get_irq(pdev, 0); port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_ST_ASC_CONSOLE); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - port->membase = devm_ioremap_resource(&pdev->dev, res); + port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(port->membase)) return PTR_ERR(port->membase); port->mapbase = res->start; @@ -704,7 +711,9 @@ static int asc_init_port(struct asc_port *ascport, if (WARN_ON(IS_ERR(ascport->clk))) return -EINVAL; /* ensure that clk rate is correct by enabling the clk */ - clk_prepare_enable(ascport->clk); + ret = clk_prepare_enable(ascport->clk); + if (ret) + return ret; ascport->port.uartclk = clk_get_rate(ascport->clk); WARN_ON(ascport->port.uartclk == 0); clk_disable_unprepare(ascport->clk); @@ -792,16 +801,13 @@ static int asc_serial_probe(struct platform_device *pdev) return 0; } -static int asc_serial_remove(struct platform_device *pdev) +static void asc_serial_remove(struct platform_device *pdev) { struct uart_port *port = platform_get_drvdata(pdev); uart_remove_one_port(&asc_uart_driver, port); - - return 0; } -#ifdef CONFIG_PM_SLEEP static int asc_serial_suspend(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); @@ -816,8 +822,6 @@ static int asc_serial_resume(struct device *dev) return uart_resume_port(&asc_uart_driver, port); } -#endif /* CONFIG_PM_SLEEP */ - /*----------------------------------------------------------------------*/ #ifdef CONFIG_SERIAL_ST_ASC_CONSOLE @@ -848,9 +852,9 @@ static void asc_console_write(struct console *co, const char *s, unsigned count) if (port->sysrq) locked = 0; /* asc_interrupt has already claimed the lock */ else if (oops_in_progress) - locked = spin_trylock_irqsave(&port->lock, flags); + locked = uart_port_trylock_irqsave(port, &flags); else - spin_lock_irqsave(&port->lock, flags); + uart_port_lock_irqsave(port, &flags); /* * Disable interrupts so we don't get the IRQ line bouncing @@ -868,7 +872,7 @@ static void asc_console_write(struct console *co, const char *s, unsigned count) asc_out(port, ASC_INTEN, intenable); if (locked) - spin_unlock_irqrestore(&port->lock, flags); + uart_port_unlock_irqrestore(port, flags); } static int asc_console_setup(struct console *co, char *options) @@ -925,16 +929,15 @@ static struct uart_driver asc_uart_driver = { .cons = ASC_SERIAL_CONSOLE, }; -static const struct dev_pm_ops asc_serial_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(asc_serial_suspend, asc_serial_resume) -}; +static DEFINE_SIMPLE_DEV_PM_OPS(asc_serial_pm_ops, asc_serial_suspend, + asc_serial_resume); static struct platform_driver asc_serial_driver = { .probe = asc_serial_probe, .remove = asc_serial_remove, .driver = { .name = DRIVER_NAME, - .pm = &asc_serial_pm_ops, + .pm = pm_sleep_ptr(&asc_serial_pm_ops), .of_match_table = of_match_ptr(asc_match), }, }; |
