@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/input.h>
+#include <linux/kthread.h>
#include <linux/leds.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>
@@ -78,6 +79,7 @@ struct cap11xx_led {
struct cap11xx_priv {
struct regmap *regmap;
+ struct task_struct *poll_thread;
struct input_dev *idev;
struct cap11xx_led *leds;
@@ -202,6 +204,24 @@ static irqreturn_t cap11xx_thread_func(int irq_num, void *data)
return IRQ_HANDLED;
}
+static int poll_irq(void *data) {
+
+ struct cap11xx_priv *priv = data;
+ int ret;
+ unsigned int status;
+
+ /* until module unload */
+ while (!kthread_should_stop()) {
+ ret = regmap_read(priv->regmap, CAP11XX_REG_MAIN_CONTROL, &status);
+ if (ret >= 0 && (status & 1))
+ cap11xx_thread_func(-1, priv);
+ usleep_range(15000, 25000);
+ }
+
+ return 0;
+}
+
+
static int cap11xx_set_sleep(struct cap11xx_priv *priv, bool sleep)
{
/*
@@ -320,6 +340,17 @@ static int cap11xx_init_leds(struct device *dev,
}
#endif
+static int cap11xx_i2c_remove(struct i2c_client *i2c_client)
+{
+ struct cap11xx_priv *priv = i2c_get_clientdata(i2c_client);
+
+ if (priv->poll_thread) {
+ kthread_stop(priv->poll_thread);
+ mdelay(10);
+ }
+ return 0;
+}
+
static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id)
{
@@ -348,8 +379,6 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
if (!priv)
return -ENOMEM;
- i2c_set_clientdata(i2c_client, priv);
-
priv->regmap = devm_regmap_init_i2c(i2c_client, &cap11xx_regmap_config);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
@@ -458,8 +487,19 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
irq = irq_of_parse_and_map(node, 0);
if (!irq) {
- dev_err(dev, "Unable to parse or map IRQ\n");
- return -ENXIO;
+ if (!of_property_read_bool(node, "linux,irq-poll")) {
+ dev_err(dev, "Unable to parse or map IRQ\n");
+ return -ENXIO;
+ }
+ dev_info(dev, "IRQ failed or undefined, using poll_thread\n");
+ priv->poll_thread = kthread_create(poll_irq, priv, "%s-%s-poll",
+ id->name, dev_name(dev));
+ if (!priv->poll_thread) {
+ dev_err(dev, "Unable to start poll_thread\n");
+ return -ENXIO;
+ }
+ wake_up_process(priv->poll_thread);
+ return 0;
}
error = devm_request_threaded_irq(dev, irq, NULL, cap11xx_thread_func,
@@ -495,6 +535,7 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
},
.id_table = cap11xx_i2c_ids,
.probe = cap11xx_i2c_probe,
+ .remove = cap11xx_i2c_remove,
};
module_i2c_driver(cap11xx_i2c_driver);
Signed-off-by: Kurt Van Dijck <dev.kurt@vandijck-laurijssen.be> --- drivers/input/keyboard/cap11xx.c | 49 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-)