lkml.org 
[lkml]   [2019]   [Jul]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectRe: [RFC PATCH v2 0/4] Input: mpr121-polled: Add polled driver for MPR121
From
Date
On 27. 07. 19 9:31, Dmitry Torokhov wrote:
> On Fri, Jul 26, 2019 at 01:31:31PM +0200, Michal Vokáč wrote:
>> On 25. 07. 19 16:40, Dmitry Torokhov wrote:
>>> On Thu, Jul 25, 2019 at 02:58:02PM +0200, Michal Vokáč wrote:
>>>> On 25. 07. 19 10:57, Dmitry Torokhov wrote:
>>>>> Hi Michal,
>>>>>
>>>>> On Tue, May 21, 2019 at 08:51:17AM +0200, Michal Vokáč wrote:
>>>>>> On 21. 05. 19 7:37, Dmitry Torokhov wrote:
>>>>>>> Hi Michal,
>>>>>>>
>>>>>>> On Fri, May 17, 2019 at 03:12:49PM +0200, Michal Vokáč wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> I have to deal with a situation where we have a custom i.MX6 based
>>>>>>>> platform in production that uses the MPR121 touchkey controller.
>>>>>>>> Unfortunately the chip is connected using only the I2C interface.
>>>>>>>> The interrupt line is not used. Back in 2015 (Linux v3.14), my
>>>>>>>> colleague modded the existing mpr121_touchkey.c driver to use polling
>>>>>>>> instead of interrupt.
>>>>>>>>
>>>>>>>> For quite some time yet I am in a process of updating the product from
>>>>>>>> the ancient Freescale v3.14 kernel to the latest mainline and pushing
>>>>>>>> any needed changes upstream. The DT files for our imx6dl-yapp4 platform
>>>>>>>> already made it into v5.1-rc.
>>>>>>>>
>>>>>>>> I rebased and updated our mpr121 patch to the latest mainline.
>>>>>>>> It is created as a separate driver, similarly to gpio_keys_polled.
>>>>>>>>
>>>>>>>> The I2C device is quite susceptible to ESD. An ESD test quite often
>>>>>>>> causes reset of the chip or some register randomly changes its value.
>>>>>>>> The [PATCH 3/4] adds a write-through register cache. With the cache
>>>>>>>> this state can be detected and the device can be re-initialied.
>>>>>>>>
>>>>>>>> The main question is: Is there any chance that such a polled driver
>>>>>>>> could be accepted? Is it correct to implement it as a separate driver
>>>>>>>> or should it be done as an option in the existing driver? I can not
>>>>>>>> really imagine how I would do that though..
>>>>>>>>
>>>>>>>> There are also certain worries that the MPR121 chip may no longer be
>>>>>>>> available in nonspecifically distant future. In case of EOL I will need
>>>>>>>> to add a polled driver for an other touchkey chip. May it be already
>>>>>>>> in mainline or a completely new one.
>>>>>>>
>>>>>>> I think that my addition of input_polled_dev was ultimately a wrong
>>>>>>> thing to do. I am looking into enabling polling mode for regular input
>>>>>>> devices as we then can enable polling mode in existing drivers.
>>>>>>
>>>>>> OK, that sounds good. Especially when one needs to switch from one chip
>>>>>> to another that is already in tree, the need for a whole new polling
>>>>>> driver is eliminated.
>>>>>
>>>>> Could you please try the patch below and see if it works for your use
>>>>> case? Note that I have not tried running it, but it compiles so it must
>>>>> be good ;)
>>>>
>>>> Hi Dmitry,
>>>> Thank you very much for the patch!
>>>> I gave it a shot and it seems you forgot to add the input-poller.h file
>>>> to the patch.. it does not compile on my side :(
>>>
>>> Oops ;) Please see the updated patch below.
>>
>> Thank you, now it is (almost) good as you said :D
>>
>>>>
>>>>> Input: add support for polling to input devices
>>>>>
>>>>> From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>>>>>
>>>>> Separating "normal" and "polled" input devices was a mistake, as often we want
>>>>> to allow the very same device work on both interrupt-driven and polled mode,
>>>>> depending on the board on which the device is used.
>>>>>
>>>>> This introduces new APIs:
>>>>>
>>>>> - input_setup_polling
>>>>> - input_set_poll_interval
>>>>> - input_set_min_poll_interval
>>>>> - input_set_max_poll_interval
>>>>>
>>>>> These new APIs allow switching an input device into polled mode with sysfs
>>>>> attributes matching drivers using input_polled_dev APIs that will be eventually
>>>>> removed.
>>>>
>>>> After reading this I am not really sure what else needs to be done
>>>> to test/use the poller. I suspect I need to modify the input device
>>>> driver (mpr121_touchkey.c in my case) like this:
>>>>
>>>> If the interrupt gpio is not provided in DT, the device driver probe
>>>> function should:
>>>> - not request the threaded interrupt
>>>> - call input_setup_polling and provide it with poll_fn
>>>> Can the mpr_touchkey_interrupt function be used as is for this
>>>> purpose? The only problem I see is it returns IRQ_HANDLED.
>>>
>>> I'd factor out code suitable for polling from mpr_touchkey_interrupt()
>>> and then do
>>>
>>> static irqreturn_t mpr_touchkey_interrupt(...)
>>> {
>>> mpr_touchkey_report(...);
>>> return IRQ_HANDLED;
>>> }
>>>
>>
>> Probably a trivial problem for experienced kernel hacker but I can not
>> wrap my head around this - the interrupt handler takes the mpr121
>> device id as an argument while the poller poll_fn takes struct input_dev.
>>
>> I fail to figure out how to get the device id from the input device.
>>
Thanks for the hints Dmitry. I am trying my best but still have some
issues with the input_set/get_drvdata.

