diff options
Diffstat (limited to 'drivers/tty/serial/sc16is7xx.c')
-rw-r--r-- | drivers/tty/serial/sc16is7xx.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index f36e6df2fa90..2675792a8f59 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -708,7 +708,7 @@ static irqreturn_t sc16is7xx_irq(int irq, void *dev_id) { struct sc16is7xx_port *s = (struct sc16is7xx_port *)dev_id; - queue_kthread_work(&s->kworker, &s->irq_work); + kthread_queue_work(&s->kworker, &s->irq_work); return IRQ_HANDLED; } @@ -784,7 +784,7 @@ static void sc16is7xx_ier_clear(struct uart_port *port, u8 bit) one->config.flags |= SC16IS7XX_RECONF_IER; one->config.ier_clear |= bit; - queue_kthread_work(&s->kworker, &one->reg_work); + kthread_queue_work(&s->kworker, &one->reg_work); } static void sc16is7xx_stop_tx(struct uart_port *port) @@ -802,7 +802,7 @@ static void sc16is7xx_start_tx(struct uart_port *port) struct sc16is7xx_port *s = dev_get_drvdata(port->dev); struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); - queue_kthread_work(&s->kworker, &one->tx_work); + kthread_queue_work(&s->kworker, &one->tx_work); } static unsigned int sc16is7xx_tx_empty(struct uart_port *port) @@ -828,7 +828,7 @@ static void sc16is7xx_set_mctrl(struct uart_port *port, unsigned int mctrl) struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); one->config.flags |= SC16IS7XX_RECONF_MD; - queue_kthread_work(&s->kworker, &one->reg_work); + kthread_queue_work(&s->kworker, &one->reg_work); } static void sc16is7xx_break_ctl(struct uart_port *port, int break_state) @@ -957,7 +957,7 @@ static int sc16is7xx_config_rs485(struct uart_port *port, port->rs485 = *rs485; one->config.flags |= SC16IS7XX_RECONF_RS485; - queue_kthread_work(&s->kworker, &one->reg_work); + kthread_queue_work(&s->kworker, &one->reg_work); return 0; } @@ -1030,7 +1030,7 @@ static void sc16is7xx_shutdown(struct uart_port *port) sc16is7xx_power(port, 0); - flush_kthread_worker(&s->kworker); + kthread_flush_worker(&s->kworker); } static const char *sc16is7xx_type(struct uart_port *port) @@ -1176,8 +1176,8 @@ static int sc16is7xx_probe(struct device *dev, s->devtype = devtype; dev_set_drvdata(dev, s); - init_kthread_worker(&s->kworker); - init_kthread_work(&s->irq_work, sc16is7xx_ist); + kthread_init_worker(&s->kworker); + kthread_init_work(&s->irq_work, sc16is7xx_ist); s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker, "sc16is7xx"); if (IS_ERR(s->kworker_task)) { @@ -1205,6 +1205,10 @@ static int sc16is7xx_probe(struct device *dev, } #endif + /* reset device, purging any pending irq / data */ + regmap_write(s->regmap, SC16IS7XX_IOCONTROL_REG << SC16IS7XX_REG_SHIFT, + SC16IS7XX_IOCONTROL_SRESET_BIT); + for (i = 0; i < devtype->nr_uart; ++i) { s->p[i].line = i; /* Initialize port data */ @@ -1230,10 +1234,26 @@ static int sc16is7xx_probe(struct device *dev, SC16IS7XX_EFCR_RXDISABLE_BIT | SC16IS7XX_EFCR_TXDISABLE_BIT); /* Initialize kthread work structs */ - init_kthread_work(&s->p[i].tx_work, sc16is7xx_tx_proc); - init_kthread_work(&s->p[i].reg_work, sc16is7xx_reg_proc); + kthread_init_work(&s->p[i].tx_work, sc16is7xx_tx_proc); + kthread_init_work(&s->p[i].reg_work, sc16is7xx_reg_proc); /* Register port */ uart_add_one_port(&sc16is7xx_uart, &s->p[i].port); + + /* Enable EFR */ + sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG, + SC16IS7XX_LCR_CONF_MODE_B); + + regcache_cache_bypass(s->regmap, true); + + /* Enable write access to enhanced features */ + sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_EFR_REG, + SC16IS7XX_EFR_ENABLE_BIT); + + regcache_cache_bypass(s->regmap, false); + + /* Restore access to general registers */ + sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG, 0x00); + /* Go to suspend mode */ sc16is7xx_power(&s->p[i].port, 0); } @@ -1281,7 +1301,7 @@ static int sc16is7xx_remove(struct device *dev) sc16is7xx_power(&s->p[i].port, 0); } - flush_kthread_worker(&s->kworker); + kthread_flush_worker(&s->kworker); kthread_stop(s->kworker_task); if (!IS_ERR(s->clk)) |