* Re: [PATCH V2 2/6] tty: serial: lpuart: add little endian 32 bit register support
From: Andy Shevchenko @ 2017-05-15 13:36 UTC (permalink / raw)
To: Dong Aisheng
Cc: fugang.duan, dongas86, Greg Kroah-Hartman, yangbo.lu,
linux-kernel@vger.kernel.org, Stefan Agner, Mingkai.Hu,
linux-serial@vger.kernel.org, Jiri Slaby, linux-arm Mailing List
In-Reply-To: <1494834539-17523-3-git-send-email-aisheng.dong@nxp.com>
On Mon, May 15, 2017 at 10:48 AM, Dong Aisheng <aisheng.dong@nxp.com> wrote:
> It's based on the exist lpuart32 read/write implementation.
Same as per previous comment (perhaps not in other UART driver, but
some might have been using device property for that.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH V2 1/6] tty: serial: lpuart: introduce lpuart_soc_data to represent SoC property
From: Andy Shevchenko @ 2017-05-15 13:35 UTC (permalink / raw)
To: Dong Aisheng
Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm Mailing List, Greg Kroah-Hartman, Jiri Slaby,
fugang.duan, Stefan Agner, dongas86, Mingkai.Hu, yangbo.lu
In-Reply-To: <1494834539-17523-2-git-send-email-aisheng.dong@nxp.com>
On Mon, May 15, 2017 at 10:48 AM, Dong Aisheng <aisheng.dong@nxp.com> wrote:
> This is used to dynamically check the SoC specific lpuart properies.
> Currently only the checking of 32 bit register width is added which
> functions the same as before. More will be added later for supporting
> new chips.
For the rest it might be okay, but don't we have specific properties
for register width and offset for UART? I think I saw something like
that in other drivers.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH V2 6/6] tty: serial: lpuart: add a more accurate baud rate calculation method
From: Dong Aisheng @ 2017-05-15 7:48 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, linux-arm-kernel, gregkh, jslaby, fugang.duan,
stefan, dongas86, Mingkai.Hu, yangbo.lu, Dong Aisheng
In-Reply-To: <1494834539-17523-1-git-send-email-aisheng.dong@nxp.com>
On new LPUART versions, the oversampling ratio for the receiver can be
changed from 4x (00011) to 32x (11111) which could help us get a more
accurate baud rate divider.
The idea is to use the best OSR (over-sampling rate) possible.
Note, OSR is typically hard-set to 16 in other LPUART instantiations.
Loop to find the best OSR value possible, one that generates minimum
baud diff iterate through the rest of the supported values of OSR.
Currently only i.MX7ULP is using it.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Mingkai Hu <Mingkai.Hu@nxp.com>
Cc: Yangbo Lu <yangbo.lu@nxp.com>
Acked-by: Fugang Duan <fugang.duan@nxp.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
drivers/tty/serial/fsl_lpuart.c | 85 ++++++++++++++++++++++++++++++++++++++---
1 file changed, 79 insertions(+), 6 deletions(-)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 107d0911..bda4b0c 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -140,6 +140,8 @@
#define UARTBAUD_SBNS 0x00002000
#define UARTBAUD_SBR 0x00000000
#define UARTBAUD_SBR_MASK 0x1fff
+#define UARTBAUD_OSR_MASK 0x1f
+#define UARTBAUD_OSR_SHIFT 24
#define UARTSTAT_LBKDIF 0x80000000
#define UARTSTAT_RXEDGIF 0x40000000
@@ -1506,6 +1508,72 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
}
static void
+lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
+{
+ u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp;
+ u32 clk = sport->port.uartclk;
+
+ /*
+ * The idea is to use the best OSR (over-sampling rate) possible.
+ * Note, OSR is typically hard-set to 16 in other LPUART instantiations.
+ * Loop to find the best OSR value possible, one that generates minimum
+ * baud_diff iterate through the rest of the supported values of OSR.
+ *
+ * Calculation Formula:
+ * Baud Rate = baud clock / ((OSR+1) × SBR)
+ */
+ baud_diff = baudrate;
+ osr = 0;
+ sbr = 0;
+
+ for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
+ /* calculate the temporary sbr value */
+ tmp_sbr = (clk / (baudrate * tmp_osr));
+ if (tmp_sbr == 0)
+ tmp_sbr = 1;
+
+ /*
+ * calculate the baud rate difference based on the temporary
+ * osr and sbr values
+ */
+ tmp_diff = clk / (tmp_osr * tmp_sbr) - baudrate;
+
+ /* select best values between sbr and sbr+1 */
+ tmp = clk / (tmp_osr * (tmp_sbr + 1));
+ if (tmp_diff > (baudrate - tmp)) {
+ tmp_diff = baudrate - tmp;
+ tmp_sbr++;
+ }
+
+ if (tmp_diff <= baud_diff) {
+ baud_diff = tmp_diff;
+ osr = tmp_osr;
+ sbr = tmp_sbr;
+ }
+ }
+
+ /* handle buadrate outside acceptable rate */
+ if (baud_diff > ((baudrate / 100) * 3))
+ dev_warn(sport->port.dev,
+ "unacceptable baud rate difference of more than 3%%\n");
+
+ tmp = lpuart32_read(sport->port.membase + UARTBAUD);
+
+ if ((osr > 3) && (osr < 8))
+ tmp |= UARTBAUD_BOTHEDGE;
+
+ tmp &= ~(UARTBAUD_OSR_MASK << UARTBAUD_OSR_SHIFT);
+ tmp |= (((osr-1) & UARTBAUD_OSR_MASK) << UARTBAUD_OSR_SHIFT);
+
+ tmp &= ~UARTBAUD_SBR_MASK;
+ tmp |= sbr & UARTBAUD_SBR_MASK;
+
+ tmp &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE);
+
+ lpuart32_write(tmp, sport->port.membase + UARTBAUD);
+}
+
+static void
lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
@@ -1611,12 +1679,17 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
lpuart32_write(old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
sport->port.membase + UARTCTRL);
- sbr = sport->port.uartclk / (16 * baud);
- bd &= ~UARTBAUD_SBR_MASK;
- bd |= sbr & UARTBAUD_SBR_MASK;
- bd |= UARTBAUD_BOTHEDGE;
- bd &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE);
- lpuart32_write(bd, sport->port.membase + UARTBAUD);
+ if (of_device_is_compatible(port->dev->of_node, "fsl,imx7ulp-lpuart")) {
+ lpuart32_serial_setbrg(sport, baud);
+ } else {
+ sbr = sport->port.uartclk / (16 * baud);
+ bd &= ~UARTBAUD_SBR_MASK;
+ bd |= sbr & UARTBAUD_SBR_MASK;
+ bd |= UARTBAUD_BOTHEDGE;
+ bd &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE);
+ lpuart32_write(bd, sport->port.membase + UARTBAUD);
+ }
+
lpuart32_write(modem, sport->port.membase + UARTMODIR);
lpuart32_write(ctrl, sport->port.membase + UARTCTRL);
/* restore control register */
--
2.7.4
^ permalink raw reply related
* [PATCH V2 5/6] tty: serial: lpuart: add earlycon support for imx7ulp
From: Dong Aisheng @ 2017-05-15 7:48 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, linux-arm-kernel, gregkh, jslaby, fugang.duan,
stefan, dongas86, Mingkai.Hu, yangbo.lu, Dong Aisheng
In-Reply-To: <1494834539-17523-1-git-send-email-aisheng.dong@nxp.com>
earlycon is executed quite early before the device tree probe,
so we need configure the correct reg_off for imx7ulp during
early console setup.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Mingkai Hu <Mingkai.Hu@nxp.com>
Cc: Yangbo Lu <yangbo.lu@nxp.com>
Acked-by: Fugang Duan <fugang.duan@nxp.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
Change Log:
v1->v2:
* updated due to lpuart_reg_off removed
---
drivers/tty/serial/fsl_lpuart.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index a3ee825..107d0911 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1976,8 +1976,20 @@ static int __init lpuart32_early_console_setup(struct earlycon_device *device,
return 0;
}
+static int __init lpuart32_imx_early_console_setup(struct earlycon_device *device,
+ const char *opt)
+{
+ if (!device->port.membase)
+ return -ENODEV;
+
+ device->port.membase += IMX_REG_OFF;
+ device->con->write = lpuart32_early_write;
+
+ return 0;
+}
OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
+OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup);
EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);
--
2.7.4
^ permalink raw reply related
* [PATCH V2 4/6] tty: serial: lpuart: add imx7ulp support
From: Dong Aisheng @ 2017-05-15 7:48 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, linux-arm-kernel, gregkh, jslaby, fugang.duan,
stefan, dongas86, Mingkai.Hu, yangbo.lu, Dong Aisheng
In-Reply-To: <1494834539-17523-1-git-send-email-aisheng.dong@nxp.com>
The lpuart of imx7ulp is basically the same as ls1021a. It's also
32 bit width register, but unlike ls1021a, it's little endian.
Besides that, imx7ulp lpuart has a minor different register layout
from ls1021a that it has four extra registers (verid, param, global,
pincfg) located at the beginning of register map, which are currently
not used by the driver and less to be used later.
To ease the register difference handling, we add a reg_off member
in lpuart_soc_data structure to represent if the normal
lpuart32_{read|write} requires plus a offset to hide the issue.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Mingkai Hu <Mingkai.Hu@nxp.com>
Cc: Yangbo Lu <yangbo.lu@nxp.com>
Acked-by: Fugang Duan <fugang.duan@nxp.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v1->v2:
* remove lpuart_reg_off according to Stefan's suggestion
---
drivers/tty/serial/fsl_lpuart.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index e72b397..a3ee825 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -231,6 +231,9 @@
#define DEV_NAME "ttyLP"
#define UART_NR 6
+/* IMX lpuart has four extra unused regs located at the beginning */
+#define IMX_REG_OFF 0x10
+
static bool lpuart_is_be;
struct lpuart_port {
@@ -263,6 +266,7 @@ struct lpuart_port {
struct lpuart_soc_data {
bool is_32;
bool is_be;
+ u8 reg_off;
};
static const struct lpuart_soc_data vf_data = {
@@ -272,11 +276,19 @@ static const struct lpuart_soc_data vf_data = {
static const struct lpuart_soc_data ls_data = {
.is_32 = true,
.is_be = true,
+ .reg_off = 0x0,
+};
+
+static struct lpuart_soc_data imx_data = {
+ .is_32 = true,
+ .is_be = false,
+ .reg_off = IMX_REG_OFF,
};
static const struct of_device_id lpuart_dt_ids[] = {
{ .compatible = "fsl,vf610-lpuart", .data = &vf_data, },
{ .compatible = "fsl,ls1021a-lpuart", .data = &ls_data, },
+ { .compatible = "fsl,imx7ulp-lpuart", .data = &imx_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
@@ -2014,6 +2026,7 @@ static int lpuart_probe(struct platform_device *pdev)
if (IS_ERR(sport->port.membase))
return PTR_ERR(sport->port.membase);
+ sport->port.membase += sdata->reg_off;
sport->port.mapbase = res->start;
sport->port.dev = &pdev->dev;
sport->port.type = PORT_LPUART;
--
2.7.4
^ permalink raw reply related
* [PATCH V2 3/6] dt-bindings: serial: fsl-lpuart: add i.MX7ULP support
From: Dong Aisheng @ 2017-05-15 7:48 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, linux-arm-kernel, gregkh, jslaby, fugang.duan,
stefan, dongas86, Mingkai.Hu, yangbo.lu, Dong Aisheng, devicetree
In-Reply-To: <1494834539-17523-1-git-send-email-aisheng.dong@nxp.com>
The lpuart of imx7ulp is basically the same as ls1021a. It's also
32 bit width register, but unlike ls1021a, it's little endian.
Besides that, imx7ulp lpuart has a minor different register layout
from ls1021a.
Cc: devicetree@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Mingkai Hu <Mingkai.Hu@nxp.com>
Cc: Yangbo Lu <yangbo.lu@nxp.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Fugang Duan <fugang.duan@nxp.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
Documentation/devicetree/bindings/serial/fsl-lpuart.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
index c95005e..a1252a0 100644
--- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
+++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
@@ -6,6 +6,8 @@ Required properties:
on Vybrid vf610 SoC with 8-bit register organization
- "fsl,ls1021a-lpuart" for lpuart compatible with the one integrated
on LS1021A SoC with 32-bit big-endian register organization
+ - "fsl,imx7ulp-lpuart" for lpuart compatible with the one integrated
+ on i.MX7ULP SoC with 32-bit little-endian register organization
- reg : Address and length of the register set for the device
- interrupts : Should contain uart interrupt
- clocks : phandle + clock specifier pairs, one for each entry in clock-names
--
2.7.4
^ permalink raw reply related
* [PATCH V2 2/6] tty: serial: lpuart: add little endian 32 bit register support
From: Dong Aisheng @ 2017-05-15 7:48 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, linux-arm-kernel, gregkh, jslaby, fugang.duan,
stefan, dongas86, Mingkai.Hu, yangbo.lu, Dong Aisheng
In-Reply-To: <1494834539-17523-1-git-send-email-aisheng.dong@nxp.com>
It's based on the exist lpuart32 read/write implementation.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com> (supporter:TTY LAYER)
Cc: Stefan Agner <stefan@agner.ch>
Cc: Mingkai Hu <Mingkai.Hu@nxp.com>
Cc: Yangbo Lu <yangbo.lu@nxp.com>
Acked-by: Fugang Duan <fugang.duan@nxp.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
drivers/tty/serial/fsl_lpuart.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 7204103..e72b397 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -231,6 +231,8 @@
#define DEV_NAME "ttyLP"
#define UART_NR 6
+static bool lpuart_is_be;
+
struct lpuart_port {
struct uart_port port;
struct clk *clk;
@@ -260,6 +262,7 @@ struct lpuart_port {
struct lpuart_soc_data {
bool is_32;
+ bool is_be;
};
static const struct lpuart_soc_data vf_data = {
@@ -268,6 +271,7 @@ static const struct lpuart_soc_data vf_data = {
static const struct lpuart_soc_data ls_data = {
.is_32 = true,
+ .is_be = true,
};
static const struct of_device_id lpuart_dt_ids[] = {
@@ -282,12 +286,15 @@ static void lpuart_dma_tx_complete(void *arg);
static u32 lpuart32_read(void __iomem *addr)
{
- return ioread32be(addr);
+ return lpuart_is_be ? ioread32be(addr) : readl(addr);
}
static void lpuart32_write(u32 val, void __iomem *addr)
{
- iowrite32be(val, addr);
+ if (lpuart_is_be)
+ iowrite32be(val, addr);
+ else
+ writel(val, addr);
}
static void lpuart_stop_tx(struct uart_port *port)
@@ -2000,6 +2007,7 @@ static int lpuart_probe(struct platform_device *pdev)
}
sport->port.line = ret;
sport->lpuart32 = sdata->is_32;
+ lpuart_is_be = sdata->is_be;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
sport->port.membase = devm_ioremap_resource(&pdev->dev, res);
--
2.7.4
^ permalink raw reply related
* [PATCH V2 1/6] tty: serial: lpuart: introduce lpuart_soc_data to represent SoC property
From: Dong Aisheng @ 2017-05-15 7:48 UTC (permalink / raw)
To: linux-serial
Cc: Dong Aisheng, fugang.duan, dongas86, gregkh, yangbo.lu,
linux-kernel, stefan, Mingkai.Hu, jslaby, linux-arm-kernel
In-Reply-To: <1494834539-17523-1-git-send-email-aisheng.dong@nxp.com>
This is used to dynamically check the SoC specific lpuart properies.
Currently only the checking of 32 bit register width is added which
functions the same as before. More will be added later for supporting
new chips.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Mingkai Hu <Mingkai.Hu@nxp.com>
Cc: Yangbo Lu <yangbo.lu@nxp.com>
Acked-by: Fugang Duan <fugang.duan@nxp.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v1->v2:
* make all soc_data const
---
drivers/tty/serial/fsl_lpuart.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 15df1ba7..7204103 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -258,13 +258,21 @@ struct lpuart_port {
wait_queue_head_t dma_wait;
};
+struct lpuart_soc_data {
+ bool is_32;
+};
+
+static const struct lpuart_soc_data vf_data = {
+ .is_32 = false,
+};
+
+static const struct lpuart_soc_data ls_data = {
+ .is_32 = true,
+};
+
static const struct of_device_id lpuart_dt_ids[] = {
- {
- .compatible = "fsl,vf610-lpuart",
- },
- {
- .compatible = "fsl,ls1021a-lpuart",
- },
+ { .compatible = "fsl,vf610-lpuart", .data = &vf_data, },
+ { .compatible = "fsl,ls1021a-lpuart", .data = &ls_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
@@ -1971,6 +1979,9 @@ static struct uart_driver lpuart_reg = {
static int lpuart_probe(struct platform_device *pdev)
{
+ const struct of_device_id *of_id = of_match_device(lpuart_dt_ids,
+ &pdev->dev);
+ const struct lpuart_soc_data *sdata = of_id->data;
struct device_node *np = pdev->dev.of_node;
struct lpuart_port *sport;
struct resource *res;
@@ -1988,7 +1999,7 @@ static int lpuart_probe(struct platform_device *pdev)
return ret;
}
sport->port.line = ret;
- sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart");
+ sport->lpuart32 = sdata->is_32;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
sport->port.membase = devm_ioremap_resource(&pdev->dev, res);
--
2.7.4
^ permalink raw reply related
* [PATCH V2 0/6] tty: serial: lpuart: add imx7ulp support
From: Dong Aisheng @ 2017-05-15 7:48 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, linux-arm-kernel, gregkh, jslaby, fugang.duan,
stefan, dongas86, Mingkai.Hu, yangbo.lu, Dong Aisheng
This patch series mainly intends to add imx7ulp support which is also
using FSL lpuart.
The lpuart in imx7ulp is basically the same as ls1021a. It's also
32 bit width register, but unlike ls1021a, it's little endian.
Besides that, imx7ulp lpuart has a minor different register layout
from ls1021a that it has four extra registers (verid, param, global,
pincfg) located at the beginning of register map, which are currently
not used by the driver and less to be used later.
Furthermore, this patch serial also add a new more accurate baud rate
calculation method as MX7ULP can't divide a suitable baud rate
with the default setting.
Currently the new baud rate calculation is only enabled on MX7ULP.
However, i guess the Layerscape may also be able to use it as there
seems to be no difference in baud rate setting register after checking
the Layerscape Reference Manual.
As i don't have Layerscape boards, i can't test it, so i only enable it
for MX7ULP by default to avoid a potential break.
I copied LayerScape guys in this series and hope they can help test later.
If it works on Layerscape as well, then they can switch to the new setting
too and totally remove the old stuff.
ChangeLog:
v1->v2:
* Patch 2/4/5 chagned, other no changes.
See individuals for details.
Dong Aisheng (6):
tty: serial: lpuart: introduce lpuart_soc_data to represent SoC
property
tty: serial: lpuart: add little endian 32 bit register support
dt-bindings: serial: fsl-lpuart: add i.MX7ULP support
tty: serial: lpuart: add imx7ulp support
tty: serial: lpuart: add earlycon support for imx7ulp
tty: serial: lpuart: add a more accurate baud rate calculation method
.../devicetree/bindings/serial/fsl-lpuart.txt | 2 +
drivers/tty/serial/fsl_lpuart.c | 147 ++++++++++++++++++---
2 files changed, 134 insertions(+), 15 deletions(-)
--
2.7.4
^ permalink raw reply
* Re: [PATCH v9 3/3] printk: fix double printing with earlycon
From: Aleksey Makarov @ 2017-05-14 21:01 UTC (permalink / raw)
To: Petr Mladek, Sergey Senozhatsky
Cc: Sabrina Dubroca, linux-serial, linux-kernel, Sudeep Holla,
Greg Kroah-Hartman, Peter Hurley, Jiri Slaby, Robin Murphy,
Steven Rostedt, Nair, Jayachandran, Sergey Senozhatsky
In-Reply-To: <20170512134655.GD31170@pathway.suse.cz>
On 05/12/2017 04:46 PM, Petr Mladek wrote:
> On Fri 2017-05-12 14:57:29, Petr Mladek wrote:
>> On Thu 2017-05-11 17:41:58, Sergey Senozhatsky wrote:
>>> On (05/11/17 17:24), Sergey Senozhatsky wrote:
>>>> On (05/09/17 10:29), Sabrina Dubroca wrote:
>>>> [..]
>>>>> That's caused a change of behavior in my qemu setup, with this cmdline
>>>>>
>>>>> root=/dev/sda1 console=ttyS1 console=ttyS0
>>>>>
>>>>> Before, the kernel logs appeared on ttyS1, and I logged in with ttyS0
>>>>> (with my setup, ttyS1 is a file and ttyS0 is unix socket). Now, the
>>>>> kernel logs go to ttyS0. I need to swap the two console= parameters to
>>>>> restore behavior.
>
> Do you actually need to define console=ttyS0 on the cmdline?
Exactly. You should specify a console on the command line only
if you want kernel logs on it. It's kernel bug that one of this
consoles does not receive kernel logs, see
Documentation/admin-guide/serial-console.rst
> IMHO, if register_console() was called for the unix socket, it
> would make logs appear on both ttyS0 and ttyS1. It seems
> that register_console() is called only for the console that
> stores logs into the file.
It's not quite accurate sentence. It's qemu who deals with file/socket and
it is transparent to kernel.
>>>>> adding
>>>>> console=tty0 anywhere on that cmdline makes the logs appear on both
>>>>> tty0 and one ttyS* (but only one of them, and the ordering of the
>>>>> ttyS* matters).
>
> I guess that it worked this way before. I mean that the logs appeared
> on both tty0 and one of ttyS*. The only difference should be that
> the patch changed the selected ttyS*. So this is still the same problem.
>
>
>> Hmm, I have no idea how to fix this. This is the case where
>> a registered console matches more entries from the command line.
>> The fix that caused this regression fixed exactly this situation
>> and we wanted to make the preferred console first.
>>
>> I am not sure if we broke some backward compatibility or actually made
>> it more predictable in the long term.
>
> I think that we actually fixed a very old bug. The last mentioned
> console= should be the preferred one and the logs are finally
> printed there. Or do I miss anything?
Last mentioned 'console=' (preferred console) is the console that
should become /dev/console. Its driver is returned by console_device().
In other respects the last mentioned console is not special,
so I believe it is irrelevant to the report.
Thank you
Aleksey Makarov
^ permalink raw reply
* Re: [PATCH v9 3/3] printk: fix double printing with earlycon
From: Aleksey Makarov @ 2017-05-14 20:37 UTC (permalink / raw)
To: Petr Mladek, Sergey Senozhatsky
Cc: Sabrina Dubroca, linux-serial, linux-kernel, Sudeep Holla,
Greg Kroah-Hartman, Peter Hurley, Jiri Slaby, Robin Murphy,
Steven Rostedt, Nair, Jayachandran, Sergey Senozhatsky
In-Reply-To: <20170512125729.GO3452@pathway.suse.cz>
On 05/12/2017 03:57 PM, Petr Mladek wrote:
> On Thu 2017-05-11 17:41:58, Sergey Senozhatsky wrote:
>> On (05/11/17 17:24), Sergey Senozhatsky wrote:
>>> On (05/09/17 10:29), Sabrina Dubroca wrote:
>>> [..]
>>>> That's caused a change of behavior in my qemu setup, with this cmdline
>>>>
>>>> root=/dev/sda1 console=ttyS1 console=ttyS0
>>>>
>>>> Before, the kernel logs appeared on ttyS1, and I logged in with ttyS0
>>>> (with my setup, ttyS1 is a file and ttyS0 is unix socket). Now, the
>>>> kernel logs go to ttyS0. I need to swap the two console= parameters to
>>>> restore behavior.
>>>>
>>>> There might be some other problem (in qemu?) though, because adding
>>>> console=tty0 anywhere on that cmdline makes the logs appear on both
>>>> tty0 and one ttyS* (but only one of them, and the ordering of the
>>>> ttyS* matters).
>>>
>>> thanks for the report.
>>>
>>> so we have ttyS1 first and ttyS0 last.
>>> after commit in question, register_console() iterates console_cmdline
>>> in reverse order so we see ttyS0 first, then we hit `if (newcon->index < 0)'
>>> condition, set newcon to ttyS0, because we iterate in reverse order now, and
>>> break out. so we enable ttyS0, instead of ttyS1.
>>>
>>> previously, we iterated console_cmdline from index 0 and saw ttyS1 first.
>>> so the same `if (newcon->index < 0)' condition would set newcone to ttyS1,
>>> and, thus, we would enable ttyS1, not ttyS0.
>>
>> Alexey,
>> can we have preferred console at offset 0 (not at console_cmdline_cnt - 1)
>> and restore the previous register_console() iteration order?
>
> This will not help. ttyS0 is the last console defined on the command
> line. Therefore it is the preferred one. It means that it will be
> moved to offset 0 and hit first.
>
> I have tried to reproduce the problem and started kernel with
> console=ttyS1 console=ttyS0 in qemu. It created:
>
> console_cmdline = {{
> .name = "ttyS";
> .index = 1; // from ttyS1
> },{
> .name = "ttyS"
> .index = 0; // from ttyS0
> }};
> preferred_console = 1; // ttyuS0;
>
>
> Then register_console() is called twice here. First time
> from con_init() that registers:
>
> static struct console vt_console_driver = {
> .name = "tty",
> .write = vt_console_print,
> .device = vt_console_device,
> .unblank = unblank_screen,
> .flags = CON_PRINTBUFFER,
> .index = -1,
> };
>
> It does not match and it is not enabled here.
>
>
> 2nd times from univ8250_console_init() that registers:
>
> static struct console univ8250_console = {
> .name = "ttyS",
> .write = univ8250_console_write,
> .device = uart_console_device,
> .setup = univ8250_console_setup,
> .match = univ8250_console_match,
> .flags = CON_PRINTBUFFER | CON_ANYTIME,
> .index = -1,
> .data = &serial8250_reg,
> };
>
> It matches both console_cmdline entries because index = -1.
> The first tested is selected.
>
>
> Hmm, I have no idea how to fix this. This is the case where
> a registered console matches more entries from the command line.
> The fix that caused this regression fixed exactly this situation
> and we wanted to make the preferred console first.
The problem is that when we are registering a new console,
we walk over the `console_cmdline` list and match _only one_ of
the specified consoles, contrary to what stated in
Documentation/admin-guide/serial-console.rst:
You can specify multiple console= options on the kernel
command line. Output will appear on *all* of them.
I emphasized all here. Moreover, it is impossible to fix this
without deep reworking of all the console framework.
So specifying same console twice (with different lines) is pointless --
only one of them will be used for kernel logs. You don't have to
specify it in command line if you just want to login on it
and don't want to see kernel logs on it.
> In fact, it always was kind of random because both init calls are
> defined as
>
> console_initcall(con_init);
> console_initcall(univ8250_console_init);
>
> They are put into special elf section and called from console_init()
> the following way:
>
> call = __con_initcall_start;
> while (call < __con_initcall_end) {
> (*call)();
> call++;
> }
>
> By other words, the order depends on the linking order which is
> kind of weak order enforcement.
The order in which consoles are registered is not relevant.
It's command line parameters order that matters.
> I am not sure if we broke some backward compatibility or actually made
> it more predictable in the long term.
I believe that we broke the way an old unfixed bug shows itself.
But reproducing this bug requires to specify the same console
in command line twice (with different lines), which is pointless
so I would say it is irrelevant.
Thank you
Aleksey Makarov
^ permalink raw reply
* [PATCH] imx-serial: RX DMA startup latency
From: Peter Senna Tschudin @ 2017-05-14 12:35 UTC (permalink / raw)
Cc: Peter Senna Tschudin, Sascha Hauer, Greg Kroah-Hartman,
Jiri Slaby, open list:SERIAL DRIVERS, open list
18a4208 introduced a change to reduce the RX DMA latency on the first reception
when the serial port was opened for reading. However it was claiming a hardirq
unsafe lock after a hardirq safe lock which is not allowed and causes lockdep
to complain verbosely.
This patch changes the code to always start RX DMA earlier, instead of
relying on the flags used to open the serial port removing the code that
was looking for the serial file flags.
CC: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Peter Senna Tschudin <peter.senna@collabora.com>
---
Tested on iMX53.
drivers/tty/serial/imx.c | 26 +++++---------------------
1 file changed, 5 insertions(+), 21 deletions(-)
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 33509b4..64e16b3 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1340,29 +1340,13 @@ static int imx_startup(struct uart_port *port)
imx_enable_ms(&sport->port);
/*
- * If the serial port is opened for reading start RX DMA immediately
- * instead of waiting for RX FIFO interrupts. In our iMX53 the average
- * delay for the first reception dropped from approximately 35000
- * microseconds to 1000 microseconds.
+ * Start RX DMA immediately instead of waiting for RX FIFO interrupts.
+ * In our iMX53 the average delay for the first reception dropped from
+ * approximately 35000 microseconds to 1000 microseconds.
*/
if (sport->dma_is_enabled) {
- struct tty_struct *tty = sport->port.state->port.tty;
- struct tty_file_private *file_priv;
- int readcnt = 0;
-
- spin_lock(&tty->files_lock);
-
- if (!list_empty(&tty->tty_files))
- list_for_each_entry(file_priv, &tty->tty_files, list)
- if (!(file_priv->file->f_flags & O_WRONLY))
- readcnt++;
-
- spin_unlock(&tty->files_lock);
-
- if (readcnt > 0) {
- imx_disable_rx_int(sport);
- start_rx_dma(sport);
- }
+ imx_disable_rx_int(sport);
+ start_rx_dma(sport);
}
spin_unlock_irqrestore(&sport->port.lock, flags);
--
2.9.3
^ permalink raw reply related
* Re: [PATCH v2] serial: exar: Fix stuck MSIs
From: Greg Kroah-Hartman @ 2017-05-14 11:32 UTC (permalink / raw)
To: Jan Kiszka
Cc: Andy Shevchenko, Linux Kernel Mailing List, linux-serial,
Sudip Mukherjee
In-Reply-To: <ffaa5003-c62a-1bce-eb59-827a762aefb0@siemens.com>
On Sat, May 13, 2017 at 09:09:17AM +0200, Jan Kiszka wrote:
> On 2017-04-24 14:07, Andy Shevchenko wrote:
> > On Mon, 2017-04-24 at 12:30 +0200, Jan Kiszka wrote:
> >> After migrating 8250_exar to MSI in 172c33cb61da, we can get stuck
> >> without further interrupts because of the special wake-up event these
> >> chips send. They are only cleared by reading INT0. As we fail to do so
> >> during startup and shutdown, we can leave the interrupt line asserted,
> >> which is fatal with edge-triggered MSIs.
> >>
> >> Add the required reading of INT0 to startup and shutdown. Also account
> >> for the fact that a pending wake-up interrupt means we have to return
> >> 1
> >> from exar_handle_irq. Drop the unneeded reading of INT1..3 along with
> >> this - those never reset anything.
> >>
> >> An alternative approach would have been disabling the wake-up
> >> interrupt.
> >> Unfortunately, this feature (REGB[17] = 1) is not available on the
> >> XR17D15X.
> >
> > FWIW:
> > Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> >
>
> Ping. Needs to go into stable 4.11 now as well.
Relax, I'll get to it after 4.12-rc1 is out...
^ permalink raw reply
* Re: [PATCH 2/8] gpio: exar: Fix passing in of parent PCI device
From: Jan Kiszka @ 2017-05-14 8:11 UTC (permalink / raw)
To: Andy Shevchenko, Jan Kiszka
Cc: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot,
Linux Kernel Mailing List, linux-serial@vger.kernel.org,
linux-gpio@vger.kernel.org, Sudip Mukherjee, Sascha Weisenberger
In-Reply-To: <CAHp75VfCd4feKeHOe4QMM88nMQ5wnP4yk7iDJMXN7LcygXVObw@mail.gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 2326 bytes --]
On 2017-05-13 15:25, Andy Shevchenko wrote:
> On Sat, May 13, 2017 at 10:29 AM, Jan Kiszka <jan.kiszka@siemens.com> wrote:
>> This fixes reloading of the driver for the same device: First of all,
>> the driver sets drvdata to its own value during probing and does not
>> restore the original value on exit. But this won't help anyway as the
>> core clears drvdata after the driver left.
>>
>> Use stable platform_data instead.
>
>>From the above I didn't clearly get what device you are talking about.
> GPIO?
"This fixes reloading of the GPIO driver for the same platform device
instance as created by the exar UART driver: [...]"
Clearer?
>
> Can you provide step by step what you did and what bug you got?
Obviously a NULL pointer: Just rmmod gpio-exar and reload it while there
is the same platform device present.
>
> Regarding below it looks to me a bit hackish.
The alternative is a classic platform data structure, then also carrying
the properties of patch 7 - which are, BTW, not DT-related, thus shall
not form an external interface. Probably another reason to switch
everything to some struct exar_gpio_platform_data.
Jan
>
>> static int gpio_exar_probe(struct platform_device *pdev)
>> {
>> - struct pci_dev *pcidev = platform_get_drvdata(pdev);
>> + struct pci_dev *pcidev = *(struct pci_dev **)pdev->dev.platform_data;
>> struct exar_gpio_chip *exar_gpio;
>> void __iomem *p;
>> int index, ret;
>> diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
>> index b4fa585156c7..2d056d1eeca3 100644
>> --- a/drivers/tty/serial/8250/8250_exar.c
>> +++ b/drivers/tty/serial/8250/8250_exar.c
>> @@ -196,8 +196,12 @@ xr17v35x_register_gpio(struct pci_dev *pcidev)
>> if (!pdev)
>> return NULL;
>>
>> - platform_set_drvdata(pdev, pcidev);
>> - if (platform_device_add(pdev) < 0) {
>> + /*
>> + * platform_device_add_data kmemdups the data, therefore we can safely
>> + * pass a stack reference.
>> + */
>> + if (platform_device_add_data(pdev, &pcidev, sizeof(pcidev)) < 0 ||
>> + platform_device_add(pdev) < 0) {
>> platform_device_put(pdev);
>> return NULL;
>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* Re: [PATCH 8/8] serial: exar: Add support for IOT2040 device
From: Andy Shevchenko @ 2017-05-13 13:54 UTC (permalink / raw)
To: Jan Kiszka
Cc: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot,
Linux Kernel Mailing List, linux-serial@vger.kernel.org,
linux-gpio@vger.kernel.org, Sudip Mukherjee, Sascha Weisenberger
In-Reply-To: <1d8ba1dea24da541389e8175097aa4f67eddc298.1494660546.git.jan.kiszka@siemens.com>
On Sat, May 13, 2017 at 10:29 AM, Jan Kiszka <jan.kiszka@siemens.com> wrote:
> This implements the setup of RS232 and the switch-over to RS485 or RS422
> for the Siemens IOT2040. That uses an EXAR XR17V352 with external logic
> to switch between the different modes. The external logic is controlled
> via MPIO pins of the EXAR controller.
>
> Only pin 10 can be exported as GPIO on the IOT2040. It is connected to
> an LED.
>
> As the XR17V352 used on the IOT2040 is not equipped with an external
> EEPROM, it cannot present itself as IOT2040-variant via subvendor/
> subdevice IDs. Thus, we have to check via DMI for the target platform.
>
> Co-developed with Sascha Weisenberger.
>
Please, refactor that using properly formed DMI structrure and use its
callback and driver data facilities/
stmmac's pattern that you obviously applied does not actually suit here.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 7/8] gpio-exar/8250-exar: Make set of exported GPIOs configurable
From: Andy Shevchenko @ 2017-05-13 13:50 UTC (permalink / raw)
To: Jan Kiszka
Cc: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot,
Linux Kernel Mailing List, linux-serial@vger.kernel.org,
linux-gpio@vger.kernel.org, Sudip Mukherjee, Sascha Weisenberger
In-Reply-To: <49df8cbd7204a5f145834715ab353f03f417e1f8.1494660546.git.jan.kiszka@siemens.com>
On Sat, May 13, 2017 at 10:29 AM, Jan Kiszka <jan.kiszka@siemens.com> wrote:
> On the SIMATIC, IOT2040 only a single pin is exportable as GPIO, the
> rest is required to operate the UART. To allow modeling this case,
> use device properties to specify a (consecutive) pin subset for
> exporting by the gpio-exar driver.
> @@ -123,6 +132,7 @@ static int gpio_exar_probe(struct platform_device *pdev)
> struct exar_gpio_chip *exar_gpio;
> void __iomem *p;
> int index, ret;
> + u32 val;
>
> if (pcidev->vendor != PCI_VENDOR_ID_EXAR)
> return -ENODEV;
> @@ -152,9 +162,12 @@ static int gpio_exar_probe(struct platform_device *pdev)
> exar_gpio->gpio_chip.get = exar_get_value;
> exar_gpio->gpio_chip.set = exar_set_value;
> exar_gpio->gpio_chip.base = -1;
> - exar_gpio->gpio_chip.ngpio = 16;
> + device_property_read_u32(&pdev->dev, "ngpio", &val);
> + exar_gpio->gpio_chip.ngpio = val;
You have to check return code, otherwise you might end up with
uninitialized data.
> exar_gpio->regs = p;
> exar_gpio->index = index;
> + device_property_read_u32(&pdev->dev, "first_gpio", &val);
> + exar_gpio->first_gpio = val;
Ditto.
> #include <linux/string.h>
> #include <linux/tty.h>
> #include <linux/8250_pci.h>
> +#include <linux/property.h>
Alphabetical order, please.
> static void *
> -xr17v35x_register_gpio(struct pci_dev *pcidev)
> +xr17v35x_register_gpio(struct pci_dev *pcidev, unsigned int first_gpio,
> + unsigned int ngpio)
> {
> + struct property_entry properties[] = {
> + PROPERTY_ENTRY_U32("first_gpio", first_gpio),
This should be documented in device tree bindings, otherwise it's a
linux software hook and I'm not sure it's the best what we can do
here.
> + PROPERTY_ENTRY_U32("ngpio", ngpio),
This should be a registered property name (I see "ngpios" in the bindings).
> + { }
> + };
> struct platform_device *pdev;
>
> pdev = platform_device_alloc("gpio_exar", PLATFORM_DEVID_AUTO);
> /*
> - * platform_device_add_data kmemdups the data, therefore we can safely
> - * pass a stack reference.
> + * platform_device_add_data and platform_device_add_properties copy
> + * the data, therefore we can safely pass a stack references.
> */
Can you formulate this in an order to reduce ping-ponging lines across
the series?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 5/8] gpio: exar: Fix reading of directions and values
From: Andy Shevchenko @ 2017-05-13 13:36 UTC (permalink / raw)
To: Jan Kiszka
Cc: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot,
Linux Kernel Mailing List, linux-serial@vger.kernel.org,
linux-gpio@vger.kernel.org, Sudip Mukherjee, Sascha Weisenberger
In-Reply-To: <1891081c09747965173fb03a7305e1c73033dac0.1494660546.git.jan.kiszka@siemens.com>
On Sat, May 13, 2017 at 10:29 AM, Jan Kiszka <jan.kiszka@siemens.com> wrote:
> First, the logic for translating a register bit to the return code of
> exar_get_direction and exar_get_value were wrong. And second, there was
> a flip regarding the register bank in exar_get_direction.
Again, I wish it was tested in the first place.
After addressing below:
FWIW:
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> @@ -68,7 +68,7 @@ static int exar_get(struct gpio_chip *chip, unsigned int reg)
> value = readb(exar_gpio->regs + reg);
> mutex_unlock(&exar_gpio->lock);
>
> - return !!value;
> + return value;
This one is correct.
> @@ -80,7 +80,7 @@ static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
> addr = bank ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
> val = exar_get(chip, addr) >> (offset % 8);
>
> - return !!val;
> + return val & 1;
It should be rather
val = exar_get(chip, addr) & BIT(offset % 8);
> }
>
> static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
> @@ -89,10 +89,10 @@ static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
> unsigned int addr;
> int val;
>
> - addr = bank ? EXAR_OFFSET_MPIOLVL_LO : EXAR_OFFSET_MPIOLVL_HI;
> + addr = bank ? EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
Good catch!
> val = exar_get(chip, addr) >> (offset % 8);
>
> - return !!val;
> + return val & 1;
Ditto (see above).
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 4/8] gpio: exar: Fix iomap request
From: Andy Shevchenko @ 2017-05-13 13:28 UTC (permalink / raw)
To: Jan Kiszka
Cc: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot,
Linux Kernel Mailing List, linux-serial@vger.kernel.org,
linux-gpio@vger.kernel.org, Sudip Mukherjee, Sascha Weisenberger
In-Reply-To: <e477e2ec669b105e6d0f61c069b1361e134de593.1494660546.git.jan.kiszka@siemens.com>
On Sat, May 13, 2017 at 10:29 AM, Jan Kiszka <jan.kiszka@siemens.com> wrote:
> The UART driver already maps the resource for us. Trying to do this here
> only fails and leaves us with a non-working device.
I hoped this had been tested previously...
FWIW:
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
> drivers/gpio/gpio-exar.c | 10 +++-------
> 1 file changed, 3 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
> index 9138ee087c5d..d6ffb3d89b9c 100644
> --- a/drivers/gpio/gpio-exar.c
> +++ b/drivers/gpio/gpio-exar.c
> @@ -128,14 +128,10 @@ static int gpio_exar_probe(struct platform_device *pdev)
> return -ENODEV;
>
> /*
> - * Map the pci device to get the register addresses.
> - * We will need to read and write those registers to control
> - * the GPIO pins.
> - * Using managed functions will save us from unmaping on exit.
> - * As the device is enabled using managed functions by the
> - * UART driver we can also use managed functions here.
> + * The UART driver must have mapped region 0 prior to registering this
> + * device - use it.
> */
> - p = pcim_iomap(pcidev, 0, 0);
> + p = pcim_iomap_table(pcidev)[0];
> if (!p)
> return -ENOMEM;
>
> --
> 2.12.0
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 3/8] gpio: exar: Allocate resources on behalf of the platform device
From: Andy Shevchenko @ 2017-05-13 13:26 UTC (permalink / raw)
To: Jan Kiszka
Cc: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot,
Linux Kernel Mailing List, linux-serial@vger.kernel.org,
linux-gpio@vger.kernel.org, Sudip Mukherjee, Sascha Weisenberger
In-Reply-To: <39cc60caa4f5c38d1449590b6c67cf026184306b.1494660546.git.jan.kiszka@siemens.com>
On Sat, May 13, 2017 at 10:29 AM, Jan Kiszka <jan.kiszka@siemens.com> wrote:
> Do not allocate resources on behalf of the parent device but on our own.
> Otherwise, cleanup does not properly work if gpio-exar is removed but
> not the parent device.
This sounds to me like a good catch.
FWIW:
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
> drivers/gpio/gpio-exar.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
> index 0a2085faf271..9138ee087c5d 100644
> --- a/drivers/gpio/gpio-exar.c
> +++ b/drivers/gpio/gpio-exar.c
> @@ -139,7 +139,7 @@ static int gpio_exar_probe(struct platform_device *pdev)
> if (!p)
> return -ENOMEM;
>
> - exar_gpio = devm_kzalloc(&pcidev->dev, sizeof(*exar_gpio), GFP_KERNEL);
> + exar_gpio = devm_kzalloc(&pdev->dev, sizeof(*exar_gpio), GFP_KERNEL);
> if (!exar_gpio)
> return -ENOMEM;
>
> @@ -160,7 +160,7 @@ static int gpio_exar_probe(struct platform_device *pdev)
> exar_gpio->regs = p;
> exar_gpio->index = index;
>
> - ret = devm_gpiochip_add_data(&pcidev->dev,
> + ret = devm_gpiochip_add_data(&pdev->dev,
> &exar_gpio->gpio_chip, exar_gpio);
> if (ret)
> goto err_destroy;
> --
> 2.12.0
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 2/8] gpio: exar: Fix passing in of parent PCI device
From: Andy Shevchenko @ 2017-05-13 13:25 UTC (permalink / raw)
To: Jan Kiszka
Cc: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot,
Linux Kernel Mailing List, linux-serial@vger.kernel.org,
linux-gpio@vger.kernel.org, Sudip Mukherjee, Sascha Weisenberger
In-Reply-To: <20f1d241d134f9f4932a26e4bd873ffc250affce.1494660546.git.jan.kiszka@siemens.com>
On Sat, May 13, 2017 at 10:29 AM, Jan Kiszka <jan.kiszka@siemens.com> wrote:
> This fixes reloading of the driver for the same device: First of all,
> the driver sets drvdata to its own value during probing and does not
> restore the original value on exit. But this won't help anyway as the
> core clears drvdata after the driver left.
>
> Use stable platform_data instead.
>From the above I didn't clearly get what device you are talking about.
GPIO?
Can you provide step by step what you did and what bug you got?
Regarding below it looks to me a bit hackish.
> static int gpio_exar_probe(struct platform_device *pdev)
> {
> - struct pci_dev *pcidev = platform_get_drvdata(pdev);
> + struct pci_dev *pcidev = *(struct pci_dev **)pdev->dev.platform_data;
> struct exar_gpio_chip *exar_gpio;
> void __iomem *p;
> int index, ret;
> diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
> index b4fa585156c7..2d056d1eeca3 100644
> --- a/drivers/tty/serial/8250/8250_exar.c
> +++ b/drivers/tty/serial/8250/8250_exar.c
> @@ -196,8 +196,12 @@ xr17v35x_register_gpio(struct pci_dev *pcidev)
> if (!pdev)
> return NULL;
>
> - platform_set_drvdata(pdev, pcidev);
> - if (platform_device_add(pdev) < 0) {
> + /*
> + * platform_device_add_data kmemdups the data, therefore we can safely
> + * pass a stack reference.
> + */
> + if (platform_device_add_data(pdev, &pcidev, sizeof(pcidev)) < 0 ||
> + platform_device_add(pdev) < 0) {
> platform_device_put(pdev);
> return NULL;
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v9 3/3] printk: fix double printing with earlycon
From: Sergey Senozhatsky @ 2017-05-13 11:48 UTC (permalink / raw)
To: Petr Mladek
Cc: Sergey Senozhatsky, Aleksey Makarov, Sabrina Dubroca,
linux-serial, linux-kernel, Sudeep Holla, Greg Kroah-Hartman,
Peter Hurley, Jiri Slaby, Robin Murphy, Steven Rostedt,
Nair, Jayachandran, Sergey Senozhatsky
In-Reply-To: <20170512125729.GO3452@pathway.suse.cz>
On (05/12/17 14:57), Petr Mladek wrote:
[..]
> I have tried to reproduce the problem and started kernel with
> console=ttyS1 console=ttyS0 in qemu. It created:
>
> console_cmdline = {{
> .name = "ttyS";
> .index = 1; // from ttyS1
> },{
> .name = "ttyS"
> .index = 0; // from ttyS0
> }};
> preferred_console = 1; // ttyuS0;
>
>
> Then register_console() is called twice here. First time
> from con_init() that registers:
>
> static struct console vt_console_driver = {
> .name = "tty",
> .write = vt_console_print,
> .device = vt_console_device,
> .unblank = unblank_screen,
> .flags = CON_PRINTBUFFER,
> .index = -1,
> };
>
> It does not match and it is not enabled here.
>
>
> 2nd times from univ8250_console_init() that registers:
>
> static struct console univ8250_console = {
> .name = "ttyS",
> .write = univ8250_console_write,
> .device = uart_console_device,
> .setup = univ8250_console_setup,
> .match = univ8250_console_match,
> .flags = CON_PRINTBUFFER | CON_ANYTIME,
> .index = -1,
> .data = &serial8250_reg,
> };
>
> It matches both console_cmdline entries because index = -1.
> The first tested is selected.
yes, that's what I observed on my host. I didn't try it with qemu,
just 86_64. and the behaviour was different.
[..]
> In fact, it always was kind of random because both init calls are
> defined as
>
> console_initcall(con_init);
> console_initcall(univ8250_console_init);
>
> They are put into special elf section and called from console_init()
> the following way:
>
> call = __con_initcall_start;
> while (call < __con_initcall_end) {
> (*call)();
> call++;
> }
>
> By other words, the order depends on the linking order which is
> kind of weak order enforcement.
>
> I am not sure if we broke some backward compatibility or actually made
> it more predictable in the long term.
well, we changed the behaviour. some automated scripts somewhere might
get broken. so may be this is the case when "a bug" becomes "a feature".
well, just saying.
-ss
^ permalink raw reply
* Re: [PATCH] serial: altera_jtaguart: adding iounmap()
From: Tobias Klauser @ 2017-05-13 11:00 UTC (permalink / raw)
To: Alexey Khoroshilov
Cc: Greg Kroah-Hartman, Jiri Slaby, linux-serial, nios2-dev,
linux-kernel, ldv-project
In-Reply-To: <1494624982-3245-1-git-send-email-khoroshilov@ispras.ru>
On 2017-05-12 at 23:36:22 +0200, Alexey Khoroshilov <khoroshilov@ispras.ru> wrote:
> The driver does ioremap(port->mapbase, ALTERA_JTAGUART_SIZE),
> but there is no any iounmap().
>
> Found by Linux Driver Verification project (linuxtesting.org).
>
> Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
Acked-by: Tobias Klauser <tklauser@distanz.ch>
Thanks!
^ permalink raw reply
* [PATCH 8/8] serial: exar: Add support for IOT2040 device
From: Jan Kiszka @ 2017-05-13 7:29 UTC (permalink / raw)
To: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot
Cc: Linux Kernel Mailing List, linux-serial, linux-gpio,
Sudip Mukherjee, Andy Shevchenko, Sascha Weisenberger
In-Reply-To: <cover.1494660546.git.jan.kiszka@siemens.com>
This implements the setup of RS232 and the switch-over to RS485 or RS422
for the Siemens IOT2040. That uses an EXAR XR17V352 with external logic
to switch between the different modes. The external logic is controlled
via MPIO pins of the EXAR controller.
Only pin 10 can be exported as GPIO on the IOT2040. It is connected to
an LED.
As the XR17V352 used on the IOT2040 is not equipped with an external
EEPROM, it cannot present itself as IOT2040-variant via subvendor/
subdevice IDs. Thus, we have to check via DMI for the target platform.
Co-developed with Sascha Weisenberger.
Signed-off-by: Sascha Weisenberger <sascha.weisenberger@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
drivers/tty/serial/8250/8250_exar.c | 121 ++++++++++++++++++++++++++++++++++--
1 file changed, 116 insertions(+), 5 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index 8e9c0e9495f5..62fe0f1ddcfe 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/tty.h>
#include <linux/8250_pci.h>
+#include <linux/dmi.h>
#include <linux/property.h>
#include <asm/byteorder.h>
@@ -61,6 +62,43 @@
#define UART_EXAR_MPIOSEL_15_8 0x99 /* MPIOSEL[15:8] */
#define UART_EXAR_MPIOOD_15_8 0x9a /* MPIOOD[15:8] */
+#define UART_EXAR_RS485_DLY(x) (x << 4)
+
+/*
+ * IOT2040 MPIO wiring semantics:
+ *
+ * MPIO Port Function
+ * ---- ---- --------
+ * 0 2 Mode bit 0
+ * 1 2 Mode bit 1
+ * 2 2 Terminate bus
+ * 3 - <reserved>
+ * 4 3 Mode bit 0
+ * 5 3 Mode bit 1
+ * 6 3 Terminate bus
+ * 7 - <reserved>
+ * 8 2 Enable
+ * 9 3 Enable
+ * 10 - Red LED
+ * 11..15 - <unused>
+ */
+
+/* IOT2040 MPIOs 0..7 */
+#define IOT2040_UART_MODE_RS232 0x01
+#define IOT2040_UART_MODE_RS485 0x02
+#define IOT2040_UART_MODE_RS422 0x03
+#define IOT2040_UART_TERMINATE_BUS 0x04
+
+#define IOT2040_UART1_MASK 0x0f
+#define IOT2040_UART2_SHIFT 4
+
+#define IOT2040_UARTS_DEFAULT_MODE 0x11 /* both RS232 */
+#define IOT2040_UARTS_GPIO_LO_MODE 0x88 /* reserved pins as input */
+
+/* IOT2040 MPIOs 8..15 */
+#define IOT2040_UARTS_ENABLE 0x03
+#define IOT2040_UARTS_GPIO_HI_MODE 0xF8 /* enable & LED as outputs */
+
struct exar8250;
/**
@@ -217,6 +255,65 @@ xr17v35x_register_gpio(struct pci_dev *pcidev, unsigned int first_gpio,
return pdev;
}
+static int iot2040_rs485_config(struct uart_port *port,
+ struct serial_rs485 *rs485)
+{
+ u8 __iomem *p = port->membase;
+ u8 mask = IOT2040_UART1_MASK;
+ u8 mode, value;
+ bool is_rs485 = false;
+
+ if (rs485->flags & SER_RS485_ENABLED) {
+ is_rs485 = true;
+ if (rs485->flags & SER_RS485_RX_DURING_TX)
+ mode = IOT2040_UART_MODE_RS422;
+ else
+ mode = IOT2040_UART_MODE_RS485;
+
+ if (rs485->flags & SER_RS485_TERMINATE_BUS)
+ mode |= IOT2040_UART_TERMINATE_BUS;
+ } else {
+ mode = IOT2040_UART_MODE_RS232;
+ }
+
+ if (port->line == 3) {
+ mask <<= IOT2040_UART2_SHIFT;
+ mode <<= IOT2040_UART2_SHIFT;
+ }
+
+ value = readb(p + UART_EXAR_MPIOLVL_7_0);
+ value &= ~mask;
+ value |= mode;
+ writeb(value, p + UART_EXAR_MPIOLVL_7_0);
+
+ value = readb(p + UART_EXAR_FCTR);
+ if (is_rs485)
+ value |= UART_FCTR_EXAR_485;
+ else
+ value &= ~UART_FCTR_EXAR_485;
+ writeb(value, p + UART_EXAR_FCTR);
+
+ if (is_rs485)
+ writeb(UART_EXAR_RS485_DLY(4), p + UART_MSR);
+
+ return 0;
+}
+
+static int iot2000_setup_gpio(struct pci_dev *pcidev,
+ struct uart_8250_port *port)
+{
+ u8 __iomem *p = port->port.membase;
+
+ writeb(IOT2040_UARTS_DEFAULT_MODE, p + UART_EXAR_MPIOLVL_7_0);
+ writeb(IOT2040_UARTS_GPIO_LO_MODE, p + UART_EXAR_MPIOSEL_7_0);
+ writeb(IOT2040_UARTS_ENABLE, p + UART_EXAR_MPIOLVL_15_8);
+ writeb(IOT2040_UARTS_GPIO_HI_MODE, p + UART_EXAR_MPIOSEL_15_8);
+
+ port->port.private_data = xr17v35x_register_gpio(pcidev, 10, 1);
+
+ return 0;
+}
+
static int
pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
struct uart_8250_port *port, int idx)
@@ -224,10 +321,20 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
const struct exar8250_board *board = priv->board;
unsigned int offset = idx * 0x400;
unsigned int baud = 7812500;
+ bool is_iot2040;
u8 __iomem *p;
int ret;
port->port.uartclk = baud * 16;
+
+ is_iot2040 =
+ strcmp(dmi_get_system_info(DMI_BOARD_NAME),
+ "SIMATIC IOT2000") == 0 &&
+ strcmp(dmi_get_system_info(DMI_BOARD_ASSET_TAG),
+ "6ES7647-0AA00-1YA2") == 0;
+ if (is_iot2040)
+ port->port.rs485_config = iot2040_rs485_config;
+
/*
* Setup the uart clock for the devices on expansion slot to
* half the clock speed of the main chip (which is 125MHz)
@@ -246,14 +353,18 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
writeb(128, p + UART_EXAR_TXTRG);
writeb(128, p + UART_EXAR_RXTRG);
- if (idx == 0) {
- /* Setup Multipurpose Input/Output pins. */
- setup_gpio(p);
+ if (idx != 0)
+ return 0;
+
+ /* Setup Multipurpose Input/Output pins. */
+ setup_gpio(p);
+ if (is_iot2040)
+ ret = iot2000_setup_gpio(pcidev, port);
+ else
port->port.private_data = xr17v35x_register_gpio(pcidev, 0, 16);
- }
- return 0;
+ return ret;
}
static void pci_xr17v35x_exit(struct pci_dev *pcidev)
--
2.12.0
^ permalink raw reply related
* [PATCH 7/8] gpio-exar/8250-exar: Make set of exported GPIOs configurable
From: Jan Kiszka @ 2017-05-13 7:29 UTC (permalink / raw)
To: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot
Cc: Linux Kernel Mailing List, linux-serial, linux-gpio,
Sudip Mukherjee, Andy Shevchenko, Sascha Weisenberger
In-Reply-To: <cover.1494660546.git.jan.kiszka@siemens.com>
On the SIMATIC, IOT2040 only a single pin is exportable as GPIO, the
rest is required to operate the UART. To allow modeling this case,
use device properties to specify a (consecutive) pin subset for
exporting by the gpio-exar driver.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
drivers/gpio/gpio-exar.c | 31 ++++++++++++++++++++++---------
drivers/tty/serial/8250/8250_exar.c | 16 ++++++++++++----
2 files changed, 34 insertions(+), 13 deletions(-)
diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index 98bd3eb1290e..e2cb1d83e4b0 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -31,6 +31,7 @@ struct exar_gpio_chip {
int index;
void __iomem *regs;
char name[20];
+ unsigned int first_gpio;
};
static void exar_update(struct gpio_chip *chip, unsigned int reg, int val,
@@ -51,9 +52,11 @@ static void exar_update(struct gpio_chip *chip, unsigned int reg, int val,
static int exar_set_direction(struct gpio_chip *chip, int direction,
unsigned int offset)
{
- unsigned int bank = offset / 8;
- unsigned int addr;
+ struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
+ unsigned int bank, addr;
+ offset += exar_gpio->first_gpio;
+ bank = offset / 8;
addr = bank ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
exar_update(chip, addr, direction, offset % 8);
return 0;
@@ -73,10 +76,12 @@ static int exar_get(struct gpio_chip *chip, unsigned int reg)
static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
{
- unsigned int bank = offset / 8;
- unsigned int addr;
+ struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
+ unsigned int bank, addr;
int val;
+ offset += exar_gpio->first_gpio;
+ bank = offset / 8;
addr = bank ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
val = exar_get(chip, addr) >> (offset % 8);
@@ -85,10 +90,12 @@ static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
{
- unsigned int bank = offset / 8;
- unsigned int addr;
+ struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
+ unsigned int bank, addr;
int val;
+ offset += exar_gpio->first_gpio;
+ bank = offset / 8;
addr = bank ? EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
val = exar_get(chip, addr) >> (offset % 8);
@@ -98,9 +105,11 @@ static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
int value)
{
- unsigned int bank = offset / 8;
- unsigned int addr;
+ struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
+ unsigned int bank, addr;
+ offset += exar_gpio->first_gpio;
+ bank = offset / 8;
addr = bank ? EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
exar_update(chip, addr, value, offset % 8);
}
@@ -123,6 +132,7 @@ static int gpio_exar_probe(struct platform_device *pdev)
struct exar_gpio_chip *exar_gpio;
void __iomem *p;
int index, ret;
+ u32 val;
if (pcidev->vendor != PCI_VENDOR_ID_EXAR)
return -ENODEV;
@@ -152,9 +162,12 @@ static int gpio_exar_probe(struct platform_device *pdev)
exar_gpio->gpio_chip.get = exar_get_value;
exar_gpio->gpio_chip.set = exar_set_value;
exar_gpio->gpio_chip.base = -1;
- exar_gpio->gpio_chip.ngpio = 16;
+ device_property_read_u32(&pdev->dev, "ngpio", &val);
+ exar_gpio->gpio_chip.ngpio = val;
exar_gpio->regs = p;
exar_gpio->index = index;
+ device_property_read_u32(&pdev->dev, "first_gpio", &val);
+ exar_gpio->first_gpio = val;
ret = devm_gpiochip_add_data(&pdev->dev,
&exar_gpio->gpio_chip, exar_gpio);
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index 2d056d1eeca3..8e9c0e9495f5 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/tty.h>
#include <linux/8250_pci.h>
+#include <linux/property.h>
#include <asm/byteorder.h>
@@ -188,8 +189,14 @@ static void setup_gpio(u8 __iomem *p)
}
static void *
-xr17v35x_register_gpio(struct pci_dev *pcidev)
+xr17v35x_register_gpio(struct pci_dev *pcidev, unsigned int first_gpio,
+ unsigned int ngpio)
{
+ struct property_entry properties[] = {
+ PROPERTY_ENTRY_U32("first_gpio", first_gpio),
+ PROPERTY_ENTRY_U32("ngpio", ngpio),
+ { }
+ };
struct platform_device *pdev;
pdev = platform_device_alloc("gpio_exar", PLATFORM_DEVID_AUTO);
@@ -197,10 +204,11 @@ xr17v35x_register_gpio(struct pci_dev *pcidev)
return NULL;
/*
- * platform_device_add_data kmemdups the data, therefore we can safely
- * pass a stack reference.
+ * platform_device_add_data and platform_device_add_properties copy
+ * the data, therefore we can safely pass a stack references.
*/
if (platform_device_add_data(pdev, &pcidev, sizeof(pcidev)) < 0 ||
+ platform_device_add_properties(pdev, properties) < 0 ||
platform_device_add(pdev) < 0) {
platform_device_put(pdev);
return NULL;
@@ -242,7 +250,7 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
/* Setup Multipurpose Input/Output pins. */
setup_gpio(p);
- port->port.private_data = xr17v35x_register_gpio(pcidev);
+ port->port.private_data = xr17v35x_register_gpio(pcidev, 0, 16);
}
return 0;
--
2.12.0
^ permalink raw reply related
* [PATCH 6/8] serial: uapi: Add support for bus termination
From: Jan Kiszka @ 2017-05-13 7:29 UTC (permalink / raw)
To: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot
Cc: Linux Kernel Mailing List, linux-serial, linux-gpio,
Sudip Mukherjee, Andy Shevchenko, Sascha Weisenberger
In-Reply-To: <cover.1494660546.git.jan.kiszka@siemens.com>
The Siemens IOT2040 comes with a RS485 interface that allows to enable
or disable bus termination via software. Add a bit to the flags field of
serial_rs485 that applications can set in order to request this feature
from the hardware. This seems generic enough to add it for everyone.
Existing driver will simply ignore it when set.
Signed-off-by: Sascha Weisenberger <sascha.weisenberger@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
include/uapi/linux/serial.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h
index 5d59c3ebf459..d2667ecd54ac 100644
--- a/include/uapi/linux/serial.h
+++ b/include/uapi/linux/serial.h
@@ -122,6 +122,9 @@ struct serial_rs485 {
#define SER_RS485_RTS_AFTER_SEND (1 << 2) /* Logical level for
RTS pin after sent*/
#define SER_RS485_RX_DURING_TX (1 << 4)
+#define SER_RS485_TERMINATE_BUS (1 << 5) /* Enable bus
+ termination
+ (if supported) */
__u32 delay_rts_before_send; /* Delay before send (milliseconds) */
__u32 delay_rts_after_send; /* Delay after send (milliseconds) */
__u32 padding[5]; /* Memory is cheap, new structs
--
2.12.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox