On Fri, Mar 24, 2023 at 03:18:53PM +0200, Roger Quadros wrote: > From: Aswath Govindraju <a-govindraju@xxxxxx> > > Some development boards don't have the interrupt line connected. > > In such cases we can resort to polling the interrupt status. > > Signed-off-by: Aswath Govindraju <a-govindraju@xxxxxx> > Signed-off-by: Roger Quadros <rogerq@xxxxxxxxxx> Reviewed-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> > --- > drivers/usb/typec/tipd/core.c | 41 ++++++++++++++++++++++++++++++----- > 1 file changed, 36 insertions(+), 5 deletions(-) > > diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c > index 485b90c13078..d28ffa10a122 100644 > --- a/drivers/usb/typec/tipd/core.c > +++ b/drivers/usb/typec/tipd/core.c > @@ -16,6 +16,7 @@ > #include <linux/usb/typec.h> > #include <linux/usb/typec_altmode.h> > #include <linux/usb/role.h> > +#include <linux/workqueue.h> > > #include "tps6598x.h" > #include "trace.h" > @@ -97,6 +98,8 @@ struct tps6598x { > > int wakeup; > u16 pwr_status; > + struct delayed_work wq_poll; > + irq_handler_t irq_handler; > }; > > static enum power_supply_property tps6598x_psy_props[] = { > @@ -568,6 +571,18 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data) > return IRQ_NONE; > } > > +/* Time interval for Polling */ > +#define POLL_INTERVAL 500 /* msecs */ > +static void tps6598x_poll_work(struct work_struct *work) > +{ > + struct tps6598x *tps = container_of(to_delayed_work(work), > + struct tps6598x, wq_poll); > + > + tps->irq_handler(0, tps); > + queue_delayed_work(system_power_efficient_wq, > + &tps->wq_poll, msecs_to_jiffies(POLL_INTERVAL)); > +} > + > static int tps6598x_check_mode(struct tps6598x *tps) > { > char mode[5] = { }; > @@ -746,6 +761,7 @@ static int tps6598x_probe(struct i2c_client *client) > TPS_REG_INT_PLUG_EVENT; > } > > + tps->irq_handler = irq_handler; > /* Make sure the controller has application firmware running */ > ret = tps6598x_check_mode(tps); > if (ret) > @@ -837,10 +853,18 @@ static int tps6598x_probe(struct i2c_client *client) > dev_err(&client->dev, "failed to register partner\n"); > } > > - ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, > - irq_handler, > - IRQF_SHARED | IRQF_ONESHOT, > - dev_name(&client->dev), tps); > + if (client->irq) { > + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, > + irq_handler, > + IRQF_SHARED | IRQF_ONESHOT, > + dev_name(&client->dev), tps); > + } else { > + dev_warn(tps->dev, "Unable to find the interrupt, switching to polling\n"); > + INIT_DELAYED_WORK(&tps->wq_poll, tps6598x_poll_work); > + queue_delayed_work(system_power_efficient_wq, &tps->wq_poll, > + msecs_to_jiffies(POLL_INTERVAL)); > + } > + > if (ret) > goto err_disconnect; > > @@ -848,7 +872,7 @@ static int tps6598x_probe(struct i2c_client *client) > fwnode_handle_put(fwnode); > > tps->wakeup = device_property_read_bool(tps->dev, "wakeup-source"); > - if (tps->wakeup) { > + if (tps->wakeup && client->irq) { > device_init_wakeup(&client->dev, true); > enable_irq_wake(client->irq); > } > @@ -887,6 +911,9 @@ static int __maybe_unused tps6598x_suspend(struct device *dev) > enable_irq_wake(client->irq); > } > > + if (!client->irq) > + cancel_delayed_work_sync(&tps->wq_poll); > + > return 0; > } > > @@ -900,6 +927,10 @@ static int __maybe_unused tps6598x_resume(struct device *dev) > enable_irq(client->irq); > } > > + if (client->irq) > + queue_delayed_work(system_power_efficient_wq, &tps->wq_poll, > + msecs_to_jiffies(POLL_INTERVAL)); > + > return 0; > } > > -- > 2.34.1 -- heikki