Skip to content

Commit 104c1b9

Browse files
systec-awegregkh
authored andcommitted
serial: sc16is7xx: Add polling mode if no IRQ pin is available
Fall back to polling mode if no interrupt is configured because there is no possibility to connect the interrupt pin. If "interrupts" property is missing in devicetree the driver uses a delayed worker to pull the state of interrupt status registers. Signed-off-by: Andre Werner <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 4dd7c9d commit 104c1b9

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

drivers/tty/serial/sc16is7xx.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@
314314
#define SC16IS7XX_FIFO_SIZE (64)
315315
#define SC16IS7XX_GPIOS_PER_BANK 4
316316

317+
#define SC16IS7XX_POLL_PERIOD_MS 10
317318
#define SC16IS7XX_RECONF_MD BIT(0)
318319
#define SC16IS7XX_RECONF_IER BIT(1)
319320
#define SC16IS7XX_RECONF_RS485 BIT(2)
@@ -348,6 +349,8 @@ struct sc16is7xx_port {
348349
u8 mctrl_mask;
349350
struct kthread_worker kworker;
350351
struct task_struct *kworker_task;
352+
struct kthread_delayed_work poll_work;
353+
bool polling;
351354
struct sc16is7xx_one p[];
352355
};
353356

@@ -861,6 +864,18 @@ static irqreturn_t sc16is7xx_irq(int irq, void *dev_id)
861864
return IRQ_HANDLED;
862865
}
863866

867+
static void sc16is7xx_poll_proc(struct kthread_work *ws)
868+
{
869+
struct sc16is7xx_port *s = container_of(ws, struct sc16is7xx_port, poll_work.work);
870+
871+
/* Reuse standard IRQ handler. Interrupt ID is unused in this context. */
872+
sc16is7xx_irq(0, s);
873+
874+
/* Setup delay based on SC16IS7XX_POLL_PERIOD_MS */
875+
kthread_queue_delayed_work(&s->kworker, &s->poll_work,
876+
msecs_to_jiffies(SC16IS7XX_POLL_PERIOD_MS));
877+
}
878+
864879
static void sc16is7xx_tx_proc(struct kthread_work *ws)
865880
{
866881
struct uart_port *port = &(to_sc16is7xx_one(ws, tx_work)->port);
@@ -1149,6 +1164,7 @@ static int sc16is7xx_config_rs485(struct uart_port *port, struct ktermios *termi
11491164
static int sc16is7xx_startup(struct uart_port *port)
11501165
{
11511166
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
1167+
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
11521168
unsigned int val;
11531169
unsigned long flags;
11541170

@@ -1211,6 +1227,10 @@ static int sc16is7xx_startup(struct uart_port *port)
12111227
sc16is7xx_enable_ms(port);
12121228
uart_port_unlock_irqrestore(port, flags);
12131229

1230+
if (s->polling)
1231+
kthread_queue_delayed_work(&s->kworker, &s->poll_work,
1232+
msecs_to_jiffies(SC16IS7XX_POLL_PERIOD_MS));
1233+
12141234
return 0;
12151235
}
12161236

@@ -1232,6 +1252,9 @@ static void sc16is7xx_shutdown(struct uart_port *port)
12321252

12331253
sc16is7xx_power(port, 0);
12341254

1255+
if (s->polling)
1256+
kthread_cancel_delayed_work_sync(&s->poll_work);
1257+
12351258
kthread_flush_worker(&s->kworker);
12361259
}
12371260

@@ -1538,6 +1561,11 @@ int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype,
15381561
/* Always ask for fixed clock rate from a property. */
15391562
device_property_read_u32(dev, "clock-frequency", &uartclk);
15401563

1564+
s->polling = !!irq;
1565+
if (s->polling)
1566+
dev_dbg(dev,
1567+
"No interrupt pin definition, falling back to polling mode\n");
1568+
15411569
s->clk = devm_clk_get_optional(dev, NULL);
15421570
if (IS_ERR(s->clk))
15431571
return PTR_ERR(s->clk);
@@ -1665,6 +1693,12 @@ int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype,
16651693
goto out_ports;
16661694
#endif
16671695

1696+
if (s->polling) {
1697+
/* Initialize kernel thread for polling */
1698+
kthread_init_delayed_work(&s->poll_work, sc16is7xx_poll_proc);
1699+
return 0;
1700+
}
1701+
16681702
/*
16691703
* Setup interrupt. We first try to acquire the IRQ line as level IRQ.
16701704
* If that succeeds, we can allow sharing the interrupt as well.
@@ -1724,6 +1758,9 @@ void sc16is7xx_remove(struct device *dev)
17241758
sc16is7xx_power(&s->p[i].port, 0);
17251759
}
17261760

1761+
if (s->polling)
1762+
kthread_cancel_delayed_work_sync(&s->poll_work);
1763+
17271764
kthread_flush_worker(&s->kworker);
17281765
kthread_stop(s->kworker_task);
17291766

0 commit comments

Comments
 (0)