The kernel Oopses on NULL pointer dereference in mpr_touchkey_report.
Here is the backtrace:

[ 2.916960] 8<--- cut here ---
[ 2.920022] Unable to handle kernel NULL pointer dereference at virtual address 000001d0
[ 2.928138] pgd = (ptrval)
[ 2.930851] [000001d0] *pgd=00000000
[ 2.934439] Internal error: Oops: 5 [#1] SMP ARM
[ 2.939065] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.3.0-rc1-00001-g7278b7c3986c-dirty #2
[ 2.947503] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[ 2.954044] PC is at mpr_touchkey_report+0x18/0x1bc
[ 2.958932] LR is at input_dev_poller_start+0x30/0x3c
[ 2.963987] pc : [<80728c50>] lr : [<8071f444>] psr: 20000013
[ 2.970255] sp : e8131c10 ip : e8131c68 fp : e8131c64
[ 2.975480] r10: 000000c9 r9 : 8108339c r8 : 81083340
[ 2.980707] r7 : 00000000 r6 : e86cf574 r5 : e86b8480 r4 : e86b8040
[ 2.987236] r3 : 80728c38 r2 : e8128000 r1 : 00000000 r0 : 00000000
[ 2.993767] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
[ 3.000906] Control: 10c5387d Table: 1000404a DAC: 00000051
[ 3.006656] Process swapper/0 (pid: 1, stack limit = 0x(ptrval))
[ 3.012667] Stack: (0xe8131c10 to 0xe8132000)
[ 3.017033] 1c00: 60000013 8017f290 e8131c64 e8131c28
[ 3.025219] 1c20: 8017f290 8017f098 80e7eb04 e8131cd4 0000013d 00000000 80bc6ba4 e86b8040
[ 3.033403] 1c40: e86b8480 e86cf574 00000000 81083340 8108339c 000000c9 e8131c7c e8131c68
[ 3.041587] 1c60: 8071f444 80728c44 e86cf400 e86b8480 e8131c9c e8131c80 8071d230 8071f420
[ 3.049769] 1c80: e86b8480 00000000 e86cf400 8106baa4 e8131cbc e8131ca0 80591b00 8071d1a0
[ 3.057951] 1ca0: 80c567c4 e86cf400 8106baa4 8106baa4 e8131cdc e8131cc0 8071d75c 80591a98
[ 3.066136] 1cc0: e86cf400 00000000 e86ba1c0 8106baa4 e8131d04 e8131ce0 8071df50 8071d6cc
[ 3.074320] 1ce0: 00000000 e834a400 e86cf400 e86ba0c0 e834a420 51eb851f e8131d54 e8131d08
[ 3.082502] 1d00: 807291c4 8071dbc0 00000000 00000000 00000000 0d3abafe 00325aa0 81006548
[ 3.090686] 1d20: 000003e8 0d3abafe 8063907c e834a420 80728e34 81083950 e834a400 00000000
[ 3.098867] 1d40: 00000000 00000000 e8131d7c e8131d58 80747410 80728e40 81123a00 e834a420
[ 3.107051] 1d60: 81123b0c 00000000 81083950 00000000 e8131dac e8131d80 8061f684 807471c4
[ 3.115233] 1d80: 00000000 e834a420 81083950 81083950 81006548 00000000 80f8c83c 80f008ac
[ 3.123415] 1da0: e8131de4 e8131db0 8061fca8 8061f590 e8131dcc e8131dc0 8080e234 8061ed70
[ 3.131599] 1dc0: e834a420 00000000 81083950 81006548 00000000 80f8c83c e8131e04 e8131de8
[ 3.139784] 1de0: 8061ffcc 8061fc44 81083950 e834a420 8061ffd4 81006548 e8131e24 e8131e08
[ 3.147969] 1e00: 80620040 8061ff70 00000000 81083950 8061ffd4 81006548 e8131e54 e8131e28
[ 3.156151] 1e20: 8061d974 8061ffe0 e8131e60 e821b758 e83413b4 0d3abafe 81083950 e8697f00
[ 3.164333] 1e40: 81084b4c 00000000 e8131e64 e8131e58 806200e0 8061d8fc e8131e8c e8131e68
[ 3.172517] 1e60: 8061e314 806200c0 80e7f9a0 e8131e78 81083950 81006548 80f4a898 ffffe000
[ 3.180699] 1e80: e8131ea4 e8131e90 80620ce4 8061e1b8 81083934 81006548 e8131ebc e8131ea8
[ 3.188882] 1ea0: 80748e18 80620c64 810c0660 81006548 e8131ecc e8131ec0 80f4a8bc 80748dd8
[ 3.197065] 1ec0: e8131f44 e8131ed0 80f01330 80f4a8a4 00000000 80e12924 80e12904 80e12900
[ 3.205250] 1ee0: 80e24610 81006548 00000000 80e128dc 00000006 00000006 00000000 80f008ac
[ 3.213433] 1f00: 80e7eac0 80ee9234 8016f4d4 ebfffb37 ebfffb3f 0d3abafe e8131f44 0d3abafe
[ 3.220284] g_ether gadget: high-speed config #1: CDC Ethernet (ECM)
[ 3.221616] 1f20: 810c0660 00000007 810c0660 80fc21f0 810c5980 810c5980 e8131f94 e8131f48
[ 3.236147] 1f40: 80f0174c 80f01274 00000006 00000006 00000000 80f008ac 801346cc 80133d54
[ 3.244330] 1f60: 80ee9234 00000154 e8131f8c 00000000 80bdb670 00000000 00000000 00000000
[ 3.252512] 1f80: 00000000 00000000 e8131fac e8131f98 80bdb688 80f0146c 00000000 80bdb670
[ 3.260695] 1fa0: 00000000 e8131fb0 801010e8 80bdb67c 00000000 00000000 00000000 00000000
[ 3.268878] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 3.277061] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000
[ 3.285237] Backtrace:
[ 3.287699] [<80728c38>] (mpr_touchkey_report) from [<8071f444>] (input_dev_poller_start+0x30/0x3c)
[ 3.296753] r10:000000c9 r9:8108339c r8:81083340 r7:00000000 r6:e86cf574 r5:e86b8480
[ 3.304584] r4:e86b8040
[ 3.307128] [<8071f414>] (input_dev_poller_start) from [<8071d230>] (input_open_device+0x9c/0xc4)
[ 3.316002] r5:e86b8480 r4:e86cf400
[ 3.319590] [<8071d194>] (input_open_device) from [<80591b00>] (kbd_connect+0x74/0x90)
[ 3.327510] r7:8106baa4 r6:e86cf400 r5:00000000 r4:e86b8480
[ 3.333180] [<80591a8c>] (kbd_connect) from [<8071d75c>] (input_attach_handler+0x9c/0xd0)
[ 3.341361] r7:8106baa4 r6:8106baa4 r5:e86cf400 r4:80c567c4
[ 3.347029] [<8071d6c0>] (input_attach_handler) from [<8071df50>] (input_register_device+0x39c/0x40c)
[ 3.356251] r7:8106baa4 r6:e86ba1c0 r5:00000000 r4:e86cf400
[ 3.361923] [<8071dbb4>] (input_register_device) from [<807291c4>] (mpr_touchkey_probe+0x390/0x4d4)
[ 3.370974] r9:51eb851f r8:e834a420 r7:e86ba0c0 r6:e86cf400 r5:e834a400 r4:00000000
[ 3.378727] [<80728e34>] (mpr_touchkey_probe) from [<80747410>] (i2c_device_probe+0x258/0x27c)
[ 3.387344] r10:00000000 r9:00000000 r8:00000000 r7:e834a400 r6:81083950 r5:80728e34
[ 3.395174] r4:e834a420
[ 3.397715] [<807471b8>] (i2c_device_probe) from [<8061f684>] (really_probe+0x100/0x2d8)
[ 3.405810] r9:00000000 r8:81083950 r7:00000000 r6:81123b0c r5:e834a420 r4:81123a00
[ 3.413562] [<8061f584>] (really_probe) from [<8061fca8>] (driver_probe_device+0x70/0x180)
[ 3.421832] r10:80f008ac r9:80f8c83c r8:00000000 r7:81006548 r6:81083950 r5:81083950
[ 3.429662] r4:e834a420 r3:00000000
[ 3.433245] [<8061fc38>] (driver_probe_device) from [<8061ffcc>] (device_driver_attach+0x68/0x70)
[ 3.442121] r9:80f8c83c r8:00000000 r7:81006548 r6:81083950 r5:00000000 r4:e834a420
[ 3.449872] [<8061ff64>] (device_driver_attach) from [<80620040>] (__driver_attach+0x6c/0xe0)
[ 3.458399] r7:81006548 r6:8061ffd4 r5:e834a420 r4:81083950
[ 3.464071] [<8061ffd4>] (__driver_attach) from [<8061d974>] (bus_for_each_dev+0x84/0xc4)
[ 3.472251] r7:81006548 r6:8061ffd4 r5:81083950 r4:00000000
[ 3.477920] [<8061d8f0>] (bus_for_each_dev) from [<806200e0>] (driver_attach+0x2c/0x30)
[ 3.485926] r7:00000000 r6:81084b4c r5:e8697f00 r4:81083950
[ 3.491594] [<806200b4>] (driver_attach) from [<8061e314>] (bus_add_driver+0x168/0x1ec)
[ 3.499604] [<8061e1ac>] (bus_add_driver) from [<80620ce4>] (driver_register+0x8c/0x124)
[ 3.507697] r7:ffffe000 r6:80f4a898 r5:81006548 r4:81083950
[ 3.513366] [<80620c58>] (driver_register) from [<80748e18>] (i2c_register_driver+0x4c/0x8c)
[ 3.521804] r5:81006548 r4:81083934
[ 3.525394] [<80748dcc>] (i2c_register_driver) from [<80f4a8bc>] (mpr_touchkey_driver_init+0x24/0x28)
[ 3.534616] r5:81006548 r4:810c0660
[ 3.538203] [<80f4a898>] (mpr_touchkey_driver_init) from [<80f01330>] (do_one_initcall+0xc8/0x1f8)
[ 3.547169] [<80f01268>] (do_one_initcall) from [<80f0174c>] (kernel_init_freeable+0x2ec/0x380)
[ 3.555872] r8:810c5980 r7:810c5980 r6:80fc21f0 r5:810c0660 r4:00000007
[ 3.562587] [<80f01460>] (kernel_init_freeable) from [<80bdb688>] (kernel_init+0x18/0x120)
[ 3.570856] r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:80bdb670
[ 3.578685] r4:00000000
[ 3.581230] [<80bdb670>] (kernel_init) from [<801010e8>] (ret_from_fork+0x14/0x2c)
[ 3.588802] Exception stack(0xe8131fb0 to 0xe8131ff8)
[ 3.593859] 1fa0: 00000000 00000000 00000000 00000000
[ 3.602042] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 3.610222] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[ 3.616839] r5:80bdb670 r4:00000000
[ 3.620422] Code: e24cb004 e24dd02c e52de004 e8bd4000 (e59051d0)
[ 3.626572] ---[ end trace eb840c8cb957e159 ]---

