Skip to content

Commit ae6d9ce

Browse files
Martin Fuzzeyjic23
authored andcommitted
iio: mma8452: Add support for interrupt driven triggers.
Implement interrupt driven trigger for data ready. This allows more efficient access to the sample data. Signed-off-by: Martin Fuzzey <mfuzzey@parkeon.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
1 parent 1e79841 commit ae6d9ce

File tree

1 file changed

+91
-6
lines changed

1 file changed

+91
-6
lines changed

drivers/iio/accel/mma8452.c

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <linux/iio/sysfs.h>
1919
#include <linux/iio/trigger_consumer.h>
2020
#include <linux/iio/buffer.h>
21+
#include <linux/iio/trigger.h>
22+
#include <linux/iio/trigger_consumer.h>
2123
#include <linux/iio/triggered_buffer.h>
2224
#include <linux/iio/events.h>
2325
#include <linux/delay.h>
@@ -66,6 +68,7 @@
6668
#define MMA8452_DATA_CFG_FS_8G 2
6769
#define MMA8452_DATA_CFG_HPF_MASK BIT(4)
6870

71+
#define MMA8452_INT_DRDY BIT(0)
6972
#define MMA8452_INT_TRANS BIT(5)
7073

7174
#define MMA8452_DEVICE_ID 0x2a
@@ -577,18 +580,24 @@ static irqreturn_t mma8452_interrupt(int irq, void *p)
577580
{
578581
struct iio_dev *indio_dev = p;
579582
struct mma8452_data *data = iio_priv(indio_dev);
583+
int ret = IRQ_NONE;
580584
int src;
581585

582586
src = i2c_smbus_read_byte_data(data->client, MMA8452_INT_SRC);
583587
if (src < 0)
584588
return IRQ_NONE;
585589

590+
if (src & MMA8452_INT_DRDY) {
591+
iio_trigger_poll_chained(indio_dev->trig);
592+
ret = IRQ_HANDLED;
593+
}
594+
586595
if (src & MMA8452_INT_TRANS) {
587596
mma8452_transient_interrupt(indio_dev);
588-
return IRQ_HANDLED;
597+
ret = IRQ_HANDLED;
589598
}
590599

591-
return IRQ_NONE;
600+
return ret;
592601
}
593602

594603
static irqreturn_t mma8452_trigger_handler(int irq, void *p)
@@ -714,6 +723,72 @@ static const struct iio_info mma8452_info = {
714723

715724
static const unsigned long mma8452_scan_masks[] = {0x7, 0};
716725

726+
static int mma8452_data_rdy_trigger_set_state(struct iio_trigger *trig,
727+
bool state)
728+
{
729+
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
730+
struct mma8452_data *data = iio_priv(indio_dev);
731+
int reg;
732+
733+
reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG4);
734+
if (reg < 0)
735+
return reg;
736+
737+
if (state)
738+
reg |= MMA8452_INT_DRDY;
739+
else
740+
reg &= ~MMA8452_INT_DRDY;
741+
742+
return mma8452_change_config(data, MMA8452_CTRL_REG4, reg);
743+
}
744+
745+
static int mma8452_validate_device(struct iio_trigger *trig,
746+
struct iio_dev *indio_dev)
747+
{
748+
struct iio_dev *indio = iio_trigger_get_drvdata(trig);
749+
750+
if (indio != indio_dev)
751+
return -EINVAL;
752+
753+
return 0;
754+
}
755+
756+
static const struct iio_trigger_ops mma8452_trigger_ops = {
757+
.set_trigger_state = mma8452_data_rdy_trigger_set_state,
758+
.validate_device = mma8452_validate_device,
759+
.owner = THIS_MODULE,
760+
};
761+
762+
static int mma8452_trigger_setup(struct iio_dev *indio_dev)
763+
{
764+
struct mma8452_data *data = iio_priv(indio_dev);
765+
struct iio_trigger *trig;
766+
int ret;
767+
768+
trig = devm_iio_trigger_alloc(&data->client->dev, "%s-dev%d",
769+
indio_dev->name,
770+
indio_dev->id);
771+
if (!trig)
772+
return -ENOMEM;
773+
774+
trig->dev.parent = &data->client->dev;
775+
trig->ops = &mma8452_trigger_ops;
776+
iio_trigger_set_drvdata(trig, indio_dev);
777+
778+
ret = iio_trigger_register(trig);
779+
if (ret)
780+
return ret;
781+
782+
indio_dev->trig = trig;
783+
return 0;
784+
}
785+
786+
static void mma8452_trigger_cleanup(struct iio_dev *indio_dev)
787+
{
788+
if (indio_dev->trig)
789+
iio_trigger_unregister(indio_dev->trig);
790+
}
791+
717792
static int mma8452_reset(struct i2c_client *client)
718793
{
719794
int i;
@@ -794,7 +869,8 @@ static int mma8452_probe(struct i2c_client *client,
794869
* enabled until userspace asks for it by
795870
* mma8452_write_event_config()
796871
*/
797-
int supported_interrupts = MMA8452_INT_TRANS;
872+
int supported_interrupts = MMA8452_INT_DRDY | MMA8452_INT_TRANS;
873+
int enabled_interrupts = MMA8452_INT_TRANS;
798874

799875
/* Assume wired to INT1 pin */
800876
ret = i2c_smbus_write_byte_data(client,
@@ -805,7 +881,11 @@ static int mma8452_probe(struct i2c_client *client,
805881

806882
ret = i2c_smbus_write_byte_data(client,
807883
MMA8452_CTRL_REG4,
808-
supported_interrupts);
884+
enabled_interrupts);
885+
if (ret < 0)
886+
return ret;
887+
888+
ret = mma8452_trigger_setup(indio_dev);
809889
if (ret < 0)
810890
return ret;
811891
}
@@ -815,12 +895,12 @@ static int mma8452_probe(struct i2c_client *client,
815895
ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1,
816896
data->ctrl_reg1);
817897
if (ret < 0)
818-
return ret;
898+
goto trigger_cleanup;
819899

820900
ret = iio_triggered_buffer_setup(indio_dev, NULL,
821901
mma8452_trigger_handler, NULL);
822902
if (ret < 0)
823-
return ret;
903+
goto trigger_cleanup;
824904

825905
if (client->irq) {
826906
ret = devm_request_threaded_irq(&client->dev,
@@ -840,6 +920,10 @@ static int mma8452_probe(struct i2c_client *client,
840920

841921
buffer_cleanup:
842922
iio_triggered_buffer_cleanup(indio_dev);
923+
924+
trigger_cleanup:
925+
mma8452_trigger_cleanup(indio_dev);
926+
843927
return ret;
844928
}
845929

@@ -849,6 +933,7 @@ static int mma8452_remove(struct i2c_client *client)
849933

850934
iio_device_unregister(indio_dev);
851935
iio_triggered_buffer_cleanup(indio_dev);
936+
mma8452_trigger_cleanup(indio_dev);
852937
mma8452_standby(iio_priv(indio_dev));
853938

854939
return 0;

0 commit comments

Comments
 (0)