summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/imx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-02-01 09:46:00 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-01 09:46:00 -0800
commitdb5933225f2fe50d3b91ebbba73ed9c3b703b99a (patch)
treeb0178b4e74c9284d8c7ca6beb46e999b3b15d1f9 /drivers/tty/serial/imx.c
parente4ee8b85b7657d9c769b727038faabdc2e6a3412 (diff)
parentc7e1b4059075c9e8eed101d7cc5da43e95eb5e18 (diff)
downloadlinux-db5933225f2fe50d3b91ebbba73ed9c3b703b99a.tar.gz
linux-db5933225f2fe50d3b91ebbba73ed9c3b703b99a.tar.bz2
linux-db5933225f2fe50d3b91ebbba73ed9c3b703b99a.zip
Merge tag 'tty-4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/staging driver updates from Greg KH: "Here is the big tty/serial driver update for 4.16-rc1. The usual number of various serial driver fixes and updates to try to get them to work with crazy hardware configurations (seriously, how many different ways are hardware engineers going to come up with to hook up a simple UART?) There is also some serdev bugfixes and updates, as well as a smattering of other small fixes in here. All have been in the linux-next tree for a while, with no reported issues" * tag 'tty-4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (65 commits) tty: serial: exar: Relocate sleep wake-up handling tty: fix data race between tty_init_dev and flush of buf serial: imx: fix endless loop during suspend serial: core: mark port as initialized after successful IRQ change serdev: only match serdev devices serdev: do not generate modaliases for controllers serial: mxs-auart: don't use GPIOF_* with gpiod_get_direction serial: 8250_dw: Revert "Improve clock rate setting" MAINTAINERS: Add myself as designated reviewer for 8250_dw gpio: serial: max310x: Support open-drain configuration for GPIOs serdev: Fix serdev_uevent failure on ACPI enumerated serdev-controllers serial: 8250_ingenic: Parse earlycon options serial: 8250_ingenic: Add support for the JZ4770 SoC serial: core: Make uart_parse_options take const char* argument serial: 8250_of: fix return code when probe function fails to get reset serial: imx: Only wakeup via RTSDEN bit if the system has RTS/CTS serial: 8250_uniphier: fix error return code in uniphier_uart_probe() tty: n_gsm: Allow ADM response in addition to UA for control dlci tty: omap-serial: Fix initial on-boot RTS GPIO level tty: serial: jsm: Add one check against NULL pointer dereference ...
Diffstat (limited to 'drivers/tty/serial/imx.c')
-rw-r--r--drivers/tty/serial/imx.c93
1 files changed, 40 insertions, 53 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index e4b3d9123a03..1d7ca382bc12 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -703,25 +703,6 @@ out:
return IRQ_HANDLED;
}
-static void imx_disable_rx_int(struct imx_port *sport)
-{
- unsigned long temp;
-
- /* disable the receiver ready and aging timer interrupts */
- temp = readl(sport->port.membase + UCR1);
- temp &= ~(UCR1_RRDYEN);
- writel(temp, sport->port.membase + UCR1);
-
- temp = readl(sport->port.membase + UCR2);
- temp &= ~(UCR2_ATEN);
- writel(temp, sport->port.membase + UCR2);
-
- /* disable the rx errors interrupts */
- temp = readl(sport->port.membase + UCR4);
- temp &= ~UCR4_OREN;
- writel(temp, sport->port.membase + UCR4);
-}
-
static void clear_rx_errors(struct imx_port *sport);
/*
@@ -1252,18 +1233,21 @@ static int imx_startup(struct uart_port *port)
if (sport->dma_is_inited && !sport->dma_is_enabled)
imx_enable_dma(sport);
- temp = readl(sport->port.membase + UCR1);
- temp |= UCR1_RRDYEN | UCR1_UARTEN;
+ temp = readl(sport->port.membase + UCR1) & ~UCR1_RRDYEN;
+ if (!sport->dma_is_enabled)
+ temp |= UCR1_RRDYEN;
+ temp |= UCR1_UARTEN;
if (sport->have_rtscts)
temp |= UCR1_RTSDEN;
writel(temp, sport->port.membase + UCR1);
- temp = readl(sport->port.membase + UCR4);
- temp |= UCR4_OREN;
+ temp = readl(sport->port.membase + UCR4) & ~UCR4_OREN;
+ if (!sport->dma_is_enabled)
+ temp |= UCR4_OREN;
writel(temp, sport->port.membase + UCR4);
- temp = readl(sport->port.membase + UCR2);
+ temp = readl(sport->port.membase + UCR2) & ~UCR2_ATEN;
temp |= (UCR2_RXEN | UCR2_TXEN);
if (!sport->have_rtscts)
temp |= UCR2_IRTS;
@@ -1297,10 +1281,8 @@ static int imx_startup(struct uart_port *port)
* In our iMX53 the average delay for the first reception dropped from
* approximately 35000 microseconds to 1000 microseconds.
*/
- if (sport->dma_is_enabled) {
- imx_disable_rx_int(sport);
+ if (sport->dma_is_enabled)
start_rx_dma(sport);
- }
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -2017,8 +1999,6 @@ static int serial_imx_probe_dt(struct imx_port *sport,
if (of_get_property(np, "rts-gpios", NULL))
sport->have_rtsgpio = 1;
- of_get_rs485_mode(np, &sport->port.rs485);
-
return 0;
}
#else
@@ -2080,7 +2060,6 @@ static int serial_imx_probe(struct platform_device *pdev)
sport->port.fifosize = 32;
sport->port.ops = &imx_pops;
sport->port.rs485_config = imx_rs485_config;
- sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND;
sport->port.flags = UPF_BOOT_AUTOCONF;
timer_setup(&sport->timer, imx_timeout, 0);
@@ -2111,6 +2090,14 @@ static int serial_imx_probe(struct platform_device *pdev)
return ret;
}
+ uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
+
+ if (sport->port.rs485.flags & SER_RS485_ENABLED &&
+ (!sport->have_rtscts || !sport->have_rtsgpio))
+ dev_err(&pdev->dev, "no RTS control, disabling rs485\n");
+
+ imx_rs485_config(&sport->port, &sport->port.rs485);
+
/* Disable interrupts before requesting them */
reg = readl_relaxed(sport->port.membase + UCR1);
reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
@@ -2232,29 +2219,28 @@ static void serial_imx_enable_wakeup(struct imx_port *sport, bool on)
unsigned int val;
val = readl(sport->port.membase + UCR3);
- if (on)
+ if (on) {
+ writel(USR1_AWAKE, sport->port.membase + USR1);
val |= UCR3_AWAKEN;
+ }
else
val &= ~UCR3_AWAKEN;
writel(val, sport->port.membase + UCR3);
- val = readl(sport->port.membase + UCR1);
- if (on)
- val |= UCR1_RTSDEN;
- else
- val &= ~UCR1_RTSDEN;
- writel(val, sport->port.membase + UCR1);
+ if (sport->have_rtscts) {
+ val = readl(sport->port.membase + UCR1);
+ if (on)
+ val |= UCR1_RTSDEN;
+ else
+ val &= ~UCR1_RTSDEN;
+ writel(val, sport->port.membase + UCR1);
+ }
}
static int imx_serial_port_suspend_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct imx_port *sport = platform_get_drvdata(pdev);
- int ret;
-
- ret = clk_enable(sport->clk_ipg);
- if (ret)
- return ret;
serial_imx_save_context(sport);
@@ -2275,8 +2261,6 @@ static int imx_serial_port_resume_noirq(struct device *dev)
serial_imx_restore_context(sport);
- clk_disable(sport->clk_ipg);
-
return 0;
}
@@ -2284,15 +2268,19 @@ static int imx_serial_port_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct imx_port *sport = platform_get_drvdata(pdev);
-
- /* enable wakeup from i.MX UART */
- serial_imx_enable_wakeup(sport, true);
+ int ret;
uart_suspend_port(&imx_reg, &sport->port);
disable_irq(sport->port.irq);
- /* Needed to enable clock in suspend_noirq */
- return clk_prepare(sport->clk_ipg);
+ ret = clk_prepare_enable(sport->clk_ipg);
+ if (ret)
+ return ret;
+
+ /* enable wakeup from i.MX UART */
+ serial_imx_enable_wakeup(sport, true);
+
+ return 0;
}
static int imx_serial_port_resume(struct device *dev)
@@ -2306,7 +2294,7 @@ static int imx_serial_port_resume(struct device *dev)
uart_resume_port(&imx_reg, &sport->port);
enable_irq(sport->port.irq);
- clk_unprepare(sport->clk_ipg);
+ clk_disable_unprepare(sport->clk_ipg);
return 0;
}
@@ -2318,8 +2306,7 @@ static int imx_serial_port_freeze(struct device *dev)
uart_suspend_port(&imx_reg, &sport->port);
- /* Needed to enable clock in suspend_noirq */
- return clk_prepare(sport->clk_ipg);
+ return clk_prepare_enable(sport->clk_ipg);
}
static int imx_serial_port_thaw(struct device *dev)
@@ -2329,7 +2316,7 @@ static int imx_serial_port_thaw(struct device *dev)
uart_resume_port(&imx_reg, &sport->port);
- clk_unprepare(sport->clk_ipg);
+ clk_disable_unprepare(sport->clk_ipg);
return 0;
}