I can confirm the poller mechanism works fine if I leave the
mpr_touchkey_report function empty and just return.

I can also confirm the interrupt mechanism works as fine if I bodge
a wire from some available GPIO (commented lines in dtsi).

Here is my code:

diff --git a/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi b/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi
index e8d800fec637..7516da441915 100644
--- a/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi
+++ b/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi
@@ -4,6 +4,7 @@

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/input/input.h>
#include <dt-bindings/pwm/pwm.h>

/ {
@@ -330,6 +331,21 @@
vcc-supply = <&sw2_reg>;
status = "disabled";
};
+
+ touchkeys: keys@5a {
+ compatible = "fsl,mpr121-touchkey";
+ //pinctrl-0 = <&pinctrl_key_irq>;
+ reg = <0x5a>;
+ vdd-supply = <&sw2_reg>;
+ autorepeat;
+ linux,keycodes = <KEY_1>, <KEY_2>, <KEY_3>, <KEY_4>, <KEY_5>,
+ <KEY_6>, <KEY_7>, <KEY_8>, <KEY_9>,
+ <KEY_BACKSPACE>, <KEY_0>, <KEY_ENTER>;
+ linux,poll-interval = <50>;
+ //interrupt-parent = <&gpio1>;
+ //interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+ status = "disabled";
+ };
};

