提交 7c573d7e 编写于 作者: J Janusz Uzycki 提交者: Greg Kroah-Hartman

serial: mxs-auart: use mctrl_gpio helpers for handling modem signals

Dedicated CTS and RTS pins are unusable together with a lot of other
peripherals because they share the same line. Pinctrl is limited.

Moreover, the AUART controller doesn't handle DTR/DSR/DCD/RI signals,
so we have to control them via GPIO.

This patch permits to use GPIOs to control the CTS/RTS/DTR/DSR/DCD/RI
signals.
Signed-off-by: NJanusz Uzycki <j.uzycki@elproma.com.pl>
Reviewed-by: NRichard Genoud <richard.genoud@gmail.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 42b4eba0
...@@ -11,8 +11,13 @@ Required properties: ...@@ -11,8 +11,13 @@ Required properties:
- dma-names: "rx" for RX channel, "tx" for TX channel. - dma-names: "rx" for RX channel, "tx" for TX channel.
Optional properties: Optional properties:
- fsl,uart-has-rtscts : Indicate the UART has RTS and CTS lines, - fsl,uart-has-rtscts : Indicate the UART has RTS and CTS lines
for hardware flow control,
it also means you enable the DMA support for this UART. it also means you enable the DMA support for this UART.
- {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD
line respectively. It will use specified PIO instead of the peripheral
function pin for the USART feature.
If unsure, don't specify this property.
Example: Example:
auart0: serial@8006a000 { auart0: serial@8006a000 {
...@@ -21,6 +26,9 @@ auart0: serial@8006a000 { ...@@ -21,6 +26,9 @@ auart0: serial@8006a000 {
interrupts = <112>; interrupts = <112>;
dmas = <&dma_apbx 8>, <&dma_apbx 9>; dmas = <&dma_apbx 8>, <&dma_apbx 9>;
dma-names = "rx", "tx"; dma-names = "rx", "tx";
cts-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
dsr-gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
dcd-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
}; };
Note: Each auart port should have an alias correctly numbered in "aliases" Note: Each auart port should have an alias correctly numbered in "aliases"
......
...@@ -1408,6 +1408,7 @@ config SERIAL_MXS_AUART ...@@ -1408,6 +1408,7 @@ config SERIAL_MXS_AUART
depends on ARCH_MXS depends on ARCH_MXS
tristate "MXS AUART support" tristate "MXS AUART support"
select SERIAL_CORE select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB
help help
This driver supports the MXS Application UART (AUART) port. This driver supports the MXS Application UART (AUART) port.
......
...@@ -42,6 +42,9 @@ ...@@ -42,6 +42,9 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <linux/err.h>
#include "serial_mctrl_gpio.h"
#define MXS_AUART_PORTS 5 #define MXS_AUART_PORTS 5
#define MXS_AUART_FIFO_SIZE 16 #define MXS_AUART_FIFO_SIZE 16
...@@ -158,6 +161,8 @@ struct mxs_auart_port { ...@@ -158,6 +161,8 @@ struct mxs_auart_port {
struct scatterlist rx_sgl; struct scatterlist rx_sgl;
struct dma_chan *rx_dma_chan; struct dma_chan *rx_dma_chan;
void *rx_dma_buf; void *rx_dma_buf;
struct mctrl_gpios *gpios;
}; };
static struct platform_device_id mxs_auart_devtype[] = { static struct platform_device_id mxs_auart_devtype[] = {
...@@ -405,6 +410,8 @@ static void mxs_auart_release_port(struct uart_port *u) ...@@ -405,6 +410,8 @@ static void mxs_auart_release_port(struct uart_port *u)
static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl) static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
{ {
struct mxs_auart_port *s = to_auart_port(u);
u32 ctrl = readl(u->membase + AUART_CTRL2); u32 ctrl = readl(u->membase + AUART_CTRL2);
ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS); ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS);
...@@ -416,17 +423,20 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl) ...@@ -416,17 +423,20 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
} }
writel(ctrl, u->membase + AUART_CTRL2); writel(ctrl, u->membase + AUART_CTRL2);
mctrl_gpio_set(s->gpios, mctrl);
} }
static u32 mxs_auart_get_mctrl(struct uart_port *u) static u32 mxs_auart_get_mctrl(struct uart_port *u)
{ {
struct mxs_auart_port *s = to_auart_port(u);
u32 stat = readl(u->membase + AUART_STAT); u32 stat = readl(u->membase + AUART_STAT);
u32 mctrl = 0; u32 mctrl = 0;
if (stat & AUART_STAT_CTS) if (stat & AUART_STAT_CTS)
mctrl |= TIOCM_CTS; mctrl |= TIOCM_CTS;
return mctrl; return mctrl_gpio_get(s->gpios, &mctrl);
} }
static int mxs_auart_dma_prep_rx(struct mxs_auart_port *s); static int mxs_auart_dma_prep_rx(struct mxs_auart_port *s);
...@@ -554,6 +564,10 @@ static int mxs_auart_dma_init(struct mxs_auart_port *s) ...@@ -554,6 +564,10 @@ static int mxs_auart_dma_init(struct mxs_auart_port *s)
} }
#define RTS_AT_AUART() IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(s->gpios, \
UART_GPIO_RTS))
#define CTS_AT_AUART() IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(s->gpios, \
UART_GPIO_CTS))
static void mxs_auart_settermios(struct uart_port *u, static void mxs_auart_settermios(struct uart_port *u,
struct ktermios *termios, struct ktermios *termios,
struct ktermios *old) struct ktermios *old)
...@@ -630,6 +644,7 @@ static void mxs_auart_settermios(struct uart_port *u, ...@@ -630,6 +644,7 @@ static void mxs_auart_settermios(struct uart_port *u,
ctrl |= AUART_LINECTRL_STP2; ctrl |= AUART_LINECTRL_STP2;
/* figure out the hardware flow control settings */ /* figure out the hardware flow control settings */
ctrl2 &= ~(AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN);
if (cflag & CRTSCTS) { if (cflag & CRTSCTS) {
/* /*
* The DMA has a bug(see errata:2836) in mx23. * The DMA has a bug(see errata:2836) in mx23.
...@@ -644,9 +659,11 @@ static void mxs_auart_settermios(struct uart_port *u, ...@@ -644,9 +659,11 @@ static void mxs_auart_settermios(struct uart_port *u,
ctrl2 |= AUART_CTRL2_TXDMAE | AUART_CTRL2_RXDMAE ctrl2 |= AUART_CTRL2_TXDMAE | AUART_CTRL2_RXDMAE
| AUART_CTRL2_DMAONERR; | AUART_CTRL2_DMAONERR;
} }
ctrl2 |= AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN; /* Even if RTS is GPIO line RTSEN can be enabled because
} else { * the pinctrl configuration decides about RTS pin function */
ctrl2 &= ~(AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN); ctrl2 |= AUART_CTRL2_RTSEN;
if (CTS_AT_AUART())
ctrl2 |= AUART_CTRL2_CTSEN;
} }
/* set baud rate */ /* set baud rate */
...@@ -690,7 +707,9 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context) ...@@ -690,7 +707,9 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
s->port.membase + AUART_INTR_CLR); s->port.membase + AUART_INTR_CLR);
if (istat & AUART_INTR_CTSMIS) { if (istat & AUART_INTR_CTSMIS) {
uart_handle_cts_change(&s->port, stat & AUART_STAT_CTS); if (CTS_AT_AUART())
uart_handle_cts_change(&s->port,
stat & AUART_STAT_CTS);
writel(AUART_INTR_CTSMIS, writel(AUART_INTR_CTSMIS,
s->port.membase + AUART_INTR_CLR); s->port.membase + AUART_INTR_CLR);
istat &= ~AUART_INTR_CTSMIS; istat &= ~AUART_INTR_CTSMIS;
...@@ -1014,6 +1033,23 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s, ...@@ -1014,6 +1033,23 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
return 0; return 0;
} }
static bool mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
{
s->gpios = mctrl_gpio_init(dev, 0);
if (IS_ERR_OR_NULL(s->gpios))
return false;
/* Block (enabled before) DMA option if RTS or CTS is GPIO line */
if (!RTS_AT_AUART() || !CTS_AT_AUART()) {
if (test_bit(MXS_AUART_RTSCTS, &s->flags))
dev_warn(dev,
"DMA and flow control via gpio may cause some problems. DMA disabled!\n");
clear_bit(MXS_AUART_RTSCTS, &s->flags);
}
return true;
}
static int mxs_auart_probe(struct platform_device *pdev) static int mxs_auart_probe(struct platform_device *pdev)
{ {
const struct of_device_id *of_id = const struct of_device_id *of_id =
...@@ -1069,6 +1105,10 @@ static int mxs_auart_probe(struct platform_device *pdev) ...@@ -1069,6 +1105,10 @@ static int mxs_auart_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, s); platform_set_drvdata(pdev, s);
if (!mxs_auart_init_gpios(s, &pdev->dev))
dev_err(&pdev->dev,
"Failed to initialize GPIOs. The serial port may not work as expected\n");
auart_port[s->port.line] = s; auart_port[s->port.line] = s;
mxs_auart_reset(&s->port); mxs_auart_reset(&s->port);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册