aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorJakub Kicinski <kubakici@wp.pl>2015-05-29 15:20:33 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-05-31 17:47:27 -0400
commit478d1051a0293b8a8857267bb0f768ebcb05cfde (patch)
tree7a35b87afbb87cdbb27f878a2d1d046707315fc2 /drivers/tty
parent059d5815304bdbe440d0ffc957d832aebf076ca3 (diff)
sc16is7xx: use kworker for RS-485 configuration
RS-485 configuration is also done under the spinlock so no blocking I/O allowed. Signed-off-by: Jakub Kicinski <kubakici@wp.pl> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/sc16is7xx.c41
1 files changed, 29 insertions, 12 deletions
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index 86a679a5870b..9e6576004a42 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -303,6 +303,7 @@ struct sc16is7xx_devtype {
303 303
304#define SC16IS7XX_RECONF_MD (1 << 0) 304#define SC16IS7XX_RECONF_MD (1 << 0)
305#define SC16IS7XX_RECONF_IER (1 << 1) 305#define SC16IS7XX_RECONF_IER (1 << 1)
306#define SC16IS7XX_RECONF_RS485 (1 << 2)
306 307
307struct sc16is7xx_one_config { 308struct sc16is7xx_one_config {
308 unsigned int flags; 309 unsigned int flags;
@@ -668,6 +669,26 @@ static void sc16is7xx_tx_proc(struct kthread_work *ws)
668 sc16is7xx_handle_tx(port); 669 sc16is7xx_handle_tx(port);
669} 670}
670 671
672static void sc16is7xx_reconf_rs485(struct uart_port *port)
673{
674 const u32 mask = SC16IS7XX_EFCR_AUTO_RS485_BIT |
675 SC16IS7XX_EFCR_RTS_INVERT_BIT;
676 u32 efcr = 0;
677 struct serial_rs485 *rs485 = &port->rs485;
678 unsigned long irqflags;
679
680 spin_lock_irqsave(&port->lock, irqflags);
681 if (rs485->flags & SER_RS485_ENABLED) {
682 efcr |= SC16IS7XX_EFCR_AUTO_RS485_BIT;
683
684 if (rs485->flags & SER_RS485_RTS_AFTER_SEND)
685 efcr |= SC16IS7XX_EFCR_RTS_INVERT_BIT;
686 }
687 spin_unlock_irqrestore(&port->lock, irqflags);
688
689 sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG, mask, efcr);
690}
691
671static void sc16is7xx_reg_proc(struct kthread_work *ws) 692static void sc16is7xx_reg_proc(struct kthread_work *ws)
672{ 693{
673 struct sc16is7xx_one *one = to_sc16is7xx_one(ws, reg_work); 694 struct sc16is7xx_one *one = to_sc16is7xx_one(ws, reg_work);
@@ -688,6 +709,9 @@ static void sc16is7xx_reg_proc(struct kthread_work *ws)
688 if (config.flags & SC16IS7XX_RECONF_IER) 709 if (config.flags & SC16IS7XX_RECONF_IER)
689 sc16is7xx_port_update(&one->port, SC16IS7XX_IER_REG, 710 sc16is7xx_port_update(&one->port, SC16IS7XX_IER_REG,
690 config.ier_clear, 0); 711 config.ier_clear, 0);
712
713 if (config.flags & SC16IS7XX_RECONF_RS485)
714 sc16is7xx_reconf_rs485(&one->port);
691} 715}
692 716
693static void sc16is7xx_ier_clear(struct uart_port *port, u8 bit) 717static void sc16is7xx_ier_clear(struct uart_port *port, u8 bit)
@@ -845,9 +869,8 @@ static void sc16is7xx_set_termios(struct uart_port *port,
845static int sc16is7xx_config_rs485(struct uart_port *port, 869static int sc16is7xx_config_rs485(struct uart_port *port,
846 struct serial_rs485 *rs485) 870 struct serial_rs485 *rs485)
847{ 871{
848 const u32 mask = SC16IS7XX_EFCR_AUTO_RS485_BIT | 872 struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
849 SC16IS7XX_EFCR_RTS_INVERT_BIT; 873 struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
850 u32 efcr = 0;
851 874
852 if (rs485->flags & SER_RS485_ENABLED) { 875 if (rs485->flags & SER_RS485_ENABLED) {
853 bool rts_during_rx, rts_during_tx; 876 bool rts_during_rx, rts_during_tx;
@@ -855,13 +878,7 @@ static int sc16is7xx_config_rs485(struct uart_port *port,
855 rts_during_rx = rs485->flags & SER_RS485_RTS_AFTER_SEND; 878 rts_during_rx = rs485->flags & SER_RS485_RTS_AFTER_SEND;
856 rts_during_tx = rs485->flags & SER_RS485_RTS_ON_SEND; 879 rts_during_tx = rs485->flags & SER_RS485_RTS_ON_SEND;
857 880
858 efcr |= SC16IS7XX_EFCR_AUTO_RS485_BIT; 881 if (rts_during_rx == rts_during_tx)
859
860 if (!rts_during_rx && rts_during_tx)
861 /* default */;
862 else if (rts_during_rx && !rts_during_tx)
863 efcr |= SC16IS7XX_EFCR_RTS_INVERT_BIT;
864 else
865 dev_err(port->dev, 882 dev_err(port->dev,
866 "unsupported RTS signalling on_send:%d after_send:%d - exactly one of RS485 RTS flags should be set\n", 883 "unsupported RTS signalling on_send:%d after_send:%d - exactly one of RS485 RTS flags should be set\n",
867 rts_during_tx, rts_during_rx); 884 rts_during_tx, rts_during_rx);
@@ -875,9 +892,9 @@ static int sc16is7xx_config_rs485(struct uart_port *port,
875 return -EINVAL; 892 return -EINVAL;
876 } 893 }
877 894
878 sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG, mask, efcr);
879
880 port->rs485 = *rs485; 895 port->rs485 = *rs485;
896 one->config.flags |= SC16IS7XX_RECONF_RS485;
897 queue_kthread_work(&s->kworker, &one->reg_work);
881 898
882 return 0; 899 return 0;
883} 900}