* Re: [PATCH V2 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices
From: Greg KH @ 2019-07-03 15:59 UTC (permalink / raw)
To: Enrico Weigelt, metux IT consult; +Cc: jeyentam, linux-serial, linux-kernel
In-Reply-To: <d6910b29-3ba6-4a3b-04e2-bc7c3c012554@metux.net>
On Wed, Jul 03, 2019 at 05:41:25PM +0200, Enrico Weigelt, metux IT consult wrote:
> On 03.07.19 16:47, Greg KH wrote:
> > On Wed, Jul 03, 2019 at 03:27:11PM +0200, Enrico Weigelt, metux IT consult wrote:
> >>> /* UART Port Control Register */> -#define NI8430_PORTCON 0x0f> -#define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
> >> Can we have that renaming as a separate patch, to ease review ?
> >>
> >> And what about introducing a config sym for the new device specific
> >> stuff ? These devices seem to be pretty rare - never seen them in
> >> embeded world, where we do need to care of kernel size.
> >
> > No, that's not the way this driver works, sorry.
>
> That's sad, because in embedded world we often have to care about
> code size, so making those devices optional would be of great help.
Really? are you sure? Try it and see what you really end up saving.
greg k-h
^ permalink raw reply
* [PATCH V2 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices
From: Enrico Weigelt, metux IT consult @ 2019-07-03 15:41 UTC (permalink / raw)
To: Greg KH; +Cc: jeyentam, linux-serial, linux-kernel
In-Reply-To: <20190703144744.GB24961@kroah.com>
On 03.07.19 16:47, Greg KH wrote:
> On Wed, Jul 03, 2019 at 03:27:11PM +0200, Enrico Weigelt, metux IT consult wrote:
>>> /* UART Port Control Register */> -#define NI8430_PORTCON 0x0f> -#define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
>> Can we have that renaming as a separate patch, to ease review ?
>>
>> And what about introducing a config sym for the new device specific
>> stuff ? These devices seem to be pretty rare - never seen them in
>> embeded world, where we do need to care of kernel size.
>
> No, that's not the way this driver works, sorry.
That's sad, because in embedded world we often have to care about
code size, so making those devices optional would be of great help.
OTOH, the 8250 driver already has several such options. What's your
concern about adding another one for a new device ? Config variant
inflation ? Would putting it behind CONFIG_EXPERT or CONFIG_EMBEDDED
an option ?
thx.
--mtx
--
Enrico Weigelt, metux IT consult
Free software and Linux embedded engineering
info@metux.net -- +49-151-27565287
^ permalink raw reply
* Re: [PATCH V2 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices
From: Greg KH @ 2019-07-03 14:47 UTC (permalink / raw)
To: Enrico Weigelt, metux IT consult; +Cc: jeyentam, linux-serial, linux-kernel
In-Reply-To: <63697b10-98a7-86b7-2513-3eb793ed03c5@metux.net>
On Wed, Jul 03, 2019 at 03:27:11PM +0200, Enrico Weigelt, metux IT consult wrote:
> > /* UART Port Control Register */> -#define NI8430_PORTCON 0x0f> -#define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
> Can we have that renaming as a separate patch, to ease review ?
>
> And what about introducing a config sym for the new device specific
> stuff ? These devices seem to be pretty rare - never seen them in
> embeded world, where we do need to care of kernel size.
No, that's not the way this driver works, sorry.
greg k-h
^ permalink raw reply
* Re: [PATCH V2 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices
From: Enrico Weigelt, metux IT consult @ 2019-07-03 13:27 UTC (permalink / raw)
To: jeyentam, gregkh; +Cc: linux-serial, linux-kernel
In-Reply-To: <20190703072435.34152-1-je.yen.tam@ni.com>
On 03.07.19 09:24, jeyentam wrote:
Hi,
besides what Greg already said:
> /* UART Port Control Register */> -#define NI8430_PORTCON 0x0f> -#define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
Can we have that renaming as a separate patch, to ease review ?
And what about introducing a config sym for the new device specific
stuff ? These devices seem to be pretty rare - never seen them in
embeded world, where we do need to care of kernel size.
--mtx
--
Enrico Weigelt, metux IT consult
Free software and Linux embedded engineering
info@metux.net -- +49-151-27565287
^ permalink raw reply
* Re: [PATCH V2 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices
From: Greg KH @ 2019-07-03 8:42 UTC (permalink / raw)
To: jeyentam; +Cc: linux-serial, linux-kernel
In-Reply-To: <20190703072435.34152-1-je.yen.tam@ni.com>
On Wed, Jul 03, 2019 at 12:24:35AM -0700, jeyentam wrote:
> Add support for NI-Serial PXIe-RS232, PXI-RS485 and PXIe-RS485 devices.
>
> Signed-off-by: jeyentam <je.yen.tam@ni.com>
I need a "full" name here please.
Also, this patch breaks the build, which is not allowed, and makes me
wonder how you tested it :(
Please fix up properly and resend.
Also, some comments below:
> ---
> drivers/tty/serial/8250/8250_pci.c | 293 ++++++++++++++++++++++++++++-
> 1 file changed, 289 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
> index df41397de478..ac8138adea9c 100644
> --- a/drivers/tty/serial/8250/8250_pci.c
> +++ b/drivers/tty/serial/8250/8250_pci.c
> @@ -730,8 +730,16 @@ static int pci_ni8430_init(struct pci_dev *dev)
> }
>
> /* UART Port Control Register */
> -#define NI8430_PORTCON 0x0f
> -#define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
Why are you renaming these #defines?
> +#define NI16550_PCR_OFFSET 0x0f
> +#define NI16550_PCR_RS422 0x00
> +#define NI16550_PCR_ECHO_RS485 0x01
> +#define NI16550_PCR_DTR_RS485 0x02
> +#define NI16550_PCR_AUTO_RS485 0x03
> +#define NI16550_PCR_WIRE_MODE_MASK 0x03
> +#define NI16550_PCR_TXVR_ENABLE_BIT (1 << 3)
BIT(3)?
> +#define NI16550_PCR_RS485_TERMINATION_BIT (1 << 6)
BIT(6)?
> +#define NI16550_ACR_DTR_AUTO_DTR (0x2 << 3)
> +#define NI16550_ACR_DTR_MANUAL_DTR (0x0 << 3)
>
> static int
> pci_ni8430_setup(struct serial_private *priv,
> @@ -753,14 +761,127 @@ pci_ni8430_setup(struct serial_private *priv,
> return -ENOMEM;
>
> /* enable the transceiver */
> - writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE,
> - p + offset + NI8430_PORTCON);
> + writeb(readb(p + offset + NI16550_PCR_OFFSET) |
> + NI16550_PCR_TXVR_ENABLE_BIT,
> + p + offset + NI16550_PCR_OFFSET);
Why indent like this? Please follow the indentation that used to be
there.
>
> iounmap(p);
>
> return setup_port(priv, port, bar, offset, board->reg_shift);
> }
>
> +static int pci_ni8431_config_rs485(struct uart_port *port,
> + struct serial_rs485 *rs485)
> +{
> + u8 pcr, acr;
> +
> + struct uart_8250_port *up;
> +
> + up = container_of(port, struct uart_8250_port, port);
> +
> + acr = up->acr;
> +
> + dev_dbg(port->dev, "ni16550_config_rs485\n");
No need for debugging lines like this, use ftrace please.
> +
> + /* "rs485" should be given to us non-NULL. */
> + WARN_ON(rs485 == NULL);
Don't crash people's machines, if this can never happen, then no need
for this line. If it can happen, test and properly return an error.
> +
> + pcr = port->serial_in(port, NI16550_PCR_OFFSET);
> + pcr &= ~NI16550_PCR_WIRE_MODE_MASK;
> +
> + if (rs485->flags & SER_RS485_ENABLED) {
> + /* RS-485 */
> + if ((rs485->flags & SER_RS485_RX_DURING_TX) &&
> + (rs485->flags & SER_RS485_RTS_ON_SEND)) {
> + dev_dbg(port->dev, "Invalid 2-wire mode\n");
> + return -EINVAL;
> + }
> +
> + if (rs485->flags & SER_RS485_RX_DURING_TX) {
> + /* Echo */
> + dev_vdbg(port->dev, "2-wire DTR with echo\n");
> + pcr |= NI16550_PCR_ECHO_RS485;
> + acr |= NI16550_ACR_DTR_MANUAL_DTR;
> + } else {
> + /* Auto or DTR */
> + if (rs485->flags & SER_RS485_RTS_ON_SEND) {
> + /* Auto */
> + dev_vdbg(port->dev, "2-wire Auto\n");
> + pcr |= NI16550_PCR_AUTO_RS485;
> + acr |= NI16550_ACR_DTR_AUTO_DTR;
> + } else {
> + /* DTR-controlled */
> + /* No Echo */
> + dev_vdbg(port->dev, "2-wire DTR no echo\n");
> + pcr |= NI16550_PCR_DTR_RS485;
> + acr |= NI16550_ACR_DTR_MANUAL_DTR;
> + }
> + }
> + } else {
> + /* RS-422 */
> + dev_vdbg(port->dev, "4-wire\n");
> + pcr |= NI16550_PCR_RS422;
> + acr |= NI16550_ACR_DTR_MANUAL_DTR;
> + }
> +
> + dev_dbg(port->dev, "write pcr: 0x%08x\n", pcr);
> + port->serial_out(port, NI16550_PCR_OFFSET, pcr);
> +
> + up->acr = acr;
> + port->serial_out(port, UART_SCR, UART_ACR);
> + port->serial_out(port, UART_ICR, up->acr);
> +
> + /* Update the cache. */
> + port->rs485 = *rs485;
> +
> + dev_dbg(port->dev, "ni16550_config_rs485\n");
Again, use ftrace, not dev_dbg() for stuff like this.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH V2 2/2] PCI: Add NI-Serial PXI/PXIe+485 device IDs
From: Greg KH @ 2019-07-03 8:36 UTC (permalink / raw)
To: jeyentam; +Cc: linux-serial, linux-kernel
In-Reply-To: <20190703072516.34199-1-je.yen.tam@ni.com>
On Wed, Jul 03, 2019 at 12:25:16AM -0700, jeyentam wrote:
> Add NI PXIe-RS232, PXI-RS485 and PXIe-RS485 device IDs.
>
> Signed-off-by: jeyentam <je.yen.tam@ni.com>
> ---
> include/linux/pci_ids.h | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
You have read the comment at the top of this file, right? If so, why
are you adding these entries?
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index 70e86148cb1e..7fad4794789f 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -1027,7 +1027,9 @@
> #define PCI_DEVICE_ID_SUN_TOMATILLO 0xa801
> #define PCI_DEVICE_ID_SUN_CASSINI 0xabba
>
> +/* NI-Serial Device IDs */
> #define PCI_VENDOR_ID_NI 0x1093
That's a vendor id, not a serial device id.
thanks,
greg k-h
^ permalink raw reply
* [PATCH V2 2/2] PCI: Add NI-Serial PXI/PXIe+485 device IDs
From: jeyentam @ 2019-07-03 7:25 UTC (permalink / raw)
To: gregkh; +Cc: linux-serial, linux-kernel, jeyentam
Add NI PXIe-RS232, PXI-RS485 and PXIe-RS485 device IDs.
Signed-off-by: jeyentam <je.yen.tam@ni.com>
---
include/linux/pci_ids.h | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 70e86148cb1e..7fad4794789f 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1027,7 +1027,9 @@
#define PCI_DEVICE_ID_SUN_TOMATILLO 0xa801
#define PCI_DEVICE_ID_SUN_CASSINI 0xabba
+/* NI-Serial Device IDs */
#define PCI_VENDOR_ID_NI 0x1093
+/* NI PXI(e) RS-232 Devices */
#define PCI_DEVICE_ID_NI_PCI2322 0xd130
#define PCI_DEVICE_ID_NI_PCI2324 0xd140
#define PCI_DEVICE_ID_NI_PCI2328 0xd150
@@ -1052,6 +1054,16 @@
#define PCI_DEVICE_ID_NI_PCI8432_2322 0x70ea
#define PCI_DEVICE_ID_NI_PXI8432_2324 0x70ec
#define PCI_DEVICE_ID_NI_PCI8432_2324 0x70ee
+#define PCIE_DEVICE_ID_NI_PXIE8430_2328 0x74C2
+#define PCIE_DEVICE_ID_NI_PXIE8430_23216 0x74C1
+/* NI PXI(e) RS-485 Devices */
+#define PCI_DEVICE_ID_NI_PXI8431_4852 0x7081
+#define PCI_DEVICE_ID_NI_PXI8431_4854 0x70DE
+#define PCI_DEVICE_ID_NI_PXI8431_4858 0x70E3
+#define PCI_DEVICE_ID_NI_PXI8433_4852 0x70E9
+#define PCI_DEVICE_ID_NI_PXI8433_4854 0x70ED
+#define PCIE_DEVICE_ID_NI_PXIE8431_4858 0x74C4
+#define PCIE_DEVICE_ID_NI_PXIE8431_48516 0x74C3
#define PCI_VENDOR_ID_CMD 0x1095
#define PCI_DEVICE_ID_CMD_643 0x0643
--
2.17.1
^ permalink raw reply related
* [PATCH V2 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices
From: jeyentam @ 2019-07-03 7:24 UTC (permalink / raw)
To: gregkh; +Cc: linux-serial, linux-kernel, jeyentam
Add support for NI-Serial PXIe-RS232, PXI-RS485 and PXIe-RS485 devices.
Signed-off-by: jeyentam <je.yen.tam@ni.com>
---
drivers/tty/serial/8250/8250_pci.c | 293 ++++++++++++++++++++++++++++-
1 file changed, 289 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index df41397de478..ac8138adea9c 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -730,8 +730,16 @@ static int pci_ni8430_init(struct pci_dev *dev)
}
/* UART Port Control Register */
-#define NI8430_PORTCON 0x0f
-#define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
+#define NI16550_PCR_OFFSET 0x0f
+#define NI16550_PCR_RS422 0x00
+#define NI16550_PCR_ECHO_RS485 0x01
+#define NI16550_PCR_DTR_RS485 0x02
+#define NI16550_PCR_AUTO_RS485 0x03
+#define NI16550_PCR_WIRE_MODE_MASK 0x03
+#define NI16550_PCR_TXVR_ENABLE_BIT (1 << 3)
+#define NI16550_PCR_RS485_TERMINATION_BIT (1 << 6)
+#define NI16550_ACR_DTR_AUTO_DTR (0x2 << 3)
+#define NI16550_ACR_DTR_MANUAL_DTR (0x0 << 3)
static int
pci_ni8430_setup(struct serial_private *priv,
@@ -753,14 +761,127 @@ pci_ni8430_setup(struct serial_private *priv,
return -ENOMEM;
/* enable the transceiver */
- writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE,
- p + offset + NI8430_PORTCON);
+ writeb(readb(p + offset + NI16550_PCR_OFFSET) |
+ NI16550_PCR_TXVR_ENABLE_BIT,
+ p + offset + NI16550_PCR_OFFSET);
iounmap(p);
return setup_port(priv, port, bar, offset, board->reg_shift);
}
+static int pci_ni8431_config_rs485(struct uart_port *port,
+ struct serial_rs485 *rs485)
+{
+ u8 pcr, acr;
+
+ struct uart_8250_port *up;
+
+ up = container_of(port, struct uart_8250_port, port);
+
+ acr = up->acr;
+
+ dev_dbg(port->dev, "ni16550_config_rs485\n");
+
+ /* "rs485" should be given to us non-NULL. */
+ WARN_ON(rs485 == NULL);
+
+ pcr = port->serial_in(port, NI16550_PCR_OFFSET);
+ pcr &= ~NI16550_PCR_WIRE_MODE_MASK;
+
+ if (rs485->flags & SER_RS485_ENABLED) {
+ /* RS-485 */
+ if ((rs485->flags & SER_RS485_RX_DURING_TX) &&
+ (rs485->flags & SER_RS485_RTS_ON_SEND)) {
+ dev_dbg(port->dev, "Invalid 2-wire mode\n");
+ return -EINVAL;
+ }
+
+ if (rs485->flags & SER_RS485_RX_DURING_TX) {
+ /* Echo */
+ dev_vdbg(port->dev, "2-wire DTR with echo\n");
+ pcr |= NI16550_PCR_ECHO_RS485;
+ acr |= NI16550_ACR_DTR_MANUAL_DTR;
+ } else {
+ /* Auto or DTR */
+ if (rs485->flags & SER_RS485_RTS_ON_SEND) {
+ /* Auto */
+ dev_vdbg(port->dev, "2-wire Auto\n");
+ pcr |= NI16550_PCR_AUTO_RS485;
+ acr |= NI16550_ACR_DTR_AUTO_DTR;
+ } else {
+ /* DTR-controlled */
+ /* No Echo */
+ dev_vdbg(port->dev, "2-wire DTR no echo\n");
+ pcr |= NI16550_PCR_DTR_RS485;
+ acr |= NI16550_ACR_DTR_MANUAL_DTR;
+ }
+ }
+ } else {
+ /* RS-422 */
+ dev_vdbg(port->dev, "4-wire\n");
+ pcr |= NI16550_PCR_RS422;
+ acr |= NI16550_ACR_DTR_MANUAL_DTR;
+ }
+
+ dev_dbg(port->dev, "write pcr: 0x%08x\n", pcr);
+ port->serial_out(port, NI16550_PCR_OFFSET, pcr);
+
+ up->acr = acr;
+ port->serial_out(port, UART_SCR, UART_ACR);
+ port->serial_out(port, UART_ICR, up->acr);
+
+ /* Update the cache. */
+ port->rs485 = *rs485;
+
+ dev_dbg(port->dev, "ni16550_config_rs485\n");
+ return 0;
+}
+
+static int pci_ni8431_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *uart, int idx)
+{
+ u8 pcr, acr;
+ struct pci_dev *dev = priv->dev;
+ void __iomem *addr;
+ unsigned int bar, offset = board->first_offset;
+
+ if (idx >= board->num_ports)
+ return 1;
+
+ bar = FL_GET_BASE(board->flags);
+ offset += idx * board->uart_offset;
+
+ addr = pci_ioremap_bar(dev, bar);
+ if (!addr)
+ return -ENOMEM;
+
+ /* enable the transceiver */
+ writeb(readb(addr + NI16550_PCR_OFFSET) | NI16550_PCR_TXVR_ENABLE_BIT,
+ addr + NI16550_PCR_OFFSET);
+
+ pcr = readb(addr + NI16550_PCR_OFFSET);
+ pcr &= ~NI16550_PCR_WIRE_MODE_MASK;
+
+ /* set wire mode to default RS-422 */
+ pcr |= NI16550_PCR_RS422;
+ acr = NI16550_ACR_DTR_MANUAL_DTR;
+
+ /* write port configuration to register */
+ writeb(pcr, addr + NI16550_PCR_OFFSET);
+
+ /* access and write to UART acr register */
+ writeb(UART_ACR, addr + UART_SCR);
+ writeb(acr, addr + UART_ICR);
+
+ uart->port.rs485_config = &pci_ni8431_config_rs485;
+
+ iounmap(addr);
+
+ return setup_port(priv, uart, bar, offset, board->reg_shift);
+}
+
static int pci_netmos_9900_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
@@ -1956,6 +2077,87 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.setup = pci_ni8430_setup,
.exit = pci_ni8430_exit,
},
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCIE_DEVICE_ID_NI_PXIE8430_2328,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8430_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCIE_DEVICE_ID_NI_PXIE8430_23216,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8430_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8431_4852,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8431_4854,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8431_4858,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8433_4852,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8433_4854,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCIE_DEVICE_ID_NI_PXIE8431_4858,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCIE_DEVICE_ID_NI_PXIE8431_48516,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
/* Quatech */
{
.vendor = PCI_VENDOR_ID_QUATECH,
@@ -2679,6 +2881,13 @@ enum pci_board_num_t {
pbn_ni8430_4,
pbn_ni8430_8,
pbn_ni8430_16,
+ pbn_ni8430_pxie_8,
+ pbn_ni8430_pxie_16,
+ pbn_ni8431_2,
+ pbn_ni8431_4,
+ pbn_ni8431_8,
+ pbn_ni8431_pxie_8,
+ pbn_ni8431_pxie_16,
pbn_ADDIDATA_PCIe_1_3906250,
pbn_ADDIDATA_PCIe_2_3906250,
pbn_ADDIDATA_PCIe_4_3906250,
@@ -3320,6 +3529,55 @@ static struct pciserial_board pci_boards[] = {
.uart_offset = 0x10,
.first_offset = 0x800,
},
+ [pbn_ni8430_pxie_16] = {
+ .flags = FL_BASE0,
+ .num_ports = 16,
+ .base_baud = 3125000,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8430_pxie_8] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 3125000,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8431_8] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 3686400,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8431_4] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 3686400,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8431_2] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 3686400,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8431_pxie_16] = {
+ .flags = FL_BASE0,
+ .num_ports = 16,
+ .base_baud = 3125000,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8431_pxie_8] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 3125000,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
/*
* ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com>
*/
@@ -5003,6 +5261,33 @@ static const struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_ni8430_4 },
+ { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_2328,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_pxie_8 },
+ { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_23216,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_pxie_16 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4852,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_2 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4854,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_4 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4858,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_8 },
+ { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_4858,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_pxie_8 },
+ { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_48516,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_pxie_16 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4852,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_2 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4854,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_4 },
/*
* ADDI-DATA GmbH communication cards <info@addi-data.com>
--
2.17.1
^ permalink raw reply related
* Re: [PATCH v1] tty: serial: max310x: Add optional reset gpio
From: Jan Kundrát @ 2019-07-02 14:44 UTC (permalink / raw)
To: Mylène Josserand
Cc: gregkh, robh+dt, mark.rutland, linux-serial, devicetree,
linux-kernel, thomas.petazzoni
In-Reply-To: <20190614141112.29962-1-mylene.josserand@bootlin.com>
On pátek 14. června 2019 16:11:12 CEST, Mylène Josserand wrote:
> --- a/Documentation/devicetree/bindings/serial/maxim,max310x.txt
> +++ b/Documentation/devicetree/bindings/serial/maxim,max310x.txt
> @@ -15,6 +15,7 @@ Required properties:
> "osc" if an external clock source is used.
>
> Optional properties:
> +- reset-gpios: Gpio to use for reset.
"GPIO", not "Gpio", for consistency.
> if (spi->dev.of_node) {
> + struct gpio_desc *reset_gpio;
> const struct of_device_id *of_id =
> of_match_device(max310x_dt_ids, &spi->dev);
> if (!of_id)
> return -ENODEV;
>
> devtype = (struct max310x_devtype *)of_id->data;
> + reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset",
> + GPIOD_OUT_HIGH);
> + if (IS_ERR(reset_gpio))
> + return PTR_ERR(reset_gpio);
> + gpiod_set_value_cansleep(reset_gpio, 0);
> } else {
The RST signal is active-low on the chip, but the code initializes the
output to GPIOD_OUT_HIGH. Are you perhaps relying on a DT binding setting
an ACTIVE_LOW flag on the reset GPIO lane? This should be documented.
Assuming that this polarity inversion works, the code first asserts the
reset, then it performs no explicit waiting, and then it clears the RST
signal. I checked MAX14830's datasheet, and there's no minimal reset
duration, so perhaps this is safe, but it looks a bit odd to me.
With kind regards,
Jan
^ permalink raw reply
* [PATCH 2/2] PCI: Add NI-Serial PXI/PXIe+485 device IDs
From: jeyentam @ 2019-07-02 3:24 UTC (permalink / raw)
To: gregkh; +Cc: linux-serial, linux-kernel, jeyentam
Add NI PXIe-RS232, PXI-RS485 and PXIe-RS485 device IDs.
Signed-off-by: jeyentam <je.yen.tam@ni.com>
---
include/linux/pci_ids.h | 62 ++++++++++++++++++++++++-----------------
1 file changed, 37 insertions(+), 25 deletions(-)
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 70e86148cb1e..cc1f61575eb4 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1027,31 +1027,43 @@
#define PCI_DEVICE_ID_SUN_TOMATILLO 0xa801
#define PCI_DEVICE_ID_SUN_CASSINI 0xabba
-#define PCI_VENDOR_ID_NI 0x1093
-#define PCI_DEVICE_ID_NI_PCI2322 0xd130
-#define PCI_DEVICE_ID_NI_PCI2324 0xd140
-#define PCI_DEVICE_ID_NI_PCI2328 0xd150
-#define PCI_DEVICE_ID_NI_PXI8422_2322 0xd190
-#define PCI_DEVICE_ID_NI_PXI8422_2324 0xd1a0
-#define PCI_DEVICE_ID_NI_PXI8420_2322 0xd1d0
-#define PCI_DEVICE_ID_NI_PXI8420_2324 0xd1e0
-#define PCI_DEVICE_ID_NI_PXI8420_2328 0xd1f0
-#define PCI_DEVICE_ID_NI_PXI8420_23216 0xd1f1
-#define PCI_DEVICE_ID_NI_PCI2322I 0xd250
-#define PCI_DEVICE_ID_NI_PCI2324I 0xd270
-#define PCI_DEVICE_ID_NI_PCI23216 0xd2b0
-#define PCI_DEVICE_ID_NI_PXI8430_2322 0x7080
-#define PCI_DEVICE_ID_NI_PCI8430_2322 0x70db
-#define PCI_DEVICE_ID_NI_PXI8430_2324 0x70dd
-#define PCI_DEVICE_ID_NI_PCI8430_2324 0x70df
-#define PCI_DEVICE_ID_NI_PXI8430_2328 0x70e2
-#define PCI_DEVICE_ID_NI_PCI8430_2328 0x70e4
-#define PCI_DEVICE_ID_NI_PXI8430_23216 0x70e6
-#define PCI_DEVICE_ID_NI_PCI8430_23216 0x70e7
-#define PCI_DEVICE_ID_NI_PXI8432_2322 0x70e8
-#define PCI_DEVICE_ID_NI_PCI8432_2322 0x70ea
-#define PCI_DEVICE_ID_NI_PXI8432_2324 0x70ec
-#define PCI_DEVICE_ID_NI_PCI8432_2324 0x70ee
+/* NI-Serial Device IDs */
+#define PCI_VENDOR_ID_NI 0x1093
+/* NI PXI(e) RS-232 Devices */
+#define PCI_DEVICE_ID_NI_PCI2322 0xd130
+#define PCI_DEVICE_ID_NI_PCI2324 0xd140
+#define PCI_DEVICE_ID_NI_PCI2328 0xd150
+#define PCI_DEVICE_ID_NI_PXI8422_2322 0xd190
+#define PCI_DEVICE_ID_NI_PXI8422_2324 0xd1a0
+#define PCI_DEVICE_ID_NI_PXI8420_2322 0xd1d0
+#define PCI_DEVICE_ID_NI_PXI8420_2324 0xd1e0
+#define PCI_DEVICE_ID_NI_PXI8420_2328 0xd1f0
+#define PCI_DEVICE_ID_NI_PXI8420_23216 0xd1f1
+#define PCI_DEVICE_ID_NI_PCI2322I 0xd250
+#define PCI_DEVICE_ID_NI_PCI2324I 0xd270
+#define PCI_DEVICE_ID_NI_PCI23216 0xd2b0
+#define PCI_DEVICE_ID_NI_PXI8430_2322 0x7080
+#define PCI_DEVICE_ID_NI_PCI8430_2322 0x70db
+#define PCI_DEVICE_ID_NI_PXI8430_2324 0x70dd
+#define PCI_DEVICE_ID_NI_PCI8430_2324 0x70df
+#define PCI_DEVICE_ID_NI_PXI8430_2328 0x70e2
+#define PCI_DEVICE_ID_NI_PCI8430_2328 0x70e4
+#define PCI_DEVICE_ID_NI_PXI8430_23216 0x70e6
+#define PCI_DEVICE_ID_NI_PCI8430_23216 0x70e7
+#define PCI_DEVICE_ID_NI_PXI8432_2322 0x70e8
+#define PCI_DEVICE_ID_NI_PCI8432_2322 0x70ea
+#define PCI_DEVICE_ID_NI_PXI8432_2324 0x70ec
+#define PCI_DEVICE_ID_NI_PCI8432_2324 0x70ee
+#define PCIE_DEVICE_ID_NI_PXIE8430_2328 0x74C2
+#define PCIE_DEVICE_ID_NI_PXIE8430_23216 0x74C1
+/* NI PXI(e) RS-485 Devices */
+#define PCI_DEVICE_ID_NI_PXI8431_4852 0x7081
+#define PCI_DEVICE_ID_NI_PXI8431_4854 0x70DE
+#define PCI_DEVICE_ID_NI_PXI8431_4858 0x70E3
+#define PCI_DEVICE_ID_NI_PXI8433_4852 0x70E9
+#define PCI_DEVICE_ID_NI_PXI8433_4854 0x70ED
+#define PCIE_DEVICE_ID_NI_PXIE8431_4858 0x74C4
+#define PCIE_DEVICE_ID_NI_PXIE8431_48516 0x74C3
#define PCI_VENDOR_ID_CMD 0x1095
#define PCI_DEVICE_ID_CMD_643 0x0643
--
2.17.1
^ permalink raw reply related
* [PATCH 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices.
From: jeyentam @ 2019-07-02 3:23 UTC (permalink / raw)
To: gregkh; +Cc: linux-serial, linux-kernel, jeyentam
Add support for NI-Serial PXIe-RS232, PXI-RS485 and PXIe-RS485 devices.
Signed-off-by: jeyentam <je.yen.tam@ni.com>
---
drivers/tty/serial/8250/8250_pci.c | 879 +++++++++++++++++++----------
1 file changed, 582 insertions(+), 297 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index df41397de478..0a711b895b33 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Probe module for 8250/16550-type PCI serial ports.
+ * Probe module for 8250/16550-type PCI serial ports.
*
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
*
- * Copyright (C) 2001 Russell King, All Rights Reserved.
+ * Copyright (C) 2001 Russell King, All Rights Reserved.
*/
#undef DEBUG
#include <linux/module.h>
@@ -26,9 +26,9 @@
/*
* init function returns:
- * > 0 - number of ports
- * = 0 - use board->num_ports
- * < 0 - error
+ * > 0 - number of ports
+ * = 0 - use board->num_ports
+ * < 0 - error
*/
struct pci_serial_quirk {
u32 vendor;
@@ -59,13 +59,13 @@ static int pci_default_setup(struct serial_private*,
static void moan_device(const char *str, struct pci_dev *dev)
{
dev_err(&dev->dev,
- "%s: %s\n"
- "Please send the output of lspci -vv, this\n"
- "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
- "manufacturer and name of serial board or\n"
- "modem board to <linux-serial@vger.kernel.org>.\n",
- pci_name(dev), str, dev->vendor, dev->device,
- dev->subsystem_vendor, dev->subsystem_device);
+ "%s: %s\n"
+ "Please send the output of lspci -vv, this\n"
+ "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
+ "manufacturer and name of serial board or\n"
+ "modem board to <linux-serial@vger.kernel.org>.\n",
+ pci_name(dev), str, dev->vendor, dev->device,
+ dev->subsystem_vendor, dev->subsystem_device);
}
static int
@@ -128,7 +128,7 @@ static int addidata_apci7800_setup(struct serial_private *priv,
*/
static int
afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -144,9 +144,9 @@ afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
}
/*
- * HP's Remote Management Console. The Diva chip came in several
- * different versions. N-class, L2000 and A500 have two Diva chips, each
- * with 3 UARTs (the third UART on the second chip is unused). Superdome
+ * HP's Remote Management Console. The Diva chip came in several
+ * different versions. N-class, L2000 and A500 have two Diva chips, each
+ * with 3 UARTs (the third UART on the second chip is unused). Superdome
* and Keystone have one Diva chip with 3 UARTs. Some later machines have
* one Diva chip, but it has been expanded to 5 UARTs.
*/
@@ -245,11 +245,11 @@ static int pci_plx9050_init(struct pci_dev *dev)
irq_config = 0x41;
if (dev->vendor == PCI_VENDOR_ID_PANACOM ||
- dev->subsystem_vendor == PCI_SUBVENDOR_ID_EXSYS)
+ dev->subsystem_vendor == PCI_SUBVENDOR_ID_EXSYS)
irq_config = 0x43;
if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
- (dev->device == PCI_DEVICE_ID_PLX_ROMULUS))
+ (dev->device == PCI_DEVICE_ID_PLX_ROMULUS))
/*
* As the megawolf cards have the int pins active
* high, and have 2 UART chips, both ints must be
@@ -317,7 +317,7 @@ static void pci_ni8420_exit(struct pci_dev *dev)
/* Disable the CPU Interrupt */
writel(readl(p + NI8420_INT_ENABLE_REG) & ~(NI8420_INT_ENABLE_BIT),
- p + NI8420_INT_ENABLE_REG);
+ p + NI8420_INT_ENABLE_REG);
iounmap(p);
}
@@ -426,15 +426,15 @@ static void sbs_exit(struct pci_dev *dev)
* hope) because it doesn't touch EEPROM settings to prevent conflicts
* with other OSes (like M$ DOS).
*
- * SIIG support added by Andrey Panin <pazke@donpac.ru>, 10/1999
+ * SIIG support added by Andrey Panin <pazke@donpac.ru>, 10/1999
*
* There is two family of SIIG serial cards with different PCI
* interface chip and different configuration methods:
- * - 10x cards have control registers in IO and/or memory space;
- * - 20x cards have control registers in standard PCI configuration space.
+ * - 10x cards have control registers in IO and/or memory space;
+ * - 20x cards have control registers in standard PCI configuration space.
*
* Note: all 10x cards have PCI device ids 0x10..
- * all 20x cards have PCI device ids 0x20..
+ * all 20x cards have PCI device ids 0x20..
*
* There are also Quartet Serial cards which use Oxford Semiconductor
* 16954 quad UART PCI chip clocked by 18.432 MHz quartz.
@@ -485,7 +485,7 @@ static int pci_siig20x_init(struct pci_dev *dev)
/* If this card has 2 UART, we have to do the same with second UART. */
if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
- ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
+ ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
pci_read_config_byte(dev, 0x73, &data);
pci_write_config_byte(dev, 0x73, data & 0xef);
}
@@ -559,9 +559,9 @@ static const struct timedia_struct {
};
/*
- * There are nearly 70 different Timedia/SUNIX PCI serial devices. Instead of
+ * There are nearly 70 different Timedia/SUNIX PCI serial devices. Instead of
* listing them individually, this driver merely grabs them all with
- * PCI_ANY_ID. Some of these devices, however, also feature a parallel port,
+ * PCI_ANY_ID. Some of these devices, however, also feature a parallel port,
* and should be left free to be claimed by parport_serial instead.
*/
static int pci_timedia_probe(struct pci_dev *dev)
@@ -634,8 +634,8 @@ pci_timedia_setup(struct serial_private *priv,
*/
static int
titan_400l_800l_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -676,7 +676,7 @@ static int pci_ni8420_init(struct pci_dev *dev)
/* Enable CPU Interrupt */
writel(readl(p + NI8420_INT_ENABLE_REG) | NI8420_INT_ENABLE_BIT,
- p + NI8420_INT_ENABLE_REG);
+ p + NI8420_INT_ENABLE_REG);
iounmap(p);
return 0;
@@ -717,7 +717,7 @@ static int pci_ni8430_init(struct pci_dev *dev)
/* Set window access to go to RAMSEL IO address space */
writel((readl(p + MITE_IOWCR1) & MITE_IOWCR1_RAMSEL_MASK),
- p + MITE_IOWCR1);
+ p + MITE_IOWCR1);
/* Enable IO Bus Interrupt 0 */
writel(MITE_LCIMR1_IO_IE_0, p + MITE_LCIMR1);
@@ -730,8 +730,16 @@ static int pci_ni8430_init(struct pci_dev *dev)
}
/* UART Port Control Register */
-#define NI8430_PORTCON 0x0f
-#define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
+#define NI16550_PCR_OFFSET 0x0f
+#define NI16550_PCR_RS422 0x00
+#define NI16550_PCR_ECHO_RS485 0x01
+#define NI16550_PCR_DTR_RS485 0x02
+#define NI16550_PCR_AUTO_RS485 0x03
+#define NI16550_PCR_WIRE_MODE_MASK 0x03
+#define NI16550_PCR_TXVR_ENABLE_BIT (1 << 3)
+#define NI16550_PCR_RS485_TERMINATION_BIT (1 << 6)
+#define NI16550_ACR_DTR_AUTO_DTR (0x2 << 3)
+#define NI16550_ACR_DTR_MANUAL_DTR (0x0 << 3)
static int
pci_ni8430_setup(struct serial_private *priv,
@@ -753,14 +761,127 @@ pci_ni8430_setup(struct serial_private *priv,
return -ENOMEM;
/* enable the transceiver */
- writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE,
- p + offset + NI8430_PORTCON);
+ writeb(readb(p + offset + NI16550_PCR_OFFSET) |
+ NI16550_PCR_TXVR_ENABLE_BIT,
+ p + offset + NI16550_PCR_OFFSET);
iounmap(p);
return setup_port(priv, port, bar, offset, board->reg_shift);
}
+static int pci_ni8431_config_rs485(struct uart_port *port,
+ struct serial_rs485 *rs485)
+{
+ u8 pcr, acr;
+
+ struct uart_8250_port *up;
+
+ up = container_of(port, struct uart_8250_port, port);
+
+ acr = up->acr;
+
+ dev_dbg(port->dev, "ni16550_config_rs485\n");
+
+ /* "rs485" should be given to us non-NULL. */
+ WARN_ON(rs485 == NULL);
+
+ pcr = port->serial_in(port, NI16550_PCR_OFFSET);
+ pcr &= ~NI16550_PCR_WIRE_MODE_MASK;
+
+ if (rs485->flags & SER_RS485_ENABLED) {
+ /* RS-485 */
+ if ((rs485->flags & SER_RS485_RX_DURING_TX) &&
+ (rs485->flags & SER_RS485_RTS_ON_SEND)) {
+ dev_dbg(port->dev, "Invalid 2-wire mode\n");
+ return -EINVAL;
+ }
+
+ if (rs485->flags & SER_RS485_RX_DURING_TX) {
+ /* Echo */
+ dev_vdbg(port->dev, "2-wire DTR with echo\n");
+ pcr |= NI16550_PCR_ECHO_RS485;
+ acr |= NI16550_ACR_DTR_MANUAL_DTR;
+ } else {
+ /* Auto or DTR */
+ if (rs485->flags & SER_RS485_RTS_ON_SEND) {
+ /* Auto */
+ dev_vdbg(port->dev, "2-wire Auto\n");
+ pcr |= NI16550_PCR_AUTO_RS485;
+ acr |= NI16550_ACR_DTR_AUTO_DTR;
+ } else {
+ /* DTR-controlled */
+ /* No Echo */
+ dev_vdbg(port->dev, "2-wire DTR no echo\n");
+ pcr |= NI16550_PCR_DTR_RS485;
+ acr |= NI16550_ACR_DTR_MANUAL_DTR;
+ }
+ }
+ } else {
+ /* RS-422 */
+ dev_vdbg(port->dev, "4-wire\n");
+ pcr |= NI16550_PCR_RS422;
+ acr |= NI16550_ACR_DTR_MANUAL_DTR;
+ }
+
+ dev_dbg(port->dev, "write pcr: 0x%08x\n", pcr);
+ port->serial_out(port, NI16550_PCR_OFFSET, pcr);
+
+ up->acr = acr;
+ port->serial_out(port, UART_SCR, UART_ACR);
+ port->serial_out(port, UART_ICR, up->acr);
+
+ /* Update the cache. */
+ port->rs485 = *rs485;
+
+ dev_dbg(port->dev, "ni16550_config_rs485\n");
+ return 0;
+}
+
+static int pci_ni8431_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *uart, int idx)
+{
+ u8 pcr, acr;
+ struct pci_dev *dev = priv->dev;
+ void __iomem *addr;
+ unsigned int bar, offset = board->first_offset;
+
+ if (idx >= board->num_ports)
+ return 1;
+
+ bar = FL_GET_BASE(board->flags);
+ offset += idx * board->uart_offset;
+
+ addr = pci_ioremap_bar(dev, bar);
+ if (!addr)
+ return -ENOMEM;
+
+ /* enable the transceiver */
+ writeb(readb(addr + NI16550_PCR_OFFSET) | NI16550_PCR_TXVR_ENABLE_BIT,
+ addr + NI16550_PCR_OFFSET);
+
+ pcr = readb(addr + NI16550_PCR_OFFSET);
+ pcr &= ~NI16550_PCR_WIRE_MODE_MASK;
+
+ /* set wire mode to default RS-422 */
+ pcr |= NI16550_PCR_RS422;
+ acr = NI16550_ACR_DTR_MANUAL_DTR;
+
+ /* write port configuration to register */
+ writeb(pcr, addr + NI16550_PCR_OFFSET);
+
+ /* access and write to UART acr register */
+ writeb(UART_ACR, addr + UART_SCR);
+ writeb(acr, addr + UART_ICR);
+
+ uart->port.rs485_config = &pci_ni8431_config_rs485;
+
+ iounmap(addr);
+
+ return setup_port(priv, uart, bar, offset, board->reg_shift);
+}
+
static int pci_netmos_9900_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
@@ -768,7 +889,7 @@ static int pci_netmos_9900_setup(struct serial_private *priv,
unsigned int bar;
if ((priv->dev->device != PCI_DEVICE_ID_NETMOS_9865) &&
- (priv->dev->subsystem_device & 0xff00) == 0x3000) {
+ (priv->dev->subsystem_device & 0xff00) == 0x3000) {
/* netmos apparently orders BARs by datasheet layout, so serial
* ports get BARs 0 and 3 (or 1 and 4 for memmapped)
*/
@@ -784,7 +905,7 @@ static int pci_netmos_9900_setup(struct serial_private *priv,
* of capabilities:
*
* 9900 has varying capabilities and can cascade to sub-controllers
- * (cascading should be purely internal)
+ * (cascading should be purely internal)
* 9904 is hardwired with 4 serial ports
* 9912 and 9922 are hardwired with 2 serial ports
*/
@@ -1030,7 +1151,7 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
/* OxSemi Tornado devices are all 0xCxxx */
if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
- (dev->device & 0xF000) != 0xC000)
+ (dev->device & 0xF000) != 0xC000)
return 0;
p = pci_iomap(dev, 0, 5);
@@ -1081,10 +1202,10 @@ struct quatech_feature {
static struct quatech_feature quatech_cards[] = {
- { PCI_DEVICE_ID_QUATECH_QSC100, 1 },
- { PCI_DEVICE_ID_QUATECH_DSC100, 1 },
+ { PCI_DEVICE_ID_QUATECH_QSC100, 1 },
+ { PCI_DEVICE_ID_QUATECH_DSC100, 1 },
{ PCI_DEVICE_ID_QUATECH_DSC100E, 0 },
- { PCI_DEVICE_ID_QUATECH_DSC200, 1 },
+ { PCI_DEVICE_ID_QUATECH_DSC200, 1 },
{ PCI_DEVICE_ID_QUATECH_DSC200E, 0 },
{ PCI_DEVICE_ID_QUATECH_ESC100D, 1 },
{ PCI_DEVICE_ID_QUATECH_ESC100M, 1 },
@@ -1237,7 +1358,7 @@ static int pci_quatech_clock(struct uart_8250_port *port)
}
reg &= QOPR_CLOCK_X8;
if (reg == QOPR_CLOCK_X2) {
- clock = 3685400;
+ clock = 3685400;
set = QOPR_CLOCK_X2;
} else if (reg == QOPR_CLOCK_X4) {
clock = 7372800;
@@ -1369,8 +1490,8 @@ ce4100_serial_setup(struct serial_private *priv,
static int
pci_omegapci_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
{
return setup_port(priv, port, 2, idx * 8, 0);
}
@@ -1394,7 +1515,7 @@ pci_brcm_trumanage_setup(struct serial_private *priv,
/* We should do proper H/W transceiver setting before change to RS485 mode */
static int pci_fintek_rs485_config(struct uart_port *port,
- struct serial_rs485 *rs485)
+ struct serial_rs485 *rs485)
{
struct pci_dev *pci_dev = to_pci_dev(port->dev);
u8 setting;
@@ -1440,8 +1561,8 @@ static int pci_fintek_rs485_config(struct uart_port *port,
}
static int pci_fintek_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
{
struct pci_dev *pdev = priv->dev;
u8 *data;
@@ -1574,7 +1695,7 @@ static unsigned int kt_serial_in(struct uart_port *p, int offset)
* When the Intel ME (management engine) gets reset its serial
* port registers could return 0 momentarily. Functions like
* serial8250_console_write, read and save the IER, perform
- * some operation and then restore it. In order to avoid
+ * some operation and then restore it. In order to avoid
* setting IER register inadvertently to 0, if the value read
* is 0, double check with ier value in uart_8250_port and use
* that instead. up->ier should be the same value as what is
@@ -1609,8 +1730,8 @@ static int pci_eg20t_init(struct pci_dev *dev)
static int
pci_wch_ch353_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
{
port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16550A;
@@ -1629,8 +1750,8 @@ pci_wch_ch355_setup(struct serial_private *priv,
static int
pci_wch_ch38x_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
{
port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16850;
@@ -1750,15 +1871,15 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
* ADDI-DATA GmbH communication cards <info@addi-data.com>
*/
{
- .vendor = PCI_VENDOR_ID_AMCC,
- .device = PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = addidata_apci7800_setup,
+ .vendor = PCI_VENDOR_ID_AMCC,
+ .device = PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = addidata_apci7800_setup,
},
/*
* AFAVLAB cards - these may be called via parport_serial
- * It is not clear whether this applies to all products.
+ * It is not clear whether this applies to all products.
*/
{
.vendor = PCI_VENDOR_ID_AFAVLAB,
@@ -1956,6 +2077,87 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.setup = pci_ni8430_setup,
.exit = pci_ni8430_exit,
},
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCIE_DEVICE_ID_NI_PXIE8430_2328,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8430_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCIE_DEVICE_ID_NI_PXIE8430_23216,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8430_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8431_4852,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8431_4854,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8431_4858,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8433_4852,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8433_4854,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCIE_DEVICE_ID_NI_PXIE8431_4858,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCIE_DEVICE_ID_NI_PXIE8431_48516,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8431_setup,
+ .exit = pci_ni8430_exit,
+ },
/* Quatech */
{
.vendor = PCI_VENDOR_ID_QUATECH,
@@ -2028,109 +2230,109 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.exit = pci_plx9050_exit,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
{
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
/*
* SBS Technologies, Inc., PMC-OCTALPRO 232
@@ -2305,72 +2507,72 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.setup = pci_default_setup,
},
{
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = 0x8811,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x8811,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = 0x8812,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x8812,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = 0x8813,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x8813,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = 0x8814,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x8814,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
- .vendor = 0x10DB,
- .device = 0x8027,
+ .vendor = 0x10DB,
+ .device = 0x8027,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
- .vendor = 0x10DB,
- .device = 0x8028,
+ .vendor = 0x10DB,
+ .device = 0x8028,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
- .vendor = 0x10DB,
- .device = 0x8029,
+ .vendor = 0x10DB,
+ .device = 0x8029,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
- .vendor = 0x10DB,
- .device = 0x800C,
+ .vendor = 0x10DB,
+ .device = 0x800C,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
- .vendor = 0x10DB,
- .device = 0x800D,
+ .vendor = 0x10DB,
+ .device = 0x800D,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
@@ -2388,35 +2590,35 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
},
/* WCH CH353 1S1P card (16550 clone) */
{
- .vendor = PCI_VENDOR_ID_WCH,
- .device = PCI_DEVICE_ID_WCH_CH353_1S1P,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_wch_ch353_setup,
+ .vendor = PCI_VENDOR_ID_WCH,
+ .device = PCI_DEVICE_ID_WCH_CH353_1S1P,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch353_setup,
},
/* WCH CH353 2S1P card (16550 clone) */
{
- .vendor = PCI_VENDOR_ID_WCH,
- .device = PCI_DEVICE_ID_WCH_CH353_2S1P,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_wch_ch353_setup,
+ .vendor = PCI_VENDOR_ID_WCH,
+ .device = PCI_DEVICE_ID_WCH_CH353_2S1P,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch353_setup,
},
/* WCH CH353 4S card (16550 clone) */
{
- .vendor = PCI_VENDOR_ID_WCH,
- .device = PCI_DEVICE_ID_WCH_CH353_4S,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_wch_ch353_setup,
+ .vendor = PCI_VENDOR_ID_WCH,
+ .device = PCI_DEVICE_ID_WCH_CH353_4S,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch353_setup,
},
/* WCH CH353 2S1PF card (16550 clone) */
{
- .vendor = PCI_VENDOR_ID_WCH,
- .device = PCI_DEVICE_ID_WCH_CH353_2S1PF,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_wch_ch353_setup,
+ .vendor = PCI_VENDOR_ID_WCH,
+ .device = PCI_DEVICE_ID_WCH_CH353_2S1PF,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch353_setup,
},
/* WCH CH352 2S card (16550 clone) */
{
@@ -2436,27 +2638,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
},
/* WCH CH382 2S card (16850 clone) */
{
- .vendor = PCIE_VENDOR_ID_WCH,
- .device = PCIE_DEVICE_ID_WCH_CH382_2S,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_wch_ch38x_setup,
+ .vendor = PCIE_VENDOR_ID_WCH,
+ .device = PCIE_DEVICE_ID_WCH_CH382_2S,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch38x_setup,
},
/* WCH CH382 2S1P card (16850 clone) */
{
- .vendor = PCIE_VENDOR_ID_WCH,
- .device = PCIE_DEVICE_ID_WCH_CH382_2S1P,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_wch_ch38x_setup,
+ .vendor = PCIE_VENDOR_ID_WCH,
+ .device = PCIE_DEVICE_ID_WCH_CH382_2S1P,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch38x_setup,
},
/* WCH CH384 4S card (16850 clone) */
{
- .vendor = PCIE_VENDOR_ID_WCH,
- .device = PCIE_DEVICE_ID_WCH_CH384_4S,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_wch_ch38x_setup,
+ .vendor = PCIE_VENDOR_ID_WCH,
+ .device = PCIE_DEVICE_ID_WCH_CH384_4S,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch38x_setup,
},
/*
* ASIX devices with FIFO bug
@@ -2526,9 +2728,9 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
for (quirk = pci_serial_quirks; ; quirk++)
if (quirk_id_matches(quirk->vendor, dev->vendor) &&
- quirk_id_matches(quirk->device, dev->device) &&
- quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) &&
- quirk_id_matches(quirk->subdevice, dev->subsystem_device))
+ quirk_id_matches(quirk->device, dev->device) &&
+ quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) &&
+ quirk_id_matches(quirk->subdevice, dev->subsystem_device))
break;
return quirk;
}
@@ -2549,13 +2751,13 @@ static inline int get_pci_irq(struct pci_dev *dev,
* driver_data member.
*
* The makeup of these names are:
- * pbn_bn{_bt}_n_baud{_offsetinhex}
+ * pbn_bn{_bt}_n_baud{_offsetinhex}
*
- * bn = PCI BAR number
- * bt = Index using PCI BARs
- * n = number of serial ports
- * baud = baud rate
- * offsetinhex = offset for each sequential port (in hex)
+ * bn = PCI BAR number
+ * bt = Index using PCI BARs
+ * n = number of serial ports
+ * baud = baud rate
+ * offsetinhex = offset for each sequential port (in hex)
*
* This table is sorted by (in order): bn, bt, baud, offsetindex, n.
*
@@ -2679,6 +2881,13 @@ enum pci_board_num_t {
pbn_ni8430_4,
pbn_ni8430_8,
pbn_ni8430_16,
+ pbn_ni8430_pxie_8,
+ pbn_ni8430_pxie_16,
+ pbn_ni8431_2,
+ pbn_ni8431_4,
+ pbn_ni8431_8,
+ pbn_ni8431_pxie_8,
+ pbn_ni8431_pxie_16,
pbn_ADDIDATA_PCIe_1_3906250,
pbn_ADDIDATA_PCIe_2_3906250,
pbn_ADDIDATA_PCIe_4_3906250,
@@ -2701,7 +2910,7 @@ enum pci_board_num_t {
/*
* uart_offset - the space between channels
* reg_shift - describes how the UART registers are mapped
- * to PCI memory by the card.
+ * to PCI memory by the card.
* For example IER register on SBS, Inc. PMC-OctPro is located at
* offset 0x10 from the UART base, while UART_IER is defined as 1
* in include/linux/serial_reg.h,
@@ -2765,10 +2974,10 @@ static struct pciserial_board pci_boards[] = {
},
[pbn_b0_2_1130000] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 1130000,
- .uart_offset = 8,
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 1130000,
+ .uart_offset = 8,
},
[pbn_b0_4_1152000] = {
@@ -3000,10 +3209,10 @@ static struct pciserial_board pci_boards[] = {
.uart_offset = 8,
},
[pbn_b2_4_115200] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
+ .flags = FL_BASE2,
+ .num_ports = 4,
+ .base_baud = 115200,
+ .uart_offset = 8,
},
[pbn_b2_8_115200] = {
.flags = FL_BASE2,
@@ -3320,6 +3529,55 @@ static struct pciserial_board pci_boards[] = {
.uart_offset = 0x10,
.first_offset = 0x800,
},
+ [pbn_ni8430_pxie_16] = {
+ .flags = FL_BASE0,
+ .num_ports = 16,
+ .base_baud = 3125000,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8430_pxie_8] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 3125000,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8431_8] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 3686400,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8431_4] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 3686400,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8431_2] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 3686400,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8431_pxie_16] = {
+ .flags = FL_BASE0,
+ .num_ports = 16,
+ .base_baud = 3125000,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8431_pxie_8] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 3125000,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
/*
* ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com>
*/
@@ -3355,7 +3613,7 @@ static struct pciserial_board pci_boards[] = {
.flags = FL_BASE_BARS,
.num_ports = 2,
.base_baud = 921600,
- .reg_shift = 2,
+ .reg_shift = 2,
},
[pbn_omegapci] = {
.flags = FL_BASE0,
@@ -3402,35 +3660,35 @@ static struct pciserial_board pci_boards[] = {
[pbn_wch384_4] = {
.flags = FL_BASE0,
.num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- .first_offset = 0xC0,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ .first_offset = 0xC0,
},
/*
* Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
*/
[pbn_pericom_PI7C9X7951] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 921600,
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
.uart_offset = 0x8,
},
[pbn_pericom_PI7C9X7952] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 921600,
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 921600,
.uart_offset = 0x8,
},
[pbn_pericom_PI7C9X7954] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 921600,
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 921600,
.uart_offset = 0x8,
},
[pbn_pericom_PI7C9X7958] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 921600,
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 921600,
.uart_offset = 0x8,
},
};
@@ -3492,9 +3750,9 @@ static int serial_pci_is_class_communication(struct pci_dev *dev)
* interface is greater than 6, give up.
*/
if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
- ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MULTISERIAL) &&
- ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
- (dev->class & 0xff) > 6)
+ ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MULTISERIAL) &&
+ ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
+ (dev->class & 0xff) > 6)
return -ENODEV;
return 0;
@@ -3534,7 +3792,7 @@ serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
/*
* If there is 1 or 0 iomem regions, and exactly one port,
- * use it. We guess the number of ports based on the IO
+ * use it. We guess the number of ports based on the IO
* region size.
*/
if (num_iomem <= 1 && num_port == 1) {
@@ -3552,8 +3810,8 @@ serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
num_port = 0;
for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
if (pci_resource_flags(dev, i) & IORESOURCE_IO &&
- pci_resource_len(dev, i) == 8 &&
- (first_port == -1 || (first_port + num_port) == i)) {
+ pci_resource_len(dev, i) == 8 &&
+ (first_port == -1 || (first_port + num_port) == i)) {
num_port++;
if (first_port == -1)
first_port = i;
@@ -3574,11 +3832,11 @@ serial_pci_matches(const struct pciserial_board *board,
const struct pciserial_board *guessed)
{
return
- board->num_ports == guessed->num_ports &&
- board->base_baud == guessed->base_baud &&
- board->uart_offset == guessed->uart_offset &&
- board->reg_shift == guessed->reg_shift &&
- board->first_offset == guessed->first_offset;
+ board->num_ports == guessed->num_ports &&
+ board->base_baud == guessed->base_baud &&
+ board->uart_offset == guessed->uart_offset &&
+ board->reg_shift == guessed->reg_shift &&
+ board->first_offset == guessed->first_offset;
}
struct serial_private *
@@ -3599,9 +3857,9 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
/*
* Run the new-style initialization function.
* The initialization function returns:
- * <0 - error
- * 0 - use board->num_ports
- * >0 - number of ports
+ * <0 - error
+ * 0 - use board->num_ports
+ * >0 - number of ports
*/
if (quirk->init) {
rc = quirk->init(dev);
@@ -3614,8 +3872,8 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
}
priv = kzalloc(sizeof(struct serial_private) +
- sizeof(unsigned int) * nr_ports,
- GFP_KERNEL);
+ sizeof(unsigned int) * nr_ports,
+ GFP_KERNEL);
if (!priv) {
priv = ERR_PTR(-ENOMEM);
goto err_deinit;
@@ -3714,7 +3972,7 @@ void pciserial_resume_ports(struct serial_private *priv)
EXPORT_SYMBOL_GPL(pciserial_resume_ports);
/*
- * Probe one serial board. Unfortunately, there is no rhyme nor reason
+ * Probe one serial board. Unfortunately, there is no rhyme nor reason
* to the arrangement of serial ports on a PCI card.
*/
static int
@@ -3760,7 +4018,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
board = &tmp;
/*
- * We matched one of our class entries. Try to
+ * We matched one of our class entries. Try to
* determine the parameters of this board.
*/
rc = serial_pci_guess_board(dev, &tmp);
@@ -3773,11 +4031,11 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
* then we no longer need this entry.
*/
memcpy(&tmp, &pci_boards[pbn_default],
- sizeof(struct pciserial_board));
+ sizeof(struct pciserial_board));
rc = serial_pci_guess_board(dev, &tmp);
if (rc == 0 && serial_pci_matches(board, &tmp))
moan_device("Redundant entry in serial pci_table.",
- dev);
+ dev);
}
priv = pciserial_init_ports(dev, board);
@@ -4015,7 +4273,7 @@ static const struct pci_device_id serial_pci_tbl[] = {
pbn_plx_romulus },
/*
* EndRun Technologies. PCI express device range.
- * EndRun PTP/1588 has 2 Native UARTs.
+ * EndRun PTP/1588 has 2 Native UARTs.
*/
{ PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -4098,7 +4356,7 @@ static const struct pci_device_id serial_pci_tbl[] = {
/*
* The below card is a little controversial since it is the
- * subject of a PCI vendor/device ID clash. (See
+ * subject of a PCI vendor/device ID clash. (See
* www.ussg.iu.edu/hypermail/linux/kernel/0303.1/0516.html).
* For now just used the hex ID 0x950a.
*/
@@ -4127,136 +4385,136 @@ static const struct pci_device_id serial_pci_tbl[] = {
/*
* Oxford Semiconductor Inc. Tornado PCI express device range.
*/
- { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_4_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_4_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_8_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_8_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
+ { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_oxsemi_1_4000000 },
/*
@@ -4308,7 +4566,7 @@ static const struct pci_device_id serial_pci_tbl[] = {
/*
* Titan Electronic cards
- * The 400L and 800L have a custom setup quirk.
+ * The 400L and 800L have a custom setup quirk.
*/
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -4644,19 +4902,19 @@ static const struct pci_device_id serial_pci_tbl[] = {
/*
* Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
*/
- { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951,
+ { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7951 },
- { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952,
+ { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954,
+ { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958,
+ { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7958 },
@@ -4786,7 +5044,7 @@ static const struct pci_device_id serial_pci_tbl[] = {
* IntaShield IS-400
*/
{ PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */
pbn_b2_4_115200 },
/*
* BrainBoxes UC-260
@@ -4802,10 +5060,10 @@ static const struct pci_device_id serial_pci_tbl[] = {
/*
* Perle PCI-RAS cards
*/
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS4,
0, 0, pbn_b2_4_921600 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS8,
0, 0, pbn_b2_8_921600 },
@@ -5003,6 +5261,33 @@ static const struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_ni8430_4 },
+ { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_2328,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_pxie_8 },
+ { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_23216,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_pxie_16 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4852,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_2 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4854,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_4 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4858,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_8 },
+ { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_4858,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_pxie_8 },
+ { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_48516,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_pxie_16 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4852,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_2 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4854,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8431_4 },
/*
* ADDI-DATA GmbH communication cards <info@addi-data.com>
@@ -5179,7 +5464,7 @@ static const struct pci_device_id serial_pci_tbl[] = {
0, 0, pbn_b0_bt_4_115200 },
/* Intel CE4100 */
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_ce4100_1_115200 },
/*
@@ -5314,8 +5599,8 @@ static struct pci_driver serial_pci_driver = {
.name = "serial",
.probe = pciserial_init_one,
.remove = pciserial_remove_one,
- .driver = {
- .pm = &pciserial_pm_ops,
+ .driver = {
+ .pm = &pciserial_pm_ops,
},
.id_table = serial_pci_tbl,
.err_handler = &serial8250_err_handler,
--
2.17.1
^ permalink raw reply related
* Re: [PATCH v3 7/7] Input: add IOC3 serio driver
From: Dmitry Torokhov @ 2019-07-01 8:19 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Ralf Baechle, Paul Burton, James Hogan, Lee Jones,
David S. Miller, Srinivas Kandagatla, Alessandro Zummo,
Alexandre Belloni, Greg Kroah-Hartman, Jiri Slaby, linux-mips,
linux-kernel, linux-input, netdev, linux-rtc, linux-serial
In-Reply-To: <20190613170636.6647-8-tbogendoerfer@suse.de>
Hi Thomas,
On Thu, Jun 13, 2019 at 07:06:33PM +0200, Thomas Bogendoerfer wrote:
> This patch adds a platform driver for supporting keyboard and mouse
> interface of SGI IOC3 chips.
>
> Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
> ---
> drivers/input/serio/Kconfig | 10 +++
> drivers/input/serio/Makefile | 1 +
> drivers/input/serio/ioc3kbd.c | 158 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 169 insertions(+)
> create mode 100644 drivers/input/serio/ioc3kbd.c
>
> diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
> index f3e18f8ef9ca..373a1646019e 100644
> --- a/drivers/input/serio/Kconfig
> +++ b/drivers/input/serio/Kconfig
> @@ -165,6 +165,16 @@ config SERIO_MACEPS2
> To compile this driver as a module, choose M here: the
> module will be called maceps2.
>
> +config SERIO_SGI_IOC3
> + tristate "SGI IOC3 PS/2 controller"
> + depends on SGI_MFD_IOC3
> + help
> + Say Y here if you have an SGI Onyx2, SGI Octane or IOC3 PCI card
> + and you want to attach and use a keyboard, mouse, or both.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called ioc3kbd.
> +
> config SERIO_LIBPS2
> tristate "PS/2 driver library"
> depends on SERIO_I8042 || SERIO_I8042=n
> diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
> index 67950a5ccb3f..6d97bad7b844 100644
> --- a/drivers/input/serio/Makefile
> +++ b/drivers/input/serio/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o
> obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o
> obj-$(CONFIG_SERIO_PS2MULT) += ps2mult.o
> obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o
> +obj-$(CONFIG_SERIO_SGI_IOC3) += ioc3kbd.o
> obj-$(CONFIG_SERIO_LIBPS2) += libps2.o
> obj-$(CONFIG_SERIO_RAW) += serio_raw.o
> obj-$(CONFIG_SERIO_AMS_DELTA) += ams_delta_serio.o
> diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c
> new file mode 100644
> index 000000000000..26fcf57465d6
> --- /dev/null
> +++ b/drivers/input/serio/ioc3kbd.c
> @@ -0,0 +1,158 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * SGI IOC3 PS/2 controller driver for linux
> + *
> + * Copyright (C) 2019 Thomas Bogendoerfer <tbogendoerfer@suse.de>
> + *
> + * Based on code Copyright (C) 2005 Stanislaw Skowronek <skylark@unaligned.org>
> + * Copyright (C) 2009 Johannes Dickgreber <tanzy@gmx.de>
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/serio.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#include <asm/sn/ioc3.h>
> +
> +struct ioc3kbd_data {
> + struct ioc3_serioregs __iomem *regs;
> + struct serio *kbd, *aux;
> +};
> +
> +static int ioc3kbd_write(struct serio *dev, u8 val)
> +{
> + struct ioc3kbd_data *d = dev->port_data;
> + unsigned long timeout = 0;
> + u32 mask;
> +
> + mask = (dev == d->aux) ? KM_CSR_M_WRT_PEND : KM_CSR_K_WRT_PEND;
> + while ((readl(&d->regs->km_csr) & mask) && (timeout < 1000)) {
> + udelay(100);
> + timeout++;
> + }
> +
> + if (timeout >= 1000)
> + return -1;
-ETIMEDOUT?
> +
> + writel(val, dev == d->aux ? &d->regs->m_wd : &d->regs->k_wd);
Nit: there are 2 spaces after ?, only one is needed.
> +
> + return 0;
> +}
> +
> +static irqreturn_t ioc3kbd_intr(int itq, void *dev_id)
> +{
> + struct ioc3kbd_data *d = dev_id;
> + u32 data_k, data_m;
> +
> + data_k = readl(&d->regs->k_rd);
> + data_m = readl(&d->regs->m_rd);
> +
> + if (data_k & KM_RD_VALID_0)
> + serio_interrupt(d->kbd,
> + (data_k >> KM_RD_DATA_0_SHIFT) & 0xff, 0);
This is weird formatting, you need one more tab here.
> + if (data_k & KM_RD_VALID_1)
> + serio_interrupt(d->kbd,
> + (data_k >> KM_RD_DATA_1_SHIFT) & 0xff, 0);
> + if (data_k & KM_RD_VALID_2)
> + serio_interrupt(d->kbd,
> + (data_k >> KM_RD_DATA_2_SHIFT) & 0xff, 0);
> + if (data_m & KM_RD_VALID_0)
> + serio_interrupt(d->aux,
> + (data_m >> KM_RD_DATA_0_SHIFT) & 0xff, 0);
> + if (data_m & KM_RD_VALID_1)
> + serio_interrupt(d->aux,
> + (data_m >> KM_RD_DATA_1_SHIFT) & 0xff, 0);
> + if (data_m & KM_RD_VALID_2)
> + serio_interrupt(d->aux,
> + (data_m >> KM_RD_DATA_2_SHIFT) & 0xff, 0);
> +
> + return 0;
> +}
> +
> +static int ioc3kbd_probe(struct platform_device *pdev)
> +{
> + struct ioc3_serioregs __iomem *regs;
> + struct device *dev = &pdev->dev;
> + struct ioc3kbd_data *d;
> + struct serio *sk, *sa;
> + struct resource *mem;
> + int irq, ret;
> +
> + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + regs = devm_ioremap_resource(&pdev->dev, mem);
We have a brand new helper: devm_platform_ioremap_resource()
> + if (IS_ERR(regs))
> + return PTR_ERR(regs);
> +
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0)
> + return -ENXIO;
> +
> + d = devm_kzalloc(&pdev->dev, sizeof(struct ioc3kbd_data), GFP_KERNEL);
I think we nor prefer deriving type from the pointer:
d = evm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
> + if (!d)
> + return -ENOMEM;
> +
> + ret = devm_request_irq(&pdev->dev, irq, ioc3kbd_intr, IRQF_SHARED,
> + "ioc3-kbd", d);
> + if (ret) {
> + dev_err(&pdev->dev, "could not request IRQ %d\n", irq);
> + return ret;
> + }
You need to make sure that interrupt will not fire while serio ports are
not yet allocated/registered. Is there a way to inhibit interrupt
generation on controller side?
> +
> + sk = kzalloc(sizeof(struct serio), GFP_KERNEL);
sk = kzalloc(sizeof(*sk), GFP_KERNEL);
> + if (!sk)
> + return -ENOMEM;
> +
> + sa = kzalloc(sizeof(struct serio), GFP_KERNEL);
sa = kzalloc(sizeof(*sa), GFP_KERNEL);
> + if (!sa) {
> + kfree(sk);
> + return -ENOMEM;
> + }
> +
> + sk->id.type = SERIO_8042;
> + sk->write = ioc3kbd_write;
> + snprintf(sk->name, sizeof(sk->name), "IOC3 keyboard %d", pdev->id);
> + snprintf(sk->phys, sizeof(sk->phys), "ioc3/serio%dkbd", pdev->id);
> + sk->port_data = d;
> + sk->dev.parent = &pdev->dev;
> +
> + sa->id.type = SERIO_8042;
> + sa->write = ioc3kbd_write;
> + snprintf(sa->name, sizeof(sa->name), "IOC3 auxiliary %d", pdev->id);
> + snprintf(sa->phys, sizeof(sa->phys), "ioc3/serio%daux", pdev->id);
> + sa->port_data = d;
> + sa->dev.parent = dev;
> +
> + d->regs = regs;
> + d->kbd = sk;
> + d->aux = sa;
> +
> + platform_set_drvdata(pdev, d);
> + serio_register_port(d->kbd);
> + serio_register_port(d->aux);
> + return 0;
> +}
> +
> +static int ioc3kbd_remove(struct platform_device *pdev)
> +{
> + struct ioc3kbd_data *d = platform_get_drvdata(pdev);
> +
> + serio_unregister_port(d->kbd);
> + serio_unregister_port(d->aux);
If you unregister ports while interrupt is registered/enabled you may
get a crash.
> + return 0;
> +}
> +
> +static struct platform_driver ioc3kbd_driver = {
> + .probe = ioc3kbd_probe,
> + .remove = ioc3kbd_remove,
> + .driver = {
> + .name = "ioc3-kbd",
> + },
> +};
> +module_platform_driver(ioc3kbd_driver);
> +
> +MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfer@suse.de>");
> +MODULE_DESCRIPTION("SGI IOC3 serio driver");
> +MODULE_LICENSE("GPL");
> --
> 2.13.7
>
--
Dmitry
^ permalink raw reply
* [PATCH 32/39] docs: serial: move it to the driver-api
From: Mauro Carvalho Chehab @ 2019-06-28 12:30 UTC (permalink / raw)
To: Linux Doc Mailing List
Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel,
Jonathan Corbet, Greg Kroah-Hartman, Jiri Slaby, Timur Tabi,
linuxppc-dev, linux-serial
In-Reply-To: <cover.1561724493.git.mchehab+samsung@kernel.org>
The contents of this directory is mostly driver-api stuff.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
Documentation/driver-api/index.rst | 1 +
Documentation/{ => driver-api}/serial/cyclades_z.rst | 0
Documentation/{ => driver-api}/serial/driver.rst | 2 +-
Documentation/{ => driver-api}/serial/index.rst | 2 +-
Documentation/{ => driver-api}/serial/moxa-smartio.rst | 0
Documentation/{ => driver-api}/serial/n_gsm.rst | 0
Documentation/{ => driver-api}/serial/rocket.rst | 0
Documentation/{ => driver-api}/serial/serial-iso7816.rst | 0
Documentation/{ => driver-api}/serial/serial-rs485.rst | 0
Documentation/{ => driver-api}/serial/tty.rst | 0
MAINTAINERS | 6 +++---
drivers/tty/Kconfig | 4 ++--
drivers/tty/serial/ucc_uart.c | 2 +-
include/linux/serial_core.h | 2 +-
14 files changed, 10 insertions(+), 9 deletions(-)
rename Documentation/{ => driver-api}/serial/cyclades_z.rst (100%)
rename Documentation/{ => driver-api}/serial/driver.rst (99%)
rename Documentation/{ => driver-api}/serial/index.rst (90%)
rename Documentation/{ => driver-api}/serial/moxa-smartio.rst (100%)
rename Documentation/{ => driver-api}/serial/n_gsm.rst (100%)
rename Documentation/{ => driver-api}/serial/rocket.rst (100%)
rename Documentation/{ => driver-api}/serial/serial-iso7816.rst (100%)
rename Documentation/{ => driver-api}/serial/serial-rs485.rst (100%)
rename Documentation/{ => driver-api}/serial/tty.rst (100%)
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index f44a3140f95d..d6f532c8d824 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -88,6 +88,7 @@ available subsections can be seen below.
pti_intel_mid
pwm
rfkill
+ serial/index
sgi-ioc4
sm501
smsc_ece1099
diff --git a/Documentation/serial/cyclades_z.rst b/Documentation/driver-api/serial/cyclades_z.rst
similarity index 100%
rename from Documentation/serial/cyclades_z.rst
rename to Documentation/driver-api/serial/cyclades_z.rst
diff --git a/Documentation/serial/driver.rst b/Documentation/driver-api/serial/driver.rst
similarity index 99%
rename from Documentation/serial/driver.rst
rename to Documentation/driver-api/serial/driver.rst
index 4537119bf624..31bd4e16fb1f 100644
--- a/Documentation/serial/driver.rst
+++ b/Documentation/driver-api/serial/driver.rst
@@ -311,7 +311,7 @@ hardware.
This call must not sleep
set_ldisc(port,termios)
- Notifier for discipline change. See Documentation/serial/tty.rst.
+ Notifier for discipline change. See Documentation/driver-api/serial/tty.rst.
Locking: caller holds tty_port->mutex
diff --git a/Documentation/serial/index.rst b/Documentation/driver-api/serial/index.rst
similarity index 90%
rename from Documentation/serial/index.rst
rename to Documentation/driver-api/serial/index.rst
index d0ba22ea23bf..33ad10d05b26 100644
--- a/Documentation/serial/index.rst
+++ b/Documentation/driver-api/serial/index.rst
@@ -1,4 +1,4 @@
-:orphan:
+.. SPDX-License-Identifier: GPL-2.0
==========================
Support for Serial devices
diff --git a/Documentation/serial/moxa-smartio.rst b/Documentation/driver-api/serial/moxa-smartio.rst
similarity index 100%
rename from Documentation/serial/moxa-smartio.rst
rename to Documentation/driver-api/serial/moxa-smartio.rst
diff --git a/Documentation/serial/n_gsm.rst b/Documentation/driver-api/serial/n_gsm.rst
similarity index 100%
rename from Documentation/serial/n_gsm.rst
rename to Documentation/driver-api/serial/n_gsm.rst
diff --git a/Documentation/serial/rocket.rst b/Documentation/driver-api/serial/rocket.rst
similarity index 100%
rename from Documentation/serial/rocket.rst
rename to Documentation/driver-api/serial/rocket.rst
diff --git a/Documentation/serial/serial-iso7816.rst b/Documentation/driver-api/serial/serial-iso7816.rst
similarity index 100%
rename from Documentation/serial/serial-iso7816.rst
rename to Documentation/driver-api/serial/serial-iso7816.rst
diff --git a/Documentation/serial/serial-rs485.rst b/Documentation/driver-api/serial/serial-rs485.rst
similarity index 100%
rename from Documentation/serial/serial-rs485.rst
rename to Documentation/driver-api/serial/serial-rs485.rst
diff --git a/Documentation/serial/tty.rst b/Documentation/driver-api/serial/tty.rst
similarity index 100%
rename from Documentation/serial/tty.rst
rename to Documentation/driver-api/serial/tty.rst
diff --git a/MAINTAINERS b/MAINTAINERS
index 055db86fdd77..856db8015edd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10723,7 +10723,7 @@ F: include/uapi/linux/meye.h
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
M: Jiri Slaby <jirislaby@gmail.com>
S: Maintained
-F: Documentation/serial/moxa-smartio.rst
+F: Documentation/driver-api/serial/moxa-smartio.rst
F: drivers/tty/mxser.*
MR800 AVERMEDIA USB FM RADIO DRIVER
@@ -13637,7 +13637,7 @@ ROCKETPORT DRIVER
P: Comtrol Corp.
W: http://www.comtrol.com
S: Maintained
-F: Documentation/serial/rocket.rst
+F: Documentation/driver-api/serial/rocket.rst
F: drivers/tty/rocket*
ROCKETPORT EXPRESS/INFINITY DRIVER
@@ -16170,7 +16170,7 @@ M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
M: Jiri Slaby <jslaby@suse.com>
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
-F: Documentation/serial/
+F: Documentation/driver-api/serial/
F: drivers/tty/
F: drivers/tty/serial/serial_core.c
F: include/linux/serial_core.h
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index ee51b9514225..c7623f99ac0f 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -175,7 +175,7 @@ config ROCKETPORT
This driver supports Comtrol RocketPort and RocketModem PCI boards.
These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
modems. For information about the RocketPort/RocketModem boards
- and this driver read <file:Documentation/serial/rocket.rst>.
+ and this driver read <file:Documentation/driver-api/serial/rocket.rst>.
To compile this driver as a module, choose M here: the
module will be called rocket.
@@ -193,7 +193,7 @@ config CYCLADES
your Linux box, for instance in order to become a dial-in server.
For information about the Cyclades-Z card, read
- <file:Documentation/serial/cyclades_z.rst>.
+ <file:Documentation/driver-api/serial/cyclades_z.rst>.
To compile this driver as a module, choose M here: the
module will be called cyclades.
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 6e3c66ab0e62..a0555ae2b1ef 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -1081,7 +1081,7 @@ static int qe_uart_verify_port(struct uart_port *port,
}
/* UART operations
*
- * Details on these functions can be found in Documentation/serial/driver.rst
+ * Details on these functions can be found in Documentation/driver-api/serial/driver.rst
*/
static const struct uart_ops qe_uart_pops = {
.tx_empty = qe_uart_tx_empty,
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 05b179015d6c..2b78cc734719 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -32,7 +32,7 @@ struct device;
/*
* This structure describes all the operations that can be done on the
- * physical hardware. See Documentation/serial/driver.rst for details.
+ * physical hardware. See Documentation/driver-api/serial/driver.rst for details.
*/
struct uart_ops {
unsigned int (*tx_empty)(struct uart_port *);
--
2.21.0
^ permalink raw reply related
* Re: [patch 2/5] genirq: Add optional hardware synchronization for shutdown
From: Thomas Gleixner @ 2019-06-28 9:41 UTC (permalink / raw)
To: Marc Zyngier
Cc: LKML, x86, Robert Hodaszi, Vadim Pasternak, Ido Schimmel,
Greg Kroah-Hartman, linux-serial
In-Reply-To: <dbcd11d3-c967-a0a0-02a6-86d162f93a56@arm.com>
Marc,
On Fri, 28 Jun 2019, Marc Zyngier wrote:
> On 25/06/2019 12:13, Thomas Gleixner wrote:
> >
> > int (*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
> > int (*irq_retrigger)(struct irq_data *data);
> > + int (*irq_inflight)(struct irq_data *data);
>
> I wonder how different this irq_inflight() is from the irq_get_irqchip_state()
> that can already report a number of states from the HW.
>
> It is also unclear to me how "in flight" maps to the internal state of
> the interrupt controller: Is it pending? Acked? If the interrupt has been
> masked already, pending should be harmless (the interrupt won't fire anymore).
> But seeing it in the acked would probably mean that it is on its way to being
> handled, with a potential splat.
in flight means that the interrupt chip (in the offending case the IO-APIC)
has that interrupt raised internally _AND_ already propagated to the
destination CPU (in this case the local APIC of the destination). The CPU
has accepted the interrupt and now the chip is in a state where it waits
for it to be acknowledged. If we proceed in that state then the destination
CPU will eventually handle it _after_ all the resources are freed. But that
means that the in flight/wait for acknowledge state becomes stale because
the handling CPU does not find the connection to that chip anymore.
> > + /*
> > + * If requested and supported, check at the chip whether it
> > + * is in flight at the hardware level:
> > + */
> > + if (!inprogress && sync_chip && chip && chip->irq_inflight)
> > + inprogress = chip->irq_inflight(irqd);
>
> To expand on what I was trying to exptree above, I wonder if that would
> be similar to in effect to:
>
> if (!inprogress && sync_chip && chip && chip->irq_get_irqchip_state)
> chip->irq_get_irqchip_state(irqd, IRQCHIP_STATE_ACTIVE, &inprogress);
Ah, indeed that could be mapped to it.
I'm happy to get rid of the extra callback. Now the question is whether
this would would give an headache for any of the chips which already
implement that callback and whether it needs to become conditional on the
trigger type at the core level. For the IO-APIC this state is only defined
for level type which makes sense as edge is fire and forget.
Thanks,
tglx
^ permalink raw reply
* Re: [patch 1/5] genirq: Delay deactivation in free_irq()
From: Thomas Gleixner @ 2019-06-28 9:28 UTC (permalink / raw)
To: Marc Zyngier
Cc: LKML, x86, Robert Hodaszi, Vadim Pasternak, Ido Schimmel,
Greg Kroah-Hartman, linux-serial
In-Reply-To: <0bb6aae3-744b-7752-04ec-9a0e68fb86e6@arm.com>
Marc,
On Fri, 28 Jun 2019, Marc Zyngier wrote:
> > --- a/kernel/irq/autoprobe.c
> > +++ b/kernel/irq/autoprobe.c
> > @@ -1699,6 +1700,7 @@ static struct irqaction *__free_irq(stru
> > /* If this was the last handler, shut down the IRQ line: */
> > if (!desc->action) {
> > irq_settings_clr_disable_unlazy(desc);
> > + /* Only shutdown. Deactivate after synchronize_irq() */
>
> synchronize_hardirq()
Correct.
> >
> > irq_release_resources(desc);
> The patch makes complete sense, so this comment is only a nit, feel free
> to ignore me: I find it a bit odd that irq_shutdown() doesn't do the
> full thing anymore, given that it is the "canonical" function, and that
> __free_irq is the only one that has special needs. Suggestion below.
We have pretty much the same thing with startup, so I made it symmetric.
> Irrespective of which version you prefer:
>
> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Thanks for looking into this!
tglx
^ permalink raw reply
* Re: [patch 2/5] genirq: Add optional hardware synchronization for shutdown
From: Marc Zyngier @ 2019-06-28 7:59 UTC (permalink / raw)
To: Thomas Gleixner, LKML
Cc: x86, Robert Hodaszi, Vadim Pasternak, Ido Schimmel,
Greg Kroah-Hartman, linux-serial
In-Reply-To: <20190625112405.666964552@linutronix.de>
On 25/06/2019 12:13, Thomas Gleixner wrote:
> free_irq() ensures that no hardware interrupt handler is executing on a
> different CPU before actually releasing resources and deactivating the
> interrupt completely in a domain hierarchy.
>
> But that does not catch the case where the interrupt is on flight at the
> hardware level but not yet serviced by the target CPU. That creates an
> interesing race condition:
>
> CPU 0 CPU 1 IRQ CHIP
>
> interrupt is raised
> sent to CPU1
> Unable to handle
> immediately
> (interrupts off,
> deep idle delay)
> mask()
> ...
> free()
> shutdown()
> synchronize_irq()
> release_resources()
> do_IRQ()
> -> resources are not available
>
> That might be harmless and just trigger a spurious interrupt warning, but
> some interrupt chips might get into a wedged state.
>
> Provide infrastructure for interrupt chips to provide an optional
> irq_inflight() callback and use it for the synchronization in free_irq().
>
> synchronize_[hard]irq() are not using this mechanism as it might actually
> deadlock unter certain conditions.
>
> Fixes: 464d12309e1b ("x86/vector: Switch IOAPIC to global reservation mode")
> Reported-by: Robert Hodaszi <Robert.Hodaszi@digi.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
> include/linux/irq.h | 2 ++
> kernel/irq/manage.c | 29 ++++++++++++++++++++++++-----
> 2 files changed, 26 insertions(+), 5 deletions(-)
>
> --- a/include/linux/irq.h
> +++ b/include/linux/irq.h
> @@ -418,6 +418,7 @@ static inline irq_hw_number_t irqd_to_hw
> * required. This is used for CPU hotplug where the
> * target CPU is not yet set in the cpu_online_mask.
> * @irq_retrigger: resend an IRQ to the CPU
> + * @irq_inflight: chip level detection of interrupts in flight (optional)
> * @irq_set_type: set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
> * @irq_set_wake: enable/disable power-management wake-on of an IRQ
> * @irq_bus_lock: function to lock access to slow bus (i2c) chips
> @@ -462,6 +463,7 @@ struct irq_chip {
>
> int (*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
> int (*irq_retrigger)(struct irq_data *data);
> + int (*irq_inflight)(struct irq_data *data);
I wonder how different this irq_inflight() is from the irq_get_irqchip_state()
that can already report a number of states from the HW.
It is also unclear to me how "in flight" maps to the internal state of
the interrupt controller: Is it pending? Acked? If the interrupt has been
masked already, pending should be harmless (the interrupt won't fire anymore).
But seeing it in the acked would probably mean that it is on its way to being
handled, with a potential splat.
> int (*irq_set_type)(struct irq_data *data, unsigned int flow_type);
> int (*irq_set_wake)(struct irq_data *data, unsigned int on);
>
> --- a/kernel/irq/manage.c
> +++ b/kernel/irq/manage.c
> @@ -35,8 +35,10 @@ static int __init setup_forced_irqthread
> early_param("threadirqs", setup_forced_irqthreads);
> #endif
>
> -static void __synchronize_hardirq(struct irq_desc *desc)
> +static void __synchronize_hardirq(struct irq_desc *desc, bool sync_chip)
> {
> + struct irq_data *irqd = irq_desc_get_irq_data(desc);
> + struct irq_chip *chip = irq_data_get_irq_chip(irqd);
> bool inprogress;
>
> do {
> @@ -52,6 +54,13 @@ static void __synchronize_hardirq(struct
> /* Ok, that indicated we're done: double-check carefully. */
> raw_spin_lock_irqsave(&desc->lock, flags);
> inprogress = irqd_irq_inprogress(&desc->irq_data);
> +
> + /*
> + * If requested and supported, check at the chip whether it
> + * is in flight at the hardware level:
> + */
> + if (!inprogress && sync_chip && chip && chip->irq_inflight)
> + inprogress = chip->irq_inflight(irqd);
To expand on what I was trying to exptree above, I wonder if that would
be similar to in effect to:
if (!inprogress && sync_chip && chip && chip->irq_get_irqchip_state)
chip->irq_get_irqchip_state(irqd, IRQCHIP_STATE_ACTIVE, &inprogress);
> raw_spin_unlock_irqrestore(&desc->lock, flags);
>
> /* Oops, that failed? */
> @@ -74,13 +83,16 @@ static void __synchronize_hardirq(struct
> * Returns: false if a threaded handler is active.
> *
> * This function may be called - with care - from IRQ context.
> + *
> + * It does not check whether there is an interrupt on flight at the
> + * hardware level, but not serviced yet, as this might deadlock.
> */
> bool synchronize_hardirq(unsigned int irq)
> {
> struct irq_desc *desc = irq_to_desc(irq);
>
> if (desc) {
> - __synchronize_hardirq(desc);
> + __synchronize_hardirq(desc, false);
> return !atomic_read(&desc->threads_active);
> }
>
> @@ -97,13 +109,16 @@ EXPORT_SYMBOL(synchronize_hardirq);
> * holding a resource the IRQ handler may need you will deadlock.
> *
> * This function may be called - with care - from IRQ context.
> + *
> + * It does not check whether there is an interrupt on flight at the
> + * hardware level, but not serviced yet, as this might deadlock.
> */
> void synchronize_irq(unsigned int irq)
> {
> struct irq_desc *desc = irq_to_desc(irq);
>
> if (desc) {
> - __synchronize_hardirq(desc);
> + __synchronize_hardirq(desc, false);
> /*
> * We made sure that no hardirq handler is
> * running. Now verify that no threaded handlers are
> @@ -1729,8 +1744,12 @@ static struct irqaction *__free_irq(stru
>
> unregister_handler_proc(irq, action);
>
> - /* Make sure it's not being used on another CPU: */
> - synchronize_hardirq(irq);
> + /*
> + * Make sure it's not being used on another CPU and if the chip
> + * supports it also make sure that there is no (not yet serviced)
> + * interrupt on flight at the hardware level.
> + */
> + __synchronize_hardirq(desc, true);
>
> #ifdef CONFIG_DEBUG_SHIRQ
> /*
>
>
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* Re: [patch 1/5] genirq: Delay deactivation in free_irq()
From: Marc Zyngier @ 2019-06-28 7:42 UTC (permalink / raw)
To: Thomas Gleixner, LKML
Cc: x86, Robert Hodaszi, Vadim Pasternak, Ido Schimmel,
Greg Kroah-Hartman, linux-serial
In-Reply-To: <20190625112405.573914765@linutronix.de>
Hi Thomas,
On 25/06/2019 12:13, Thomas Gleixner wrote:
> When interrupts are shutdown, they are immediately deactivated in the
> irqdomain hierarchy. While this looks obviously correct there is a subtle
> issue:
>
> There might be an interrupt in flight when free_irq() is invoking the
> shutdown. This is properly handled at the irq descriptor / primary handler
> level, but the deactivation might completely disable resources which are
> required to acknowledge the interrupt.
>
> Split the shutdown code and deactivate the interrupt after synchronization
> in free_irq(). Fixup all other usage sites where this is not an issue to
> invoke the combined shutdown_and_deactivate() function instead.
>
> This still might be an issue if the interrupt in flight servicing is
> delayed on a remote CPU beyond the invocation of synchronize_irq(), but
> that cannot be handled at that level and needs to be handled in the
> synchronize_irq() context.
>
> Fixes: f8264e34965a ("irqdomain: Introduce new interfaces to support hierarchy irqdomains")
> Reported-by: Robert Hodaszi <Robert.Hodaszi@digi.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
> kernel/irq/autoprobe.c | 6 +++---
> kernel/irq/chip.c | 6 ++++++
> kernel/irq/cpuhotplug.c | 2 +-
> kernel/irq/internals.h | 1 +
> kernel/irq/manage.c | 12 +++++++++++-
> 5 files changed, 22 insertions(+), 5 deletions(-)
>
> --- a/kernel/irq/autoprobe.c
> +++ b/kernel/irq/autoprobe.c
> @@ -90,7 +90,7 @@ unsigned long probe_irq_on(void)
> /* It triggered already - consider it spurious. */
> if (!(desc->istate & IRQS_WAITING)) {
> desc->istate &= ~IRQS_AUTODETECT;
> - irq_shutdown(desc);
> + irq_shutdown_and_deactivate(desc);
> } else
> if (i < 32)
> mask |= 1 << i;
> @@ -127,7 +127,7 @@ unsigned int probe_irq_mask(unsigned lon
> mask |= 1 << i;
>
> desc->istate &= ~IRQS_AUTODETECT;
> - irq_shutdown(desc);
> + irq_shutdown_and_deactivate(desc);
> }
> raw_spin_unlock_irq(&desc->lock);
> }
> @@ -169,7 +169,7 @@ int probe_irq_off(unsigned long val)
> nr_of_irqs++;
> }
> desc->istate &= ~IRQS_AUTODETECT;
> - irq_shutdown(desc);
> + irq_shutdown_and_deactivate(desc);
> }
> raw_spin_unlock_irq(&desc->lock);
> }
> --- a/kernel/irq/chip.c
> +++ b/kernel/irq/chip.c
> @@ -314,6 +314,12 @@ void irq_shutdown(struct irq_desc *desc)
> }
> irq_state_clr_started(desc);
> }
> +}
> +
> +
> +void irq_shutdown_and_deactivate(struct irq_desc *desc)
> +{
> + irq_shutdown(desc);
> /*
> * This must be called even if the interrupt was never started up,
> * because the activation can happen before the interrupt is
> --- a/kernel/irq/cpuhotplug.c
> +++ b/kernel/irq/cpuhotplug.c
> @@ -116,7 +116,7 @@ static bool migrate_one_irq(struct irq_d
> */
> if (irqd_affinity_is_managed(d)) {
> irqd_set_managed_shutdown(d);
> - irq_shutdown(desc);
> + irq_shutdown_and_deactivate(desc);
> return false;
> }
> affinity = cpu_online_mask;
> --- a/kernel/irq/internals.h
> +++ b/kernel/irq/internals.h
> @@ -82,6 +82,7 @@ extern int irq_activate_and_startup(stru
> extern int irq_startup(struct irq_desc *desc, bool resend, bool force);
>
> extern void irq_shutdown(struct irq_desc *desc);
> +extern void irq_shutdown_and_deactivate(struct irq_desc *desc);
> extern void irq_enable(struct irq_desc *desc);
> extern void irq_disable(struct irq_desc *desc);
> extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu);
> --- a/kernel/irq/manage.c
> +++ b/kernel/irq/manage.c
> @@ -13,6 +13,7 @@
> #include <linux/module.h>
> #include <linux/random.h>
> #include <linux/interrupt.h>
> +#include <linux/irqdomain.h>
> #include <linux/slab.h>
> #include <linux/sched.h>
> #include <linux/sched/rt.h>
> @@ -1699,6 +1700,7 @@ static struct irqaction *__free_irq(stru
> /* If this was the last handler, shut down the IRQ line: */
> if (!desc->action) {
> irq_settings_clr_disable_unlazy(desc);
> + /* Only shutdown. Deactivate after synchronize_irq() */
synchronize_hardirq()
> irq_shutdown(desc);
> }
>
> @@ -1768,6 +1770,14 @@ static struct irqaction *__free_irq(stru
> * require it to deallocate resources over the slow bus.
> */
> chip_bus_lock(desc);
> + /*
> + * There is no interrupt on the fly anymore. Deactivate it
> + * completely.
> + */
> + raw_spin_lock_irqsave(&desc->lock, flags);
> + irq_domain_deactivate_irq(&desc->irq_data);
> + raw_spin_unlock_irqrestore(&desc->lock, flags);
> +
> irq_release_resources(desc);
> chip_bus_sync_unlock(desc);
> irq_remove_timings(desc);
> @@ -1855,7 +1865,7 @@ static const void *__cleanup_nmi(unsigne
> }
>
> irq_settings_clr_disable_unlazy(desc);
> - irq_shutdown(desc);
> + irq_shutdown_and_deactivate(desc);
>
> irq_release_resources(desc);
The patch makes complete sense, so this comment is only a nit, feel free
to ignore me: I find it a bit odd that irq_shutdown() doesn't do the
full thing anymore, given that it is the "canonical" function, and that
__free_irq is the only one that has special needs. Suggestion below.
Irrespective of which version you prefer:
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
M.
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 29d6c7d070b4..aeab853fcc10 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -301,7 +301,7 @@ int irq_activate_and_startup(struct irq_desc *desc, bool resend)
static void __irq_disable(struct irq_desc *desc, bool mask);
-void irq_shutdown(struct irq_desc *desc)
+void __irq_shutdown(struct irq_desc *desc)
{
if (irqd_is_started(&desc->irq_data)) {
desc->depth = 1;
@@ -314,6 +314,11 @@ void irq_shutdown(struct irq_desc *desc)
}
irq_state_clr_started(desc);
}
+}
+
+void irq_shutdown(struct irq_desc *desc)
+{
+ __irq_shutdown(desc);
/*
* This must be called even if the interrupt was never started up,
* because the activation can happen before the interrupt is
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 70c3053bc1f6..107f7d342e3d 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -81,6 +81,7 @@ extern int irq_activate(struct irq_desc *desc);
extern int irq_activate_and_startup(struct irq_desc *desc, bool resend);
extern int irq_startup(struct irq_desc *desc, bool resend, bool force);
+extern void __irq_shutdown(struct irq_desc *desc);
extern void irq_shutdown(struct irq_desc *desc);
extern void irq_enable(struct irq_desc *desc);
extern void irq_disable(struct irq_desc *desc);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 78f3ddeb7fe4..f19e3589989e 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/random.h>
#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/sched/rt.h>
@@ -1699,7 +1700,8 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id)
/* If this was the last handler, shut down the IRQ line: */
if (!desc->action) {
irq_settings_clr_disable_unlazy(desc);
- irq_shutdown(desc);
+ /* Only shutdown. Deactivate after synchronize_hardirq() */
+ __irq_shutdown(desc);
}
#ifdef CONFIG_SMP
@@ -1768,6 +1770,14 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id)
* require it to deallocate resources over the slow bus.
*/
chip_bus_lock(desc);
+ /*
+ * There is no interrupt on the fly anymore. Deactivate it
+ * completely.
+ */
+ raw_spin_lock_irqsave(&desc->lock, flags);
+ irq_domain_deactivate_irq(&desc->irq_data);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
+
irq_release_resources(desc);
chip_bus_sync_unlock(desc);
irq_remove_timings(desc);
--
Jazz is not dead. It just smells funny...
^ permalink raw reply related
* [PATCH v2 21/27] tty: remove unneeded memset
From: Fuqian Huang @ 2019-06-28 2:50 UTC (permalink / raw)
Cc: Fuqian Huang, Greg Kroah-Hartman, Jiri Slaby, linux-serial,
linux-kernel
pci_alloc_consistent calls dma_alloc_coherent directly.
In commit af7ddd8a627c
("Merge tag 'dma-mapping-4.21' of git://git.infradead.org/users/hch/dma-mapping"),
dma_alloc_coherent has already zeroed the memory.
So memset is not needed.
Signed-off-by: Fuqian Huang <huangfq.daxian@gmail.com>
---
drivers/tty/serial/icom.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index ad374f7c476d..624f3d541c68 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -207,8 +207,6 @@ static int get_port_memory(struct icom_port *icom_port)
return -ENOMEM;
}
- memset(icom_port->statStg, 0, 4096);
-
/* FODs: Frame Out Descriptor Queue, this is a FIFO queue that
indicates that frames are to be transmitted
*/
--
2.11.0
^ permalink raw reply related
* [PATCH 47/87] tty: serial: remove memset after pci_alloc_consistent in icom.c
From: Fuqian Huang @ 2019-06-27 17:41 UTC (permalink / raw)
Cc: Fuqian Huang, Greg Kroah-Hartman, Jiri Slaby, linux-serial,
linux-kernel
pci_alloc_consistent calls dma_alloc_coherent directly.
In commit af7ddd8a627c
("Merge tag 'dma-mapping-4.21' of git://git.infradead.org/users/hch/dma-mapping"),
dma_alloc_coherent has already zeroed the memory.
So memset is not needed.
Signed-off-by: Fuqian Huang <huangfq.daxian@gmail.com>
---
drivers/tty/serial/icom.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index ad374f7c476d..624f3d541c68 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -207,8 +207,6 @@ static int get_port_memory(struct icom_port *icom_port)
return -ENOMEM;
}
- memset(icom_port->statStg, 0, 4096);
-
/* FODs: Frame Out Descriptor Queue, this is a FIFO queue that
indicates that frames are to be transmitted
*/
--
2.11.0
^ permalink raw reply related
* Re: [PATCH 1/2] serial: imx: remove duplicate handling of CTS change
From: Sascha Hauer @ 2019-06-27 7:59 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Pengutronix Kernel Team, Sergey Organov, linux-arm-kernel,
linux-serial, NXP Linux Team
In-Reply-To: <20190627061607.4ehhr6jj6vkfjorl@pengutronix.de>
On Thu, Jun 27, 2019 at 08:16:07AM +0200, Uwe Kleine-König wrote:
> On Wed, Jun 26, 2019 at 12:15:56PM +0200, Sascha Hauer wrote:
> > We have an interrupt for the CTS input (RTS in FSL speech). Its handler
> > calls uart_handle_cts_change(), so we shouldn't do this in
> > imx_uart_mctrl_check() again.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> > drivers/tty/serial/imx.c | 6 ------
> > 1 file changed, 6 deletions(-)
> >
> > diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> > index a5e80a028e83..0419a084c0ed 100644
> > --- a/drivers/tty/serial/imx.c
> > +++ b/drivers/tty/serial/imx.c
> > @@ -805,12 +805,8 @@ static void imx_uart_clear_rx_errors(struct imx_port *sport);
> > static unsigned int imx_uart_get_hwmctrl(struct imx_port *sport)
> > {
> > unsigned int tmp = TIOCM_DSR;
> > - unsigned usr1 = imx_uart_readl(sport, USR1);
> > unsigned usr2 = imx_uart_readl(sport, USR2);
> >
> > - if (usr1 & USR1_RTSS)
> > - tmp |= TIOCM_CTS;
> > -
> > /* in DCE mode DCDIN is always 0 */
> > if (!(usr2 & USR2_DCDIN))
> > tmp |= TIOCM_CAR;
>
> Is this hunk supposed to be included in this patch? I think it's wrong.
The rationale was that when we do not evaluate the TIOCM_CTS anymore in
the return value of imx_uart_get_hwmctrl() then there's no point in
setting it in the first place. However, imx_uart_get_hwmctrl() also has
another user which needs the flag, so right, this hunk shouldn't be
here.
>
> > @@ -843,8 +839,6 @@ static void imx_uart_mctrl_check(struct imx_port *sport)
> > sport->port.icount.dsr++;
> > if (changed & TIOCM_CAR)
> > uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
> > - if (changed & TIOCM_CTS)
> > - uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
>
> This doesn't hurt, does it?
With this patch the number of CTS changes is correctly counted, I have
verified this with a logic analyzer. Without it port->icount.cts has 978
changes when it should be only 968 changes.
> Also imx_uart_mctrl_check is called from
> imx_uart_timeout which is supposed to catch missed interrupts and in
> this case uart_handle_cts_change() must be called.
Beginning with 2/2 uart_handle_cts_change() is needed for nothing else
but statistic counting. There won't be any timeout due to missed
interrupts as the hardware handles CTS itself.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* Re: [PATCH v2 7/7] serial: imx: get rid of imx_uart_rts_auto()
From: Sergey Organov @ 2019-06-27 7:58 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Pengutronix Kernel Team, Sascha Hauer, linux-arm-kernel,
linux-serial, NXP Linux Team
In-Reply-To: <20190627060838.ls5ghzngkoiczqex@pengutronix.de>
Uwe Kleine-König <u.kleine-koenig@pengutronix.de> writes:
> On Wed, Jun 26, 2019 at 05:11:33PM +0300, Sergey Organov wrote:
>> Called in only one place, for RS232, it only obscures things, as it
>> doesn't go well with 2 similar named functions,
>> imx_uart_rts_inactive() and imx_uart_rts_active(), that both are
>> RS485-specific.
>>
>> Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
>> Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
>> Signed-off-by: Sergey Organov <sorganov@gmail.com>
>> ---
>> drivers/tty/serial/imx.c | 13 ++++---------
>> 1 file changed, 4 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
>> index 171347d..a5e80a0 100644
>> --- a/drivers/tty/serial/imx.c
>> +++ b/drivers/tty/serial/imx.c
>> @@ -402,13 +402,6 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
>> mctrl_gpio_set(sport->gpios, sport->port.mctrl);
>> }
>>
>> -/* called with port.lock taken and irqs caller dependent */
>> -static void imx_uart_rts_auto(struct imx_port *sport, u32 *ucr2)
>> -{
>> - if (*ucr2 & UCR2_CTS)
>> - *ucr2 |= UCR2_CTSC;
>> -}
>> -
>> /* called with port.lock taken and irqs off */
>> static void imx_uart_start_rx(struct uart_port *port)
>> {
>> @@ -1598,8 +1591,10 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
>> else
>> imx_uart_rts_inactive(sport, &ucr2);
>>
>> - } else if (termios->c_cflag & CRTSCTS)
>> - imx_uart_rts_auto(sport, &ucr2);
>> + } else if (termios->c_cflag & CRTSCTS) {
>> + if (ucr2 & UCR2_CTS)
>> + ucr2 |= UCR2_CTSC;
>> + }
>
> At least before it was (somewhat) clear that this is about RTS and it
> is about something automatic. So I don't like the patch.
Maybe I just need to put a comment here to clarify?
Let me try to convince you removal is a good thing.
Let's try to mentally revert the patch. If we already have
} else if (termios->c_cflag & CRTSCTS) {
if (ucr2 & UCR2_CTS)
ucr2 |= UCR2_CTSC;
}
I see no reason to make 2 lines inside if() a function.
First, it's already obvious it's about something automatic, due to if()
condition itself.
Second, the fact that it's about RTS is as [non-]obvious as in any other
place in the driver, taking into account that iMX calls "RTS" "CTS" and
vice versa.
Finally, should we still argue adding a function would be useful, we'd
need to also add, for consistency,
static void imx_uart_rts_manual(struct imx_port *sport, u32 *ucr2);
(as existing rts_on() and rts_off() do not serve the purpose),
as well as CTS counterparts:
static void imx_uart_cts_auto(struct imx_port *sport, u32 *ucr2);
static void imx_uart_cts_manual(struct imx_port *sport, u32 *ucr2);
and patch the code rather heavily, for no obvious gain.
Overall, I believe adding the function would only obscure things.
OTOH, existence of that function forced me to examine the whole source
just to figure that unlike other 2 similar named, it serves entirely
different logical purpose (i.e., it's _not_ 3-d alternative for those
2), and is not used anywhere else.
Look: when we have rts_auto(), rts_off(), and rts_on(), it's logical to
expect it's one of them that will be called when top-level asks for
automatic RTS/CTS, manual RTS off, and manual RTS on, respectively,
isn't it? But it is not the case at all! Still rts_auto() doesn't fit to
the overall picture.
Thanks!
-- Sergey
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 6/7] serial: imx: set_mctrl(): correctly restore autoRTS state
From: Sergey Organov @ 2019-06-27 7:01 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Pengutronix Kernel Team, Sascha Hauer, linux-arm-kernel,
linux-serial, NXP Linux Team
In-Reply-To: <20190627060537.brmgsmoh3usr4vo6@pengutronix.de>
Uwe Kleine-König <u.kleine-koenig@pengutronix.de> writes:
> On Wed, Jun 26, 2019 at 05:11:32PM +0300, Sergey Organov wrote:
>> imx_uart_set_mctrl() happened to set UCR2_CTSC bit whenever TIOCM_RTS
>> was set, no matter if RTS/CTS handshake is enabled or not. Now fixed by
>> turning handshake on only when CRTSCTS bit for the port is set.
>>
>> Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
>> Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
>> Signed-off-by: Sergey Organov <sorganov@gmail.com>
>> ---
>> drivers/tty/serial/imx.c | 13 +++++++++++--
>> 1 file changed, 11 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
>> index 4867f80..171347d 100644
>> --- a/drivers/tty/serial/imx.c
>> +++ b/drivers/tty/serial/imx.c
>> @@ -970,10 +970,19 @@ static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
>> if (!(port->rs485.flags & SER_RS485_ENABLED)) {
>> u32 ucr2;
>>
>> + /*
>> + * Turn off autoRTS (UCR2_CTSC) if RTS is lowered and restore
>> + * autoRTS setting if RTS is raised. Inverted UCR2_IRTS is set
>> + * if and only if CRTSCTS bit is set for the port, so we use it
>> + * to get the state to restore to.
>> + */
>
> The comment is quite complicated. I like the comments of Sascha's patch
> that addressed the same issue better.
This one is simply modeled after similar comments in other drivers,
then adding the specifics.
> Are you using UCR2_IRTS as an indicator if CRTSCTS is set? If it's that
> what you intend to express in the second sentence that is hard to grasp.
> Something like:
>
> UCR2_IRTS is unset iff the port is configured for CRTSCTS
Yeah, exactly. Fine, I'll change this, thanks!
>
> Also as the value of the CTS bit doesn't matter if CTSC is set, the
> order of the checks could be swapped to result in easier code (IMHO at
> least) that doesn't need a nested if.
>
> Something like:
>
> ucr2 = imx_uart_readl(sport, UCR2);
> ucr2 &= ~(UCR2_CTS | UCR2_CTSC);
>
> /* UCR2_IRTS is unset iff the port is configured for CRTSCTS */
> crtscts = !(ucr2 & UCR2_IRTS);
>
> if (!(mctrl & TIOCM_RTS)) {
> /* Force RTS inactive, i.e. UCR2_CTS=0 and UCR2_CTSC=0 */
> } else if (crtscts) {
> /* let the receiver control RTS */
> ucr2 |= UCR2_CTSC;
> } else {
> /* Force RTS active */
> ucr2 |= UCR2_CTS;
> }
Right, this is functionally correct as well, and thus it's a matter of
taste, but I still believe that what I suggested is better:
ucr2 = imx_uart_readl(sport, UCR2);
ucr2 &= ~(UCR2_CTS | UCR2_CTSC);
if (mctrl & TIOCM_RTS) {
ucr2 |= UCR2_CTS;
if (!(ucr2 & UCR2_IRTS))
ucr2 |= UCR2_CTSC;
}
First, it always sets hardware RTS according to TIOCM_RTS, that IMHO is
less surprising than clearing hardware RTS bit when port is configured
CRTSCTS.
Second, (unfortunate) inter-dependency between TIOCM_RTS and CRTSCTS is
better isolated, so to get rid of it (even if only mentally), only
removals are required, that reduces the code to quite obvious:
ucr2 = imx_uart_readl(sport, UCR2);
ucr2 &= ~(UCR2_CTS);
if (mctrl & TIOCM_RTS)
ucr2 |= UCR2_CTS;
Thanks!
-- Sergey
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 5/7] serial: imx: set_termios(): do not enable autoRTS if RTS is unset
From: Sergey Organov @ 2019-06-27 6:16 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Pengutronix Kernel Team, Sascha Hauer, linux-arm-kernel,
linux-serial, NXP Linux Team
In-Reply-To: <20190627054733.wssatfb2i257737m@pengutronix.de>
Uwe Kleine-König <u.kleine-koenig@pengutronix.de> writes:
> On Wed, Jun 26, 2019 at 05:11:31PM +0300, Sergey Organov wrote:
>> set_termios() shouldn't set UCR2_CTSC bit if UCR2_CTS (=TIOCM_RTS) is
>> cleared. Added corresponding check in imx_uart_rts_auto() to fix this.
>>
>> Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
>> Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
>> Signed-off-by: Sergey Organov <sorganov@gmail.com>
>> ---
>> drivers/tty/serial/imx.c | 3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
>> index e0f5365..4867f80 100644
>> --- a/drivers/tty/serial/imx.c
>> +++ b/drivers/tty/serial/imx.c
>> @@ -405,7 +405,8 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
>> /* called with port.lock taken and irqs caller dependent */
>> static void imx_uart_rts_auto(struct imx_port *sport, u32 *ucr2)
>> {
>> - *ucr2 |= UCR2_CTSC;
>> + if (*ucr2 & UCR2_CTS)
>> + *ucr2 |= UCR2_CTSC;
>> }
>
> I wonder if this patch is only correct in the presence of the previous
> patch. With the code currently in mainline imx_uart_rts_auto() is only
> called with UCR2_CTS unset.
Yes, exactly.
Thanks!
-- Sergey
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/2] serial: imx: remove duplicate handling of CTS change
From: Uwe Kleine-König @ 2019-06-27 6:16 UTC (permalink / raw)
To: Sascha Hauer
Cc: Pengutronix Kernel Team, Sergey Organov, linux-arm-kernel,
linux-serial, NXP Linux Team
In-Reply-To: <20190626101557.26299-2-s.hauer@pengutronix.de>
On Wed, Jun 26, 2019 at 12:15:56PM +0200, Sascha Hauer wrote:
> We have an interrupt for the CTS input (RTS in FSL speech). Its handler
> calls uart_handle_cts_change(), so we shouldn't do this in
> imx_uart_mctrl_check() again.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> drivers/tty/serial/imx.c | 6 ------
> 1 file changed, 6 deletions(-)
>
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> index a5e80a028e83..0419a084c0ed 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -805,12 +805,8 @@ static void imx_uart_clear_rx_errors(struct imx_port *sport);
> static unsigned int imx_uart_get_hwmctrl(struct imx_port *sport)
> {
> unsigned int tmp = TIOCM_DSR;
> - unsigned usr1 = imx_uart_readl(sport, USR1);
> unsigned usr2 = imx_uart_readl(sport, USR2);
>
> - if (usr1 & USR1_RTSS)
> - tmp |= TIOCM_CTS;
> -
> /* in DCE mode DCDIN is always 0 */
> if (!(usr2 & USR2_DCDIN))
> tmp |= TIOCM_CAR;
Is this hunk supposed to be included in this patch? I think it's wrong.
> @@ -843,8 +839,6 @@ static void imx_uart_mctrl_check(struct imx_port *sport)
> sport->port.icount.dsr++;
> if (changed & TIOCM_CAR)
> uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
> - if (changed & TIOCM_CTS)
> - uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
This doesn't hurt, does it? Also imx_uart_mctrl_check is called from
imx_uart_timeout which is supposed to catch missed interrupts and in
this case uart_handle_cts_change() must be called.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* Re: [PATCH v2 4/7] serial: imx: set_termios(): preserve RTS state
From: Sergey Organov @ 2019-06-27 6:15 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Pengutronix Kernel Team, Sascha Hauer, linux-arm-kernel,
linux-serial, NXP Linux Team
In-Reply-To: <20190627054040.fmox5woti4gztmat@pengutronix.de>
Uwe Kleine-König <u.kleine-koenig@pengutronix.de> writes:
> On Wed, Jun 26, 2019 at 05:11:30PM +0300, Sergey Organov wrote:
>> imx_set_termios() cleared RTS on every call, now fixed.
>
> Is this a real problem, or something you noticed by looking at the code?
> I think I already asked that in a previous round, if so this should at
> least be explained in more detail in the commit log.
Yes, it was real observed problem. Every call to set_termios from user
space (through tcsetattr() function) cleared RTS.
> Also please note that this is about the UCR2_CTS flag. (It is, isn't
> it? I don't understand it after staring at the code for a while.)
"CTS" in iMX terms means what everybody else calls "RTS"! Please notice
how they are used in the entire driver, e.g.:
if (mctrl & TIOCM_RTS) {
ucr2 |= UCR2_CTS;
> Assuming this is a real fix, it would be great if this patch came first
> in the series (i.e. before the cleanups) and would be more straight
> forward to understand.
I rather believe that pre-cleanups actually make the fix more
straightforward to understand.
Thanks!
-- Sergey
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
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