sc16is7xx: Add flag to activate IrDA mode
authorPascal Huerst <pascal.huerst@gmail.com>
Fri, 29 May 2020 05:50:58 +0000 (07:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 29 May 2020 10:42:56 +0000 (12:42 +0200)
This series of uart controllers is able to work in IrDA mode.
Add per-port flag to the device-tree to enable that feature if needed.

Signed-off-by: Pascal Huerst <pascal.huerst@gmail.com>
Signed-off-by: Daniel Mack <daniel@zonque.org>
Link: https://lore.kernel.org/r/20200529055058.1606910-3-daniel@zonque.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/sc16is7xx.c

index 8fee0e8..d2e5c6c 100644 (file)
@@ -315,6 +315,7 @@ struct sc16is7xx_one {
        struct kthread_work             tx_work;
        struct kthread_work             reg_work;
        struct sc16is7xx_one_config     config;
+       bool                            irda_mode;
 };
 
 struct sc16is7xx_port {
@@ -986,6 +987,7 @@ static int sc16is7xx_config_rs485(struct uart_port *port,
 
 static int sc16is7xx_startup(struct uart_port *port)
 {
+       struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
        struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
        unsigned int val;
 
@@ -1024,6 +1026,13 @@ static int sc16is7xx_startup(struct uart_port *port)
        /* Now, initialize the UART */
        sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8);
 
+       /* Enable IrDA mode if requested in DT */
+       /* This bit must be written with LCR[7] = 0 */
+       sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
+                             SC16IS7XX_MCR_IRDA_BIT,
+                             one->irda_mode ?
+                               SC16IS7XX_MCR_IRDA_BIT : 0);
+
        /* Enable the Rx and Tx FIFO */
        sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG,
                              SC16IS7XX_EFCR_RXDISABLE_BIT |
@@ -1304,6 +1313,17 @@ static int sc16is7xx_probe(struct device *dev,
                sc16is7xx_power(&s->p[i].port, 0);
        }
 
+       if (dev->of_node) {
+               struct property *prop;
+               const __be32 *p;
+               u32 u;
+
+               of_property_for_each_u32(dev->of_node, "irda-mode-ports",
+                                        prop, p, u)
+                       if (u < devtype->nr_uart)
+                               s->p[u].irda_mode = true;
+       }
+
        /*
         * Setup interrupt. We first try to acquire the IRQ line as level IRQ.
         * If that succeeds, we can allow sharing the interrupt as well.