&iomuxc {
@@ -433,6 +449,12 @@
>;
};

+ pinctrl_key_irq: keyirq {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0x1b098
+ >;
+ };
+
pinctrl_touch: touchgrp {
fsl,pins = <
MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b098
diff --git a/arch/arm/boot/dts/imx6dl-yapp4-hydra.dts b/arch/arm/boot/dts/imx6dl-yapp4-hydra.dts
index f97927064750..84c275bfdd38 100644
--- a/arch/arm/boot/dts/imx6dl-yapp4-hydra.dts
+++ b/arch/arm/boot/dts/imx6dl-yapp4-hydra.dts
@@ -45,6 +45,10 @@
status = "okay";
};

+&touchkeys {
+ status = "okay";
+};
+
&usdhc3 {
status = "okay";
};
diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index e9ceaa16b46a..d6b9f6acddca 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -7,7 +7,7 @@
*
* Based on mcs_touchkey.c
*/
-
+#define DEBUG
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/i2c.h>
@@ -54,6 +54,9 @@
/* MPR121 has 12 keys */
#define MPR121_MAX_KEY_COUNT 12

+#define MPR121_MIN_POLL_INTERVAL 10
+#define MPR121_MAX_POLL_INTERVAL 2000
+
struct mpr121_touchkey {
struct i2c_client *client;
struct input_dev *input_dev;
@@ -115,11 +118,11 @@ static struct regulator *mpr121_vdd_supply_init(struct device *dev)
return vdd_supply;
}

