summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/imx.c')
-rw-r--r--drivers/tty/serial/imx.c250
1 files changed, 197 insertions, 53 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index ff32cd2d2863..c488e5d372ff 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -30,7 +30,7 @@
#include <linux/iopoll.h>
#include <linux/dma-mapping.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
#include <linux/dma/imx-dma.h>
#include "serial_mctrl_gpio.h"
@@ -230,9 +230,12 @@ struct imx_port {
unsigned int saved_reg[10];
bool context_saved;
+ bool last_putchar_was_newline;
+
enum imx_tx_state tx_state;
struct hrtimer trigger_start_tx;
struct hrtimer trigger_stop_tx;
+ unsigned int rxtl;
};
struct imx_port_ucrs {
@@ -265,6 +268,11 @@ static const struct of_device_id imx_uart_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, imx_uart_dt_ids);
+static inline struct imx_port *to_imx_port(struct uart_port *port)
+{
+ return container_of(port, struct imx_port, port);
+}
+
static inline void imx_uart_writel(struct imx_port *sport, u32 val, u32 offset)
{
writel(val, sport->port.membase + offset);
@@ -365,6 +373,7 @@ static void imx_uart_soft_reset(struct imx_port *sport)
sport->idle_counter = 0;
}
+/* called with port.lock taken and irqs off */
static void imx_uart_disable_loopback_rs485(struct imx_port *sport)
{
unsigned int uts;
@@ -378,7 +387,7 @@ static void imx_uart_disable_loopback_rs485(struct imx_port *sport)
/* called with port.lock taken and irqs off */
static void imx_uart_start_rx(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned int ucr1, ucr2;
ucr1 = imx_uart_readl(sport, UCR1);
@@ -402,7 +411,7 @@ static void imx_uart_start_rx(struct uart_port *port)
/* called with port.lock taken and irqs off */
static void imx_uart_stop_tx(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
u32 ucr1, ucr4, usr2;
if (sport->tx_state == OFF)
@@ -465,9 +474,10 @@ static void imx_uart_stop_tx(struct uart_port *port)
}
}
+/* called with port.lock taken and irqs off */
static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loopback)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
u32 ucr1, ucr2, ucr4, uts;
ucr1 = imx_uart_readl(sport, UCR1);
@@ -512,7 +522,7 @@ static void imx_uart_stop_rx(struct uart_port *port)
/* called with port.lock taken and irqs off */
static void imx_uart_enable_ms(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
mod_timer(&sport->timer, jiffies);
@@ -663,7 +673,7 @@ static void imx_uart_dma_tx(struct imx_port *sport)
/* called with port.lock taken and irqs off */
static void imx_uart_start_tx(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
struct tty_port *tport = &sport->port.state->port;
u32 ucr1;
@@ -757,6 +767,21 @@ static irqreturn_t __imx_uart_rtsint(int irq, void *dev_id)
imx_uart_writel(sport, USR1_RTSD, USR1);
usr1 = imx_uart_readl(sport, USR1) & USR1_RTSS;
+ /*
+ * Update sport->old_status here, so any follow-up calls to
+ * imx_uart_mctrl_check() will be able to recognize that RTS
+ * state changed since last imx_uart_mctrl_check() call.
+ *
+ * In case RTS has been detected as asserted here and later on
+ * deasserted by the time imx_uart_mctrl_check() was called,
+ * imx_uart_mctrl_check() can detect the RTS state change and
+ * trigger uart_handle_cts_change() to unblock the port for
+ * further TX transfers.
+ */
+ if (usr1 & USR1_RTSS)
+ sport->old_status |= TIOCM_CTS;
+ else
+ sport->old_status &= ~TIOCM_CTS;
uart_handle_cts_change(&sport->port, usr1);
wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
@@ -798,6 +823,8 @@ static irqreturn_t imx_uart_txint(int irq, void *dev_id)
* issuing soft reset to the UART (just stop/start of RX does not help). Note
* that what we do here is sending isolated start bit about 2.4 times shorter
* than it is to be on UART configured baud rate.
+ *
+ * Called with port.lock taken and irqs off.
*/
static void imx_uart_check_flood(struct imx_port *sport, u32 usr2)
{
@@ -833,6 +860,7 @@ static void imx_uart_check_flood(struct imx_port *sport, u32 usr2)
}
}
+/* called with port.lock taken and irqs off */
static irqreturn_t __imx_uart_rxint(int irq, void *dev_id)
{
struct imx_port *sport = dev_id;
@@ -911,6 +939,7 @@ static void imx_uart_clear_rx_errors(struct imx_port *sport);
/*
* We have a modem side uart, so the meanings of RTS and CTS are inverted.
*/
+/* called with port.lock taken and irqs off */
static unsigned int imx_uart_get_hwmctrl(struct imx_port *sport)
{
unsigned int tmp = TIOCM_DSR;
@@ -933,6 +962,8 @@ static unsigned int imx_uart_get_hwmctrl(struct imx_port *sport)
/*
* Handle any change of modem status signal since we were last called.
+ *
+ * Called with port.lock taken and irqs off.
*/
static void imx_uart_mctrl_check(struct imx_port *sport)
{
@@ -1044,7 +1075,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
*/
static unsigned int imx_uart_tx_empty(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned int ret;
ret = (imx_uart_readl(sport, USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0;
@@ -1059,7 +1090,7 @@ static unsigned int imx_uart_tx_empty(struct uart_port *port)
/* called with port.lock taken and irqs off */
static unsigned int imx_uart_get_mctrl(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned int ret = imx_uart_get_hwmctrl(sport);
mctrl_gpio_get(sport->gpios, &ret);
@@ -1070,7 +1101,7 @@ static unsigned int imx_uart_get_mctrl(struct uart_port *port)
/* called with port.lock taken and irqs off */
static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
u32 ucr3, uts;
if (!(port->rs485.flags & SER_RS485_ENABLED)) {
@@ -1113,7 +1144,7 @@ static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
*/
static void imx_uart_break_ctl(struct uart_port *port, int break_state)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned long flags;
u32 ucr1;
@@ -1135,7 +1166,7 @@ static void imx_uart_break_ctl(struct uart_port *port, int break_state)
*/
static void imx_uart_timeout(struct timer_list *t)
{
- struct imx_port *sport = from_timer(sport, t, timer);
+ struct imx_port *sport = timer_container_of(sport, t, timer);
unsigned long flags;
if (sport->port.state) {
@@ -1272,6 +1303,7 @@ static int imx_uart_start_rx_dma(struct imx_port *sport)
return 0;
}
+/* called with port.lock taken and irqs off */
static void imx_uart_clear_rx_errors(struct imx_port *sport)
{
struct tty_port *port = &sport->port.state->port;
@@ -1308,6 +1340,7 @@ static void imx_uart_clear_rx_errors(struct imx_port *sport)
#define TXTL_DEFAULT 8
#define RXTL_DEFAULT 8 /* 8 characters or aging timer */
+#define RXTL_CONSOLE_DEFAULT 1
#define TXTL_DMA 8 /* DMA burst setting */
#define RXTL_DMA 9 /* DMA burst setting */
@@ -1402,6 +1435,7 @@ err:
return ret;
}
+/* called with port.lock taken and irqs off */
static void imx_uart_enable_dma(struct imx_port *sport)
{
u32 ucr1;
@@ -1425,7 +1459,7 @@ static void imx_uart_disable_dma(struct imx_port *sport)
ucr1 &= ~(UCR1_RXDMAEN | UCR1_TXDMAEN | UCR1_ATDMAEN);
imx_uart_writel(sport, ucr1, UCR1);
- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, sport->rxtl);
sport->dma_is_enabled = 0;
}
@@ -1435,7 +1469,7 @@ static void imx_uart_disable_dma(struct imx_port *sport)
static int imx_uart_startup(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
int retval;
unsigned long flags;
int dma_is_inited = 0;
@@ -1450,7 +1484,12 @@ static int imx_uart_startup(struct uart_port *port)
return retval;
}
- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+ if (uart_console(&sport->port))
+ sport->rxtl = RXTL_CONSOLE_DEFAULT;
+ else
+ sport->rxtl = RXTL_DEFAULT;
+
+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, sport->rxtl);
/* disable the DREN bit (Data Ready interrupt enable) before
* requesting IRQs
@@ -1549,7 +1588,7 @@ static int imx_uart_startup(struct uart_port *port)
static void imx_uart_shutdown(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned long flags;
u32 ucr1, ucr2, ucr4, uts;
int loops;
@@ -1576,7 +1615,7 @@ static void imx_uart_shutdown(struct uart_port *port)
imx_uart_dma_exit(sport);
}
- mctrl_gpio_disable_ms(sport->gpios);
+ mctrl_gpio_disable_ms_sync(sport->gpios);
uart_port_lock_irqsave(&sport->port, &flags);
ucr2 = imx_uart_readl(sport, UCR2);
@@ -1587,7 +1626,7 @@ static void imx_uart_shutdown(struct uart_port *port)
/*
* Stop our timer.
*/
- del_timer_sync(&sport->timer);
+ timer_delete_sync(&sport->timer);
/*
* Disable all interrupts, port and break condition.
@@ -1674,7 +1713,7 @@ static void imx_uart_shutdown(struct uart_port *port)
/* called with port.lock taken and irqs off */
static void imx_uart_flush_buffer(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
struct scatterlist *sgl = &sport->tx_sgl[0];
if (!sport->dma_chan_tx)
@@ -1701,7 +1740,7 @@ static void
imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
const struct ktermios *old)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned long flags;
u32 ucr2, old_ucr2, ufcr;
unsigned int baud, quot;
@@ -1720,7 +1759,7 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
old_csize = CS8;
}
- del_timer_sync(&sport->timer);
+ timer_delete_sync(&sport->timer);
/*
* Ask the core to calculate the divisor for us.
@@ -1904,7 +1943,7 @@ imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
static int imx_uart_poll_init(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned long flags;
u32 ucr1, ucr2;
int retval;
@@ -1916,7 +1955,7 @@ static int imx_uart_poll_init(struct uart_port *port)
if (retval)
clk_disable_unprepare(sport->clk_ipg);
- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, sport->rxtl);
uart_port_lock_irqsave(&sport->port, &flags);
@@ -1953,7 +1992,7 @@ static int imx_uart_poll_init(struct uart_port *port)
static int imx_uart_poll_get_char(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
if (!(imx_uart_readl(sport, USR2) & USR2_RDR))
return NO_POLL_CHAR;
@@ -1962,7 +2001,7 @@ static int imx_uart_poll_get_char(struct uart_port *port)
static void imx_uart_poll_put_char(struct uart_port *port, unsigned char c)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
unsigned int status;
/* drain */
@@ -1984,7 +2023,7 @@ static void imx_uart_poll_put_char(struct uart_port *port, unsigned char c)
static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termios,
struct serial_rs485 *rs485conf)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
u32 ucr2, ufcr;
if (rs485conf->flags & SER_RS485_ENABLED) {
@@ -2008,7 +2047,7 @@ static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termio
/* If the receiver trigger is 0, set it to a default value */
ufcr = imx_uart_readl(sport, UFCR);
if ((ufcr & UFCR_RXTL_MASK) == 0)
- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, sport->rxtl);
imx_uart_start_rx(port);
}
@@ -2043,32 +2082,40 @@ static struct imx_port *imx_uart_ports[UART_NR];
#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
static void imx_uart_console_putchar(struct uart_port *port, unsigned char ch)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct imx_port *sport = to_imx_port(port);
while (imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL)
barrier();
imx_uart_writel(sport, ch, URTX0);
+
+ sport->last_putchar_was_newline = (ch == '\n');
}
-/*
- * Interrupts are disabled on entering
- */
-static void
-imx_uart_console_write(struct console *co, const char *s, unsigned int count)
+static void imx_uart_console_device_lock(struct console *co, unsigned long *flags)
+{
+ struct uart_port *up = &imx_uart_ports[co->index]->port;
+
+ return __uart_port_lock_irqsave(up, flags);
+}
+
+static void imx_uart_console_device_unlock(struct console *co, unsigned long flags)
+{
+ struct uart_port *up = &imx_uart_ports[co->index]->port;
+
+ return __uart_port_unlock_irqrestore(up, flags);
+}
+
+static void imx_uart_console_write_atomic(struct console *co,
+ struct nbcon_write_context *wctxt)
{
struct imx_port *sport = imx_uart_ports[co->index];
+ struct uart_port *port = &sport->port;
struct imx_port_ucrs old_ucr;
- unsigned long flags;
unsigned int ucr1, usr2;
- int locked = 1;
- if (sport->port.sysrq)
- locked = 0;
- else if (oops_in_progress)
- locked = uart_port_trylock_irqsave(&sport->port, &flags);
- else
- uart_port_lock_irqsave(&sport->port, &flags);
+ if (!nbcon_enter_unsafe(wctxt))
+ return;
/*
* First, save UCR1/2/3 and then disable interrupts
@@ -2082,10 +2129,12 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN);
imx_uart_writel(sport, ucr1, UCR1);
-
imx_uart_writel(sport, old_ucr.ucr2 | UCR2_TXEN, UCR2);
- uart_console_write(&sport->port, s, count, imx_uart_console_putchar);
+ if (!sport->last_putchar_was_newline)
+ uart_console_write(port, "\n", 1, imx_uart_console_putchar);
+ uart_console_write(port, wctxt->outbuf, wctxt->len,
+ imx_uart_console_putchar);
/*
* Finally, wait for transmitter to become empty
@@ -2095,8 +2144,73 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
0, USEC_PER_SEC, false, sport, USR2);
imx_uart_ucrs_restore(sport, &old_ucr);
- if (locked)
- uart_port_unlock_irqrestore(&sport->port, flags);
+ nbcon_exit_unsafe(wctxt);
+}
+
+static void imx_uart_console_write_thread(struct console *co,
+ struct nbcon_write_context *wctxt)
+{
+ struct imx_port *sport = imx_uart_ports[co->index];
+ struct uart_port *port = &sport->port;
+ struct imx_port_ucrs old_ucr;
+ unsigned int ucr1, usr2;
+
+ if (!nbcon_enter_unsafe(wctxt))
+ return;
+
+ /*
+ * First, save UCR1/2/3 and then disable interrupts
+ */
+ imx_uart_ucrs_save(sport, &old_ucr);
+ ucr1 = old_ucr.ucr1;
+
+ if (imx_uart_is_imx1(sport))
+ ucr1 |= IMX1_UCR1_UARTCLKEN;
+ ucr1 |= UCR1_UARTEN;
+ ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN);
+
+ imx_uart_writel(sport, ucr1, UCR1);
+ imx_uart_writel(sport, old_ucr.ucr2 | UCR2_TXEN, UCR2);
+
+ if (nbcon_exit_unsafe(wctxt)) {
+ int len = READ_ONCE(wctxt->len);
+ int i;
+
+ /*
+ * Write out the message. Toggle unsafe for each byte in order
+ * to give another (higher priority) context the opportunity
+ * for a friendly takeover. If such a takeover occurs, this
+ * context must reacquire ownership in order to perform final
+ * actions (such as re-enabling the interrupts).
+ *
+ * IMPORTANT: wctxt->outbuf and wctxt->len are no longer valid
+ * after a reacquire so writing the message must be
+ * aborted.
+ */
+ for (i = 0; i < len; i++) {
+ if (!nbcon_enter_unsafe(wctxt))
+ break;
+
+ uart_console_write(port, wctxt->outbuf + i, 1,
+ imx_uart_console_putchar);
+
+ if (!nbcon_exit_unsafe(wctxt))
+ break;
+ }
+ }
+
+ while (!nbcon_enter_unsafe(wctxt))
+ nbcon_reacquire_nobuf(wctxt);
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore UCR1/2/3
+ */
+ read_poll_timeout(imx_uart_readl, usr2, usr2 & USR2_TXDC,
+ 0, USEC_PER_SEC, false, sport, USR2);
+ imx_uart_ucrs_restore(sport, &old_ucr);
+
+ nbcon_exit_unsafe(wctxt);
}
/*
@@ -2188,12 +2302,14 @@ imx_uart_console_setup(struct console *co, char *options)
if (retval)
goto error_console;
+ sport->last_putchar_was_newline = true;
+
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
imx_uart_console_get_options(sport, &baud, &parity, &bits);
- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, sport->rxtl);
retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
@@ -2224,11 +2340,14 @@ imx_uart_console_exit(struct console *co)
static struct uart_driver imx_uart_uart_driver;
static struct console imx_uart_console = {
.name = DEV_NAME,
- .write = imx_uart_console_write,
+ .write_atomic = imx_uart_console_write_atomic,
+ .write_thread = imx_uart_console_write_thread,
+ .device_lock = imx_uart_console_device_lock,
+ .device_unlock = imx_uart_console_device_unlock,
+ .flags = CON_PRINTBUFFER | CON_NBCON,
.device = uart_console_device,
.setup = imx_uart_console_setup,
.exit = imx_uart_console_exit,
- .flags = CON_PRINTBUFFER,
.index = -1,
.data = &imx_uart_uart_driver,
};
@@ -2470,10 +2589,10 @@ static int imx_uart_probe(struct platform_device *pdev)
imx_uart_writel(sport, ucr3, UCR3);
}
- hrtimer_init(&sport->trigger_start_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- hrtimer_init(&sport->trigger_stop_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- sport->trigger_start_tx.function = imx_trigger_start_tx;
- sport->trigger_stop_tx.function = imx_trigger_stop_tx;
+ hrtimer_setup(&sport->trigger_start_tx, imx_trigger_start_tx, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ hrtimer_setup(&sport->trigger_stop_tx, imx_trigger_stop_tx, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
/*
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
@@ -2575,16 +2694,35 @@ static void imx_uart_save_context(struct imx_port *sport)
uart_port_unlock_irqrestore(&sport->port, flags);
}
+/* called with irq off */
static void imx_uart_enable_wakeup(struct imx_port *sport, bool on)
{
- u32 ucr3;
+ struct tty_port *port = &sport->port.state->port;
+ struct device *tty_dev;
+ bool may_wake = false, wake_active = false;
+ u32 ucr3, usr1;
+
+ scoped_guard(tty_port_tty, port) {
+ struct tty_struct *tty = scoped_tty();
+
+ tty_dev = tty->dev;
+ may_wake = tty_dev && device_may_wakeup(tty_dev);
+ }
+
+ /* only configure the wake register when device set as wakeup source */
+ if (!may_wake)
+ return;
+
+ uart_port_lock_irq(&sport->port);
+ usr1 = imx_uart_readl(sport, USR1);
ucr3 = imx_uart_readl(sport, UCR3);
if (on) {
imx_uart_writel(sport, USR1_AWAKE, USR1);
ucr3 |= UCR3_AWAKEN;
} else {
ucr3 &= ~UCR3_AWAKEN;
+ wake_active = usr1 & USR1_AWAKE;
}
imx_uart_writel(sport, ucr3, UCR3);
@@ -2595,9 +2733,15 @@ static void imx_uart_enable_wakeup(struct imx_port *sport, bool on)
ucr1 |= UCR1_RTSDEN;
} else {
ucr1 &= ~UCR1_RTSDEN;
+ wake_active = wake_active || (usr1 & USR1_RTSD);
}
imx_uart_writel(sport, ucr1, UCR1);
}
+
+ if (wake_active && irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq)))
+ pm_wakeup_event(tty_port_tty_get(port)->dev, 0);
+
+ uart_port_unlock_irq(&sport->port);
}
static int imx_uart_suspend_noirq(struct device *dev)
@@ -2697,7 +2841,7 @@ static const struct dev_pm_ops imx_uart_pm_ops = {
static struct platform_driver imx_uart_platform_driver = {
.probe = imx_uart_probe,
- .remove_new = imx_uart_remove,
+ .remove = imx_uart_remove,
.driver = {
.name = "imx-uart",