diff mbox series

[v12,2/3] Input: adc-joystick - Add polled input device support

Message ID 20220805171016.21217-3-macroalpha82@gmail.com (mailing list archive)
State Handled Elsewhere
Headers show
Series dt-bindings: adc-joystick: add poll-interval | expand

Commit Message

Chris Morgan Aug. 5, 2022, 5:10 p.m. UTC
From: Chris Morgan <macromorgan@hotmail.com>

Add polled input device support to the adc-joystick driver. This is
useful for devices which do not have hardware capable triggers on
their SARADC. Code modified from adc-joystick.c changes made by Maya
Matuszczyk.

Signed-off-by: Maya Matuszczyk <maccraft123mc@gmail.com>
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
 drivers/input/joystick/adc-joystick.c | 44 +++++++++++++++++++++++++--
 1 file changed, 41 insertions(+), 3 deletions(-)

Comments

Artur Rojek Aug. 6, 2022, 2:19 p.m. UTC | #1
On 2022-08-06 16:20, Jonathan Cameron wrote:
> On Fri,  5 Aug 2022 12:10:15 -0500
> Chris Morgan <macroalpha82@gmail.com> wrote:
> 
>> From: Chris Morgan <macromorgan@hotmail.com>
>> 
>> Add polled input device support to the adc-joystick driver. This is
>> useful for devices which do not have hardware capable triggers on
>> their SARADC. Code modified from adc-joystick.c changes made by Maya
>> Matuszczyk.
>> 
>> Signed-off-by: Maya Matuszczyk <maccraft123mc@gmail.com>
>> Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
> Hi Chris,
> 
> Trying to avoid too much indentation has lead to an odd code structure.
> Still minor thing, so either way this looks fine to me.
> 
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> 
>> ---
>>  drivers/input/joystick/adc-joystick.c | 44 
>> +++++++++++++++++++++++++--
>>  1 file changed, 41 insertions(+), 3 deletions(-)
>> 
>> diff --git a/drivers/input/joystick/adc-joystick.c 
>> b/drivers/input/joystick/adc-joystick.c
>> index 78ebca7d400a..77dfb7dd96eb 100644
>> --- a/drivers/input/joystick/adc-joystick.c
>> +++ b/drivers/input/joystick/adc-joystick.c
>> @@ -26,8 +26,23 @@ struct adc_joystick {
>>  	struct adc_joystick_axis *axes;
>>  	struct iio_channel *chans;
>>  	int num_chans;
>> +	bool polled;
>>  };
>> 
>> +static void adc_joystick_poll(struct input_dev *input)
>> +{
>> +	struct adc_joystick *joy = input_get_drvdata(input);
>> +	int i, val, ret;
>> +
>> +	for (i = 0; i < joy->num_chans; i++) {
>> +		ret = iio_read_channel_raw(&joy->chans[i], &val);
>> +		if (ret < 0)
>> +			return;
>> +		input_report_abs(input, joy->axes[i].code, val);
>> +	}
>> +	input_sync(input);
>> +}
>> +
>>  static int adc_joystick_handle(const void *data, void *private)
>>  {
>>  	struct adc_joystick *joy = private;
>> @@ -179,6 +194,7 @@ static int adc_joystick_probe(struct 
>> platform_device *pdev)
>>  	int error;
>>  	int bits;
>>  	int i;
>> +	unsigned int poll_interval;
>> 
>>  	joy = devm_kzalloc(dev, sizeof(*joy), GFP_KERNEL);
>>  	if (!joy)
>> @@ -192,8 +208,21 @@ static int adc_joystick_probe(struct 
>> platform_device *pdev)
>>  		return error;
>>  	}
>> 
>> -	/* Count how many channels we got. NULL terminated. */
>> +	if (device_property_present(dev, "poll-interval")) {
>> +		error = device_property_read_u32(dev, "poll-interval",
>> +						 &poll_interval);
>> +		if (error)
>> +			return error;
>> +		joy->polled = true;
>> +	}
>> +
>> +	/*
>> +	 * Count how many channels we got. NULL terminated.
>> +	 * Do not check the storage size if using polling.
>> +	 */
>>  	for (i = 0; joy->chans[i].indio_dev; i++) {
>> +		if (joy->polled)
>> +			continue;
> 
> Whilst I can see why did this, it is a rather 'unusual' code structure
> and that makes me a tiny bit uncomfortable. However if everyone else
> is happy with this then fair enough (I see it was Artur's suggestion to
> handle it like this).
Yep, I'm fine with the way it is right now :)

Acked-by: Artur Rojek <contact@artur-rojek.eu>

> 
>>  		bits = joy->chans[i].channel->scan_type.storagebits;
>>  		if (!bits || bits > 16) {
>>  			dev_err(dev, "Unsupported channel storage size\n");
>> @@ -215,8 +244,14 @@ static int adc_joystick_probe(struct 
>> platform_device *pdev)
>>  	joy->input = input;
>>  	input->name = pdev->name;
>>  	input->id.bustype = BUS_HOST;
>> -	input->open = adc_joystick_open;
>> -	input->close = adc_joystick_close;
>> +
>> +	if (joy->polled) {
>> +		input_setup_polling(input, adc_joystick_poll);
>> +		input_set_poll_interval(input, poll_interval);
>> +	} else {
>> +		input->open = adc_joystick_open;
>> +		input->close = adc_joystick_close;
>> +	}
>> 
>>  	error = adc_joystick_set_axes(dev, joy);
>>  	if (error)
>> @@ -229,6 +264,9 @@ static int adc_joystick_probe(struct 
>> platform_device *pdev)
>>  		return error;
>>  	}
>> 
>> +	if (joy->polled)
>> +		return 0;
>> +
>>  	joy->buffer = iio_channel_get_all_cb(dev, adc_joystick_handle, joy);
>>  	if (IS_ERR(joy->buffer)) {
>>  		dev_err(dev, "Unable to allocate callback buffer\n");
Jonathan Cameron Aug. 6, 2022, 2:20 p.m. UTC | #2
On Fri,  5 Aug 2022 12:10:15 -0500
Chris Morgan <macroalpha82@gmail.com> wrote:

> From: Chris Morgan <macromorgan@hotmail.com>
> 
> Add polled input device support to the adc-joystick driver. This is
> useful for devices which do not have hardware capable triggers on
> their SARADC. Code modified from adc-joystick.c changes made by Maya
> Matuszczyk.
> 
> Signed-off-by: Maya Matuszczyk <maccraft123mc@gmail.com>
> Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
Hi Chris,

Trying to avoid too much indentation has lead to an odd code structure.
Still minor thing, so either way this looks fine to me.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

> ---
>  drivers/input/joystick/adc-joystick.c | 44 +++++++++++++++++++++++++--
>  1 file changed, 41 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/input/joystick/adc-joystick.c b/drivers/input/joystick/adc-joystick.c
> index 78ebca7d400a..77dfb7dd96eb 100644
> --- a/drivers/input/joystick/adc-joystick.c
> +++ b/drivers/input/joystick/adc-joystick.c
> @@ -26,8 +26,23 @@ struct adc_joystick {
>  	struct adc_joystick_axis *axes;
>  	struct iio_channel *chans;
>  	int num_chans;
> +	bool polled;
>  };
>  
> +static void adc_joystick_poll(struct input_dev *input)
> +{
> +	struct adc_joystick *joy = input_get_drvdata(input);
> +	int i, val, ret;
> +
> +	for (i = 0; i < joy->num_chans; i++) {
> +		ret = iio_read_channel_raw(&joy->chans[i], &val);
> +		if (ret < 0)
> +			return;
> +		input_report_abs(input, joy->axes[i].code, val);
> +	}
> +	input_sync(input);
> +}
> +
>  static int adc_joystick_handle(const void *data, void *private)
>  {
>  	struct adc_joystick *joy = private;
> @@ -179,6 +194,7 @@ static int adc_joystick_probe(struct platform_device *pdev)
>  	int error;
>  	int bits;
>  	int i;
> +	unsigned int poll_interval;
>  
>  	joy = devm_kzalloc(dev, sizeof(*joy), GFP_KERNEL);
>  	if (!joy)
> @@ -192,8 +208,21 @@ static int adc_joystick_probe(struct platform_device *pdev)
>  		return error;
>  	}
>  
> -	/* Count how many channels we got. NULL terminated. */
> +	if (device_property_present(dev, "poll-interval")) {
> +		error = device_property_read_u32(dev, "poll-interval",
> +						 &poll_interval);
> +		if (error)
> +			return error;
> +		joy->polled = true;
> +	}
> +
> +	/*
> +	 * Count how many channels we got. NULL terminated.
> +	 * Do not check the storage size if using polling.
> +	 */
>  	for (i = 0; joy->chans[i].indio_dev; i++) {
> +		if (joy->polled)
> +			continue;

Whilst I can see why did this, it is a rather 'unusual' code structure
and that makes me a tiny bit uncomfortable. However if everyone else
is happy with this then fair enough (I see it was Artur's suggestion to
handle it like this).

>  		bits = joy->chans[i].channel->scan_type.storagebits;
>  		if (!bits || bits > 16) {
>  			dev_err(dev, "Unsupported channel storage size\n");
> @@ -215,8 +244,14 @@ static int adc_joystick_probe(struct platform_device *pdev)
>  	joy->input = input;
>  	input->name = pdev->name;
>  	input->id.bustype = BUS_HOST;
> -	input->open = adc_joystick_open;
> -	input->close = adc_joystick_close;
> +
> +	if (joy->polled) {
> +		input_setup_polling(input, adc_joystick_poll);
> +		input_set_poll_interval(input, poll_interval);
> +	} else {
> +		input->open = adc_joystick_open;
> +		input->close = adc_joystick_close;
> +	}
>  
>  	error = adc_joystick_set_axes(dev, joy);
>  	if (error)
> @@ -229,6 +264,9 @@ static int adc_joystick_probe(struct platform_device *pdev)
>  		return error;
>  	}
>  
> +	if (joy->polled)
> +		return 0;
> +
>  	joy->buffer = iio_channel_get_all_cb(dev, adc_joystick_handle, joy);
>  	if (IS_ERR(joy->buffer)) {
>  		dev_err(dev, "Unable to allocate callback buffer\n");
Dmitry Torokhov Aug. 11, 2022, 12:58 a.m. UTC | #3
On Sat, Aug 06, 2022 at 04:19:21PM +0200, Artur Rojek wrote:
> On 2022-08-06 16:20, Jonathan Cameron wrote:
> > On Fri,  5 Aug 2022 12:10:15 -0500
> > Chris Morgan <macroalpha82@gmail.com> wrote:
> > 
> > > From: Chris Morgan <macromorgan@hotmail.com>
> > > 
> > > Add polled input device support to the adc-joystick driver. This is
> > > useful for devices which do not have hardware capable triggers on
> > > their SARADC. Code modified from adc-joystick.c changes made by Maya
> > > Matuszczyk.
> > > 
> > > Signed-off-by: Maya Matuszczyk <maccraft123mc@gmail.com>
> > > Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
> > Hi Chris,
> > 
> > Trying to avoid too much indentation has lead to an odd code structure.
> > Still minor thing, so either way this looks fine to me.
> > 
> > Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> > 
> > > ---
> > >  drivers/input/joystick/adc-joystick.c | 44
> > > +++++++++++++++++++++++++--
> > >  1 file changed, 41 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/drivers/input/joystick/adc-joystick.c
> > > b/drivers/input/joystick/adc-joystick.c
> > > index 78ebca7d400a..77dfb7dd96eb 100644
> > > --- a/drivers/input/joystick/adc-joystick.c
> > > +++ b/drivers/input/joystick/adc-joystick.c
> > > @@ -26,8 +26,23 @@ struct adc_joystick {
> > >  	struct adc_joystick_axis *axes;
> > >  	struct iio_channel *chans;
> > >  	int num_chans;
> > > +	bool polled;
> > >  };
> > > 
> > > +static void adc_joystick_poll(struct input_dev *input)
> > > +{
> > > +	struct adc_joystick *joy = input_get_drvdata(input);
> > > +	int i, val, ret;
> > > +
> > > +	for (i = 0; i < joy->num_chans; i++) {
> > > +		ret = iio_read_channel_raw(&joy->chans[i], &val);
> > > +		if (ret < 0)
> > > +			return;
> > > +		input_report_abs(input, joy->axes[i].code, val);
> > > +	}
> > > +	input_sync(input);
> > > +}
> > > +
> > >  static int adc_joystick_handle(const void *data, void *private)
> > >  {
> > >  	struct adc_joystick *joy = private;
> > > @@ -179,6 +194,7 @@ static int adc_joystick_probe(struct
> > > platform_device *pdev)
> > >  	int error;
> > >  	int bits;
> > >  	int i;
> > > +	unsigned int poll_interval;
> > > 
> > >  	joy = devm_kzalloc(dev, sizeof(*joy), GFP_KERNEL);
> > >  	if (!joy)
> > > @@ -192,8 +208,21 @@ static int adc_joystick_probe(struct
> > > platform_device *pdev)
> > >  		return error;
> > >  	}
> > > 
> > > -	/* Count how many channels we got. NULL terminated. */
> > > +	if (device_property_present(dev, "poll-interval")) {
> > > +		error = device_property_read_u32(dev, "poll-interval",
> > > +						 &poll_interval);
> > > +		if (error)
> > > +			return error;
> > > +		joy->polled = true;


device_property_read_u32() return -EINVAL if property is not present, so
we can write:

	error = device_property_read_u32(dev, "poll-interval", &poll_interval);
	if (error) {
		/* -EINVAL means the property is absent. */
		if (error != -EINVAL)
			return error;
	} else if (poll_interval == 0) {
		dev_err(...);
		return -EINVAL;
	} else {
		joy->polled = true;
	}

> > > +	}
> > > +
> > > +	/*
> > > +	 * Count how many channels we got. NULL terminated.
> > > +	 * Do not check the storage size if using polling.
> > > +	 */
> > >  	for (i = 0; joy->chans[i].indio_dev; i++) {
> > > +		if (joy->polled)
> > > +			continue;
> > 
> > Whilst I can see why did this, it is a rather 'unusual' code structure
> > and that makes me a tiny bit uncomfortable. However if everyone else
> > is happy with this then fair enough (I see it was Artur's suggestion to
> > handle it like this).
> Yep, I'm fine with the way it is right now :)
> 
> Acked-by: Artur Rojek <contact@artur-rojek.eu>
> 
> > 
> > >  		bits = joy->chans[i].channel->scan_type.storagebits;
> > >  		if (!bits || bits > 16) {
> > >  			dev_err(dev, "Unsupported channel storage size\n");
> > > @@ -215,8 +244,14 @@ static int adc_joystick_probe(struct
> > > platform_device *pdev)
> > >  	joy->input = input;
> > >  	input->name = pdev->name;
> > >  	input->id.bustype = BUS_HOST;
> > > -	input->open = adc_joystick_open;
> > > -	input->close = adc_joystick_close;
> > > +
> > > +	if (joy->polled) {
> > > +		input_setup_polling(input, adc_joystick_poll);
> > > +		input_set_poll_interval(input, poll_interval);
> > > +	} else {
> > > +		input->open = adc_joystick_open;
> > > +		input->close = adc_joystick_close;
> > > +	}
> > > 
> > >  	error = adc_joystick_set_axes(dev, joy);
> > >  	if (error)
> > > @@ -229,6 +264,9 @@ static int adc_joystick_probe(struct
> > > platform_device *pdev)
> > >  		return error;
> > >  	}
> > > 
> > > +	if (joy->polled)
> > > +		return 0;
> > > +

This is no longer compatible with the latest driver code as input device
registration has been moved to the very end, so you actually need to move
getting bugger and setting up cleanup action into the "else" clause of "if
(joy->polled)", even though it adds indentation level.

> > >  	joy->buffer = iio_channel_get_all_cb(dev, adc_joystick_handle, joy);
> > >  	if (IS_ERR(joy->buffer)) {
> > >  		dev_err(dev, "Unable to allocate callback buffer\n");

Thanks.
Chris Morgan Aug. 12, 2022, 2:56 p.m. UTC | #4
On Wed, Aug 10, 2022 at 05:58:48PM -0700, Dmitry Torokhov wrote:
> On Sat, Aug 06, 2022 at 04:19:21PM +0200, Artur Rojek wrote:
> > On 2022-08-06 16:20, Jonathan Cameron wrote:
> > > On Fri,  5 Aug 2022 12:10:15 -0500
> > > Chris Morgan <macroalpha82@gmail.com> wrote:
> > > 
> > > > From: Chris Morgan <macromorgan@hotmail.com>
> > > > 
> > > > Add polled input device support to the adc-joystick driver. This is
> > > > useful for devices which do not have hardware capable triggers on
> > > > their SARADC. Code modified from adc-joystick.c changes made by Maya
> > > > Matuszczyk.
> > > > 
> > > > Signed-off-by: Maya Matuszczyk <maccraft123mc@gmail.com>
> > > > Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
> > > Hi Chris,
> > > 
> > > Trying to avoid too much indentation has lead to an odd code structure.
> > > Still minor thing, so either way this looks fine to me.
> > > 
> > > Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> > > 
> > > > ---
> > > >  drivers/input/joystick/adc-joystick.c | 44
> > > > +++++++++++++++++++++++++--
> > > >  1 file changed, 41 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/drivers/input/joystick/adc-joystick.c
> > > > b/drivers/input/joystick/adc-joystick.c
> > > > index 78ebca7d400a..77dfb7dd96eb 100644
> > > > --- a/drivers/input/joystick/adc-joystick.c
> > > > +++ b/drivers/input/joystick/adc-joystick.c
> > > > @@ -26,8 +26,23 @@ struct adc_joystick {
> > > >  	struct adc_joystick_axis *axes;
> > > >  	struct iio_channel *chans;
> > > >  	int num_chans;
> > > > +	bool polled;
> > > >  };
> > > > 
> > > > +static void adc_joystick_poll(struct input_dev *input)
> > > > +{
> > > > +	struct adc_joystick *joy = input_get_drvdata(input);
> > > > +	int i, val, ret;
> > > > +
> > > > +	for (i = 0; i < joy->num_chans; i++) {
> > > > +		ret = iio_read_channel_raw(&joy->chans[i], &val);
> > > > +		if (ret < 0)
> > > > +			return;
> > > > +		input_report_abs(input, joy->axes[i].code, val);
> > > > +	}
> > > > +	input_sync(input);
> > > > +}
> > > > +
> > > >  static int adc_joystick_handle(const void *data, void *private)
> > > >  {
> > > >  	struct adc_joystick *joy = private;
> > > > @@ -179,6 +194,7 @@ static int adc_joystick_probe(struct
> > > > platform_device *pdev)
> > > >  	int error;
> > > >  	int bits;
> > > >  	int i;
> > > > +	unsigned int poll_interval;
> > > > 
> > > >  	joy = devm_kzalloc(dev, sizeof(*joy), GFP_KERNEL);
> > > >  	if (!joy)
> > > > @@ -192,8 +208,21 @@ static int adc_joystick_probe(struct
> > > > platform_device *pdev)
> > > >  		return error;
> > > >  	}
> > > > 
> > > > -	/* Count how many channels we got. NULL terminated. */
> > > > +	if (device_property_present(dev, "poll-interval")) {
> > > > +		error = device_property_read_u32(dev, "poll-interval",
> > > > +						 &poll_interval);
> > > > +		if (error)
> > > > +			return error;
> > > > +		joy->polled = true;
> 
> 
> device_property_read_u32() return -EINVAL if property is not present, so
> we can write:

Understood. Both ways can work but when I do the next revision I'll change it
to this.

> 
> 	error = device_property_read_u32(dev, "poll-interval", &poll_interval);
> 	if (error) {
> 		/* -EINVAL means the property is absent. */
> 		if (error != -EINVAL)
> 			return error;
> 	} else if (poll_interval == 0) {
> 		dev_err(...);
> 		return -EINVAL;
> 	} else {
> 		joy->polled = true;
> 	}
> 
> > > > +	}
> > > > +
> > > > +	/*
> > > > +	 * Count how many channels we got. NULL terminated.
> > > > +	 * Do not check the storage size if using polling.
> > > > +	 */
> > > >  	for (i = 0; joy->chans[i].indio_dev; i++) {
> > > > +		if (joy->polled)
> > > > +			continue;
> > > 
> > > Whilst I can see why did this, it is a rather 'unusual' code structure
> > > and that makes me a tiny bit uncomfortable. However if everyone else
> > > is happy with this then fair enough (I see it was Artur's suggestion to
> > > handle it like this).
> > Yep, I'm fine with the way it is right now :)
> > 
> > Acked-by: Artur Rojek <contact@artur-rojek.eu>
> > 
> > > 
> > > >  		bits = joy->chans[i].channel->scan_type.storagebits;
> > > >  		if (!bits || bits > 16) {
> > > >  			dev_err(dev, "Unsupported channel storage size\n");
> > > > @@ -215,8 +244,14 @@ static int adc_joystick_probe(struct
> > > > platform_device *pdev)
> > > >  	joy->input = input;
> > > >  	input->name = pdev->name;
> > > >  	input->id.bustype = BUS_HOST;
> > > > -	input->open = adc_joystick_open;
> > > > -	input->close = adc_joystick_close;
> > > > +
> > > > +	if (joy->polled) {
> > > > +		input_setup_polling(input, adc_joystick_poll);
> > > > +		input_set_poll_interval(input, poll_interval);
> > > > +	} else {
> > > > +		input->open = adc_joystick_open;
> > > > +		input->close = adc_joystick_close;
> > > > +	}
> > > > 
> > > >  	error = adc_joystick_set_axes(dev, joy);
> > > >  	if (error)
> > > > @@ -229,6 +264,9 @@ static int adc_joystick_probe(struct
> > > > platform_device *pdev)
> > > >  		return error;
> > > >  	}
> > > > 
> > > > +	if (joy->polled)
> > > > +		return 0;
> > > > +
> 
> This is no longer compatible with the latest driver code as input device
> registration has been moved to the very end, so you actually need to move
> getting bugger and setting up cleanup action into the "else" clause of "if
> (joy->polled)", even though it adds indentation level.

I'm afraid I don't understand the issue you are describing.
input_register_device is called before this section, and since it's allocated
with devm we shouldn't need to clean it up in the event of an error, right?
The two functions below this line (including the one establishing the
joystick cleanup) are only required for non-polled devices.

Thank you.

> 
> > > >  	joy->buffer = iio_channel_get_all_cb(dev, adc_joystick_handle, joy);
> > > >  	if (IS_ERR(joy->buffer)) {
> > > >  		dev_err(dev, "Unable to allocate callback buffer\n");
> 
> Thanks.
> 
> -- 
> Dmitry
diff mbox series

Patch

diff --git a/drivers/input/joystick/adc-joystick.c b/drivers/input/joystick/adc-joystick.c
index 78ebca7d400a..77dfb7dd96eb 100644
--- a/drivers/input/joystick/adc-joystick.c
+++ b/drivers/input/joystick/adc-joystick.c
@@ -26,8 +26,23 @@  struct adc_joystick {
 	struct adc_joystick_axis *axes;
 	struct iio_channel *chans;
 	int num_chans;
+	bool polled;
 };
 
+static void adc_joystick_poll(struct input_dev *input)
+{
+	struct adc_joystick *joy = input_get_drvdata(input);
+	int i, val, ret;
+
+	for (i = 0; i < joy->num_chans; i++) {
+		ret = iio_read_channel_raw(&joy->chans[i], &val);
+		if (ret < 0)
+			return;
+		input_report_abs(input, joy->axes[i].code, val);
+	}
+	input_sync(input);
+}
+
 static int adc_joystick_handle(const void *data, void *private)
 {
 	struct adc_joystick *joy = private;
@@ -179,6 +194,7 @@  static int adc_joystick_probe(struct platform_device *pdev)
 	int error;
 	int bits;
 	int i;
+	unsigned int poll_interval;
 
 	joy = devm_kzalloc(dev, sizeof(*joy), GFP_KERNEL);
 	if (!joy)
@@ -192,8 +208,21 @@  static int adc_joystick_probe(struct platform_device *pdev)
 		return error;
 	}
 
-	/* Count how many channels we got. NULL terminated. */
+	if (device_property_present(dev, "poll-interval")) {
+		error = device_property_read_u32(dev, "poll-interval",
+						 &poll_interval);
+		if (error)
+			return error;
+		joy->polled = true;
+	}
+
+	/*
+	 * Count how many channels we got. NULL terminated.
+	 * Do not check the storage size if using polling.
+	 */
 	for (i = 0; joy->chans[i].indio_dev; i++) {
+		if (joy->polled)
+			continue;
 		bits = joy->chans[i].channel->scan_type.storagebits;
 		if (!bits || bits > 16) {
 			dev_err(dev, "Unsupported channel storage size\n");
@@ -215,8 +244,14 @@  static int adc_joystick_probe(struct platform_device *pdev)
 	joy->input = input;
 	input->name = pdev->name;
 	input->id.bustype = BUS_HOST;
-	input->open = adc_joystick_open;
-	input->close = adc_joystick_close;
+
+	if (joy->polled) {
+		input_setup_polling(input, adc_joystick_poll);
+		input_set_poll_interval(input, poll_interval);
+	} else {
+		input->open = adc_joystick_open;
+		input->close = adc_joystick_close;
+	}
 
 	error = adc_joystick_set_axes(dev, joy);
 	if (error)
@@ -229,6 +264,9 @@  static int adc_joystick_probe(struct platform_device *pdev)
 		return error;
 	}
 
+	if (joy->polled)
+		return 0;
+
 	joy->buffer = iio_channel_get_all_cb(dev, adc_joystick_handle, joy);
 	if (IS_ERR(joy->buffer)) {
 		dev_err(dev, "Unable to allocate callback buffer\n");