-static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
+static void mpr_touchkey_report(struct input_dev *dev)
{
- struct mpr121_touchkey *mpr121 = dev_id;
- struct i2c_client *client = mpr121->client;
+ struct mpr121_touchkey *mpr121 = input_get_drvdata(dev);
struct input_dev *input = mpr121->input_dev;
+ struct i2c_client *client = mpr121->client;
unsigned long bit_changed;
unsigned int key_num;
int reg;
@@ -127,14 +130,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR);
if (reg < 0) {
dev_err(&client->dev, "i2c read error [%d]\n", reg);
- goto out;
+ return;
}

reg <<= 8;
reg |= i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_0_ADDR);
if (reg < 0) {
dev_err(&client->dev, "i2c read error [%d]\n", reg);
- goto out;
+ return;
}

reg &= TOUCH_STATUS_MASK;
@@ -155,8 +158,13 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)

}
input_sync(input);
+}
+
+static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
+{
+ struct mpr121_touchkey *mpr121 = dev_id;
+ mpr_touchkey_report(mpr121->input_dev);

-out:
return IRQ_HANDLED;
}

@@ -229,13 +237,10 @@ static int mpr_touchkey_probe(struct i2c_client *client,
int vdd_uv;
struct mpr121_touchkey *mpr121;
struct input_dev *input_dev;
+ u32 poll_interval = 0;
int error;
int i;

- if (!client->irq) {
- dev_err(dev, "irq number should not be zero\n");
- return -EINVAL;
- }

vdd_supply = mpr121_vdd_supply_init(dev);
if (IS_ERR(vdd_supply))
@@ -275,11 +280,13 @@ static int mpr_touchkey_probe(struct i2c_client *client,
if (device_property_read_bool(dev, "autorepeat"))
__set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+ input_set_drvdata(input_dev, mpr121);

input_dev->keycode = mpr121->keycodes;
input_dev->keycodesize = sizeof(mpr121->keycodes[0]);
input_dev->keycodemax = mpr121->keycount;

+
for (i = 0; i < mpr121->keycount; i++)
input_set_capability(input_dev, EV_KEY, mpr121->keycodes[i]);

@@ -289,13 +296,34 @@ static int mpr_touchkey_probe(struct i2c_client *client,
return error;
}

- error = devm_request_threaded_irq(dev, client->irq, NULL,
- mpr_touchkey_interrupt,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- dev->driver->name, mpr121);
- if (error) {
- dev_err(dev, "Failed to register interrupt\n");
- return error;
+ device_property_read_u32(dev, "linux,poll-interval", &poll_interval);
+
+ if (client->irq) {
+ error = devm_request_threaded_irq(dev, client->irq, NULL,
+ mpr_touchkey_interrupt,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ dev->driver->name, mpr121);
+ if (error) {
+ dev_err(dev, "Failed to register interrupt\n");
+ return error;
+ }
+ } else if (poll_interval > 0) {
+ error = input_setup_polling(input_dev, mpr_touchkey_report);
+ if (error) {
+ dev_err(dev, "Failed to setup polling\n");
+ return error;
+ }
+
+ input_set_poll_interval(input_dev, poll_interval);
+ input_set_min_poll_interval(input_dev,
+ MPR121_MIN_POLL_INTERVAL);
+ input_set_max_poll_interval(input_dev,
+ MPR121_MAX_POLL_INTERVAL);
+ } else {
+ dev_err(dev,
+ "invalid IRQ number and polling not configured\n");
+ return -EINVAL;
}

error = input_register_device(input_dev);
--
\
 
 \ /
  Last update: 2019-07-30 11:26    [W:0.077 / U:1.336 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site