diff options
author | Daniel Baluta <daniel.baluta@intel.com> | 2014-12-03 08:31:52 -0500 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2014-12-12 08:49:30 -0500 |
commit | c3a23ecc0901f624b681bbfbc4829766c5aa3070 (patch) | |
tree | 207836cf892c6afdf135946fdc819165beb5c9df /drivers/iio | |
parent | 3b9c40e604ee61e69a8aff6e1a426a6250ff4361 (diff) |
iio: imu: kmx61: Add support for data ready triggers
This creates a data ready trigger per IIO device.
Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/imu/Kconfig | 2 | ||||
-rw-r--r-- | drivers/iio/imu/kmx61.c | 295 |
2 files changed, 296 insertions, 1 deletions
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index db4221db10f2..5e610f7de5aa 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig | |||
@@ -28,6 +28,8 @@ config ADIS16480 | |||
28 | config KMX61 | 28 | config KMX61 |
29 | tristate "Kionix KMX61 6-axis accelerometer and magnetometer" | 29 | tristate "Kionix KMX61 6-axis accelerometer and magnetometer" |
30 | depends on I2C | 30 | depends on I2C |
31 | select IIO_BUFFER | ||
32 | select IIO_TRIGGERED_BUFFER | ||
31 | help | 33 | help |
32 | Say Y here if you want to build a driver for Kionix KMX61 6-axis | 34 | Say Y here if you want to build a driver for Kionix KMX61 6-axis |
33 | accelerometer and magnetometer. | 35 | accelerometer and magnetometer. |
diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 98d58e1b6c6b..b8080fc54a76 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c | |||
@@ -20,9 +20,14 @@ | |||
20 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
21 | #include <linux/iio/iio.h> | 21 | #include <linux/iio/iio.h> |
22 | #include <linux/iio/sysfs.h> | 22 | #include <linux/iio/sysfs.h> |
23 | #include <linux/iio/trigger.h> | ||
24 | #include <linux/iio/buffer.h> | ||
25 | #include <linux/iio/triggered_buffer.h> | ||
26 | #include <linux/iio/trigger_consumer.h> | ||
23 | 27 | ||
24 | #define KMX61_DRV_NAME "kmx61" | 28 | #define KMX61_DRV_NAME "kmx61" |
25 | #define KMX61_GPIO_NAME "kmx61_int" | 29 | #define KMX61_GPIO_NAME "kmx61_int" |
30 | #define KMX61_IRQ_NAME "kmx61_event" | ||
26 | 31 | ||
27 | #define KMX61_REG_WHO_AM_I 0x00 | 32 | #define KMX61_REG_WHO_AM_I 0x00 |
28 | 33 | ||
@@ -55,9 +60,11 @@ | |||
55 | #define KMX61_MAG_ZOUT_L 0x16 | 60 | #define KMX61_MAG_ZOUT_L 0x16 |
56 | #define KMX61_MAG_ZOUT_H 0x17 | 61 | #define KMX61_MAG_ZOUT_H 0x17 |
57 | 62 | ||
63 | #define KMX61_REG_INL 0x28 | ||
58 | #define KMX61_REG_STBY 0x29 | 64 | #define KMX61_REG_STBY 0x29 |
59 | #define KMX61_REG_CTRL1 0x2A | 65 | #define KMX61_REG_CTRL1 0x2A |
60 | #define KMX61_REG_ODCNTL 0x2C | 66 | #define KMX61_REG_ODCNTL 0x2C |
67 | #define KMX61_REG_INC1 0x2D | ||
61 | 68 | ||
62 | #define KMX61_ACC_STBY_BIT BIT(0) | 69 | #define KMX61_ACC_STBY_BIT BIT(0) |
63 | #define KMX61_MAG_STBY_BIT BIT(1) | 70 | #define KMX61_MAG_STBY_BIT BIT(1) |
@@ -67,6 +74,13 @@ | |||
67 | 74 | ||
68 | #define KMX61_REG_CTRL1_GSEL_MASK 0x03 | 75 | #define KMX61_REG_CTRL1_GSEL_MASK 0x03 |
69 | 76 | ||
77 | #define KMX61_REG_CTRL1_BIT_RES BIT(4) | ||
78 | #define KMX61_REG_CTRL1_BIT_DRDYE BIT(5) | ||
79 | |||
80 | #define KMX61_REG_INC1_BIT_DRDYM BIT(1) | ||
81 | #define KMX61_REG_INC1_BIT_DRDYA BIT(2) | ||
82 | #define KMX61_REG_INC1_BIT_IEN BIT(5) | ||
83 | |||
70 | #define KMX61_ACC_ODR_SHIFT 0 | 84 | #define KMX61_ACC_ODR_SHIFT 0 |
71 | #define KMX61_MAG_ODR_SHIFT 4 | 85 | #define KMX61_MAG_ODR_SHIFT 4 |
72 | #define KMX61_ACC_ODR_MASK 0x0F | 86 | #define KMX61_ACC_ODR_MASK 0x0F |
@@ -100,9 +114,13 @@ struct kmx61_data { | |||
100 | 114 | ||
101 | /* accelerometer specific data */ | 115 | /* accelerometer specific data */ |
102 | struct iio_dev *acc_indio_dev; | 116 | struct iio_dev *acc_indio_dev; |
117 | struct iio_trigger *acc_dready_trig; | ||
118 | bool acc_dready_trig_on; | ||
103 | 119 | ||
104 | /* magnetometer specific data */ | 120 | /* magnetometer specific data */ |
105 | struct iio_dev *mag_indio_dev; | 121 | struct iio_dev *mag_indio_dev; |
122 | struct iio_trigger *mag_dready_trig; | ||
123 | bool mag_dready_trig_on; | ||
106 | }; | 124 | }; |
107 | 125 | ||
108 | enum kmx61_range { | 126 | enum kmx61_range { |
@@ -466,6 +484,69 @@ static int kmx61_chip_init(struct kmx61_data *data) | |||
466 | return 0; | 484 | return 0; |
467 | } | 485 | } |
468 | 486 | ||
487 | static int kmx61_setup_new_data_interrupt(struct kmx61_data *data, | ||
488 | bool status, u8 device) | ||
489 | { | ||
490 | u8 mode; | ||
491 | int ret; | ||
492 | |||
493 | ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); | ||
494 | if (ret < 0) | ||
495 | return ret; | ||
496 | |||
497 | ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); | ||
498 | if (ret < 0) | ||
499 | return ret; | ||
500 | |||
501 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1); | ||
502 | if (ret < 0) { | ||
503 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | ||
504 | return ret; | ||
505 | } | ||
506 | |||
507 | if (status) { | ||
508 | ret |= KMX61_REG_INC1_BIT_IEN; | ||
509 | if (device & KMX61_ACC) | ||
510 | ret |= KMX61_REG_INC1_BIT_DRDYA; | ||
511 | if (device & KMX61_MAG) | ||
512 | ret |= KMX61_REG_INC1_BIT_DRDYM; | ||
513 | } else { | ||
514 | ret &= ~KMX61_REG_INC1_BIT_IEN; | ||
515 | if (device & KMX61_ACC) | ||
516 | ret &= ~KMX61_REG_INC1_BIT_DRDYA; | ||
517 | if (device & KMX61_MAG) | ||
518 | ret &= ~KMX61_REG_INC1_BIT_DRDYM; | ||
519 | } | ||
520 | ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret); | ||
521 | if (ret < 0) { | ||
522 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); | ||
523 | return ret; | ||
524 | } | ||
525 | |||
526 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); | ||
527 | if (ret < 0) { | ||
528 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | ||
529 | return ret; | ||
530 | } | ||
531 | |||
532 | if (status) | ||
533 | ret |= KMX61_REG_CTRL1_BIT_DRDYE; | ||
534 | else | ||
535 | ret &= ~KMX61_REG_CTRL1_BIT_DRDYE; | ||
536 | |||
537 | ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); | ||
538 | if (ret < 0) { | ||
539 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); | ||
540 | return ret; | ||
541 | } | ||
542 | |||
543 | ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); | ||
544 | if (ret) | ||
545 | return ret; | ||
546 | |||
547 | return 0; | ||
548 | } | ||
549 | |||
469 | /** | 550 | /** |
470 | * kmx61_set_power_state() - set power state for kmx61 @device | 551 | * kmx61_set_power_state() - set power state for kmx61 @device |
471 | * @data - kmx61 device private pointer | 552 | * @data - kmx61 device private pointer |
@@ -626,11 +707,34 @@ static int kmx61_write_raw(struct iio_dev *indio_dev, | |||
626 | } | 707 | } |
627 | } | 708 | } |
628 | 709 | ||
710 | static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev, | ||
711 | struct iio_trigger *trig) | ||
712 | { | ||
713 | struct kmx61_data *data = kmx61_get_data(indio_dev); | ||
714 | |||
715 | if (data->acc_dready_trig != trig) | ||
716 | return -EINVAL; | ||
717 | |||
718 | return 0; | ||
719 | } | ||
720 | |||
721 | static int kmx61_mag_validate_trigger(struct iio_dev *indio_dev, | ||
722 | struct iio_trigger *trig) | ||
723 | { | ||
724 | struct kmx61_data *data = kmx61_get_data(indio_dev); | ||
725 | |||
726 | if (data->mag_dready_trig != trig) | ||
727 | return -EINVAL; | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
629 | static const struct iio_info kmx61_acc_info = { | 732 | static const struct iio_info kmx61_acc_info = { |
630 | .driver_module = THIS_MODULE, | 733 | .driver_module = THIS_MODULE, |
631 | .read_raw = kmx61_read_raw, | 734 | .read_raw = kmx61_read_raw, |
632 | .write_raw = kmx61_write_raw, | 735 | .write_raw = kmx61_write_raw, |
633 | .attrs = &kmx61_acc_attribute_group, | 736 | .attrs = &kmx61_acc_attribute_group, |
737 | .validate_trigger = kmx61_acc_validate_trigger, | ||
634 | }; | 738 | }; |
635 | 739 | ||
636 | static const struct iio_info kmx61_mag_info = { | 740 | static const struct iio_info kmx61_mag_info = { |
@@ -638,8 +742,109 @@ static const struct iio_info kmx61_mag_info = { | |||
638 | .read_raw = kmx61_read_raw, | 742 | .read_raw = kmx61_read_raw, |
639 | .write_raw = kmx61_write_raw, | 743 | .write_raw = kmx61_write_raw, |
640 | .attrs = &kmx61_mag_attribute_group, | 744 | .attrs = &kmx61_mag_attribute_group, |
745 | .validate_trigger = kmx61_mag_validate_trigger, | ||
746 | }; | ||
747 | |||
748 | |||
749 | static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, | ||
750 | bool state) | ||
751 | { | ||
752 | int ret = 0; | ||
753 | u8 device; | ||
754 | |||
755 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | ||
756 | struct kmx61_data *data = iio_priv(indio_dev); | ||
757 | |||
758 | mutex_lock(&data->lock); | ||
759 | |||
760 | if (data->acc_dready_trig == trig) | ||
761 | device = KMX61_ACC; | ||
762 | else | ||
763 | device = KMX61_MAG; | ||
764 | |||
765 | ret = kmx61_set_power_state(data, state, device); | ||
766 | if (ret < 0) { | ||
767 | mutex_unlock(&data->lock); | ||
768 | return ret; | ||
769 | } | ||
770 | |||
771 | ret = kmx61_setup_new_data_interrupt(data, state, device); | ||
772 | if (ret < 0) { | ||
773 | kmx61_set_power_state(data, false, device); | ||
774 | mutex_unlock(&data->lock); | ||
775 | return ret; | ||
776 | } | ||
777 | |||
778 | if (data->acc_dready_trig == trig) | ||
779 | data->acc_dready_trig_on = state; | ||
780 | else | ||
781 | data->mag_dready_trig_on = state; | ||
782 | |||
783 | mutex_unlock(&data->lock); | ||
784 | |||
785 | return 0; | ||
786 | } | ||
787 | |||
788 | static int kmx61_trig_try_reenable(struct iio_trigger *trig) | ||
789 | { | ||
790 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | ||
791 | struct kmx61_data *data = kmx61_get_data(indio_dev); | ||
792 | int ret; | ||
793 | |||
794 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL); | ||
795 | if (ret < 0) { | ||
796 | dev_err(&data->client->dev, "Error reading reg_inl\n"); | ||
797 | return ret; | ||
798 | } | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static const struct iio_trigger_ops kmx61_trigger_ops = { | ||
804 | .set_trigger_state = kmx61_data_rdy_trigger_set_state, | ||
805 | .try_reenable = kmx61_trig_try_reenable, | ||
806 | .owner = THIS_MODULE, | ||
641 | }; | 807 | }; |
642 | 808 | ||
809 | static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) | ||
810 | { | ||
811 | struct kmx61_data *data = private; | ||
812 | |||
813 | if (data->acc_dready_trig_on) | ||
814 | iio_trigger_poll(data->acc_dready_trig); | ||
815 | if (data->mag_dready_trig_on) | ||
816 | iio_trigger_poll(data->mag_dready_trig); | ||
817 | |||
818 | return IRQ_HANDLED; | ||
819 | } | ||
820 | |||
821 | static irqreturn_t kmx61_trigger_handler(int irq, void *p) | ||
822 | { | ||
823 | struct iio_poll_func *pf = p; | ||
824 | struct iio_dev *indio_dev = pf->indio_dev; | ||
825 | struct kmx61_data *data = kmx61_get_data(indio_dev); | ||
826 | int bit, ret, i = 0; | ||
827 | s16 buffer[8]; | ||
828 | |||
829 | mutex_lock(&data->lock); | ||
830 | for_each_set_bit(bit, indio_dev->buffer->scan_mask, | ||
831 | indio_dev->masklength) { | ||
832 | ret = kmx61_read_measurement(data, KMX61_ACC_XOUT_L, bit); | ||
833 | if (ret < 0) { | ||
834 | mutex_unlock(&data->lock); | ||
835 | goto err; | ||
836 | } | ||
837 | buffer[i++] = ret; | ||
838 | } | ||
839 | mutex_unlock(&data->lock); | ||
840 | |||
841 | iio_push_to_buffers(indio_dev, buffer); | ||
842 | err: | ||
843 | iio_trigger_notify_done(indio_dev->trig); | ||
844 | |||
845 | return IRQ_HANDLED; | ||
846 | } | ||
847 | |||
643 | static const char *kmx61_match_acpi_device(struct device *dev) | 848 | static const char *kmx61_match_acpi_device(struct device *dev) |
644 | { | 849 | { |
645 | const struct acpi_device_id *id; | 850 | const struct acpi_device_id *id; |
@@ -702,6 +907,32 @@ static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data, | |||
702 | return indio_dev; | 907 | return indio_dev; |
703 | } | 908 | } |
704 | 909 | ||
910 | static struct iio_trigger *kmx61_trigger_setup(struct kmx61_data *data, | ||
911 | struct iio_dev *indio_dev, | ||
912 | const char *tag) | ||
913 | { | ||
914 | struct iio_trigger *trig; | ||
915 | int ret; | ||
916 | |||
917 | trig = devm_iio_trigger_alloc(&data->client->dev, | ||
918 | "%s-%s-dev%d", | ||
919 | indio_dev->name, | ||
920 | tag, | ||
921 | indio_dev->id); | ||
922 | if (!trig) | ||
923 | return ERR_PTR(-ENOMEM); | ||
924 | |||
925 | trig->dev.parent = &data->client->dev; | ||
926 | trig->ops = &kmx61_trigger_ops; | ||
927 | iio_trigger_set_drvdata(trig, indio_dev); | ||
928 | |||
929 | ret = iio_trigger_register(trig); | ||
930 | if (ret) | ||
931 | return ERR_PTR(ret); | ||
932 | |||
933 | return trig; | ||
934 | } | ||
935 | |||
705 | static int kmx61_probe(struct i2c_client *client, | 936 | static int kmx61_probe(struct i2c_client *client, |
706 | const struct i2c_device_id *id) | 937 | const struct i2c_device_id *id) |
707 | { | 938 | { |
@@ -748,10 +979,55 @@ static int kmx61_probe(struct i2c_client *client, | |||
748 | if (client->irq < 0) | 979 | if (client->irq < 0) |
749 | client->irq = kmx61_gpio_probe(client, data); | 980 | client->irq = kmx61_gpio_probe(client, data); |
750 | 981 | ||
982 | if (client->irq >= 0) { | ||
983 | ret = devm_request_threaded_irq(&client->dev, client->irq, | ||
984 | kmx61_data_rdy_trig_poll, | ||
985 | NULL, | ||
986 | IRQF_TRIGGER_RISING, | ||
987 | KMX61_IRQ_NAME, | ||
988 | data); | ||
989 | if (ret) | ||
990 | goto err_chip_uninit; | ||
991 | |||
992 | data->acc_dready_trig = | ||
993 | kmx61_trigger_setup(data, data->acc_indio_dev, | ||
994 | "dready"); | ||
995 | if (IS_ERR(data->acc_dready_trig)) | ||
996 | return PTR_ERR(data->acc_dready_trig); | ||
997 | |||
998 | data->mag_dready_trig = | ||
999 | kmx61_trigger_setup(data, data->mag_indio_dev, | ||
1000 | "dready"); | ||
1001 | if (IS_ERR(data->mag_dready_trig)) { | ||
1002 | ret = PTR_ERR(data->mag_dready_trig); | ||
1003 | goto err_trigger_unregister; | ||
1004 | } | ||
1005 | |||
1006 | ret = iio_triggered_buffer_setup(data->acc_indio_dev, | ||
1007 | &iio_pollfunc_store_time, | ||
1008 | kmx61_trigger_handler, | ||
1009 | NULL); | ||
1010 | if (ret < 0) { | ||
1011 | dev_err(&data->client->dev, | ||
1012 | "Failed to setup acc triggered buffer\n"); | ||
1013 | goto err_trigger_unregister; | ||
1014 | } | ||
1015 | |||
1016 | ret = iio_triggered_buffer_setup(data->mag_indio_dev, | ||
1017 | &iio_pollfunc_store_time, | ||
1018 | kmx61_trigger_handler, | ||
1019 | NULL); | ||
1020 | if (ret < 0) { | ||
1021 | dev_err(&data->client->dev, | ||
1022 | "Failed to setup mag triggered buffer\n"); | ||
1023 | goto err_trigger_unregister; | ||
1024 | } | ||
1025 | } | ||
1026 | |||
751 | ret = iio_device_register(data->acc_indio_dev); | 1027 | ret = iio_device_register(data->acc_indio_dev); |
752 | if (ret < 0) { | 1028 | if (ret < 0) { |
753 | dev_err(&client->dev, "Failed to register acc iio device\n"); | 1029 | dev_err(&client->dev, "Failed to register acc iio device\n"); |
754 | goto err_chip_uninit; | 1030 | goto err_buffer_cleanup; |
755 | } | 1031 | } |
756 | 1032 | ||
757 | ret = iio_device_register(data->mag_indio_dev); | 1033 | ret = iio_device_register(data->mag_indio_dev); |
@@ -774,6 +1050,16 @@ err_iio_unregister_mag: | |||
774 | iio_device_unregister(data->mag_indio_dev); | 1050 | iio_device_unregister(data->mag_indio_dev); |
775 | err_iio_unregister_acc: | 1051 | err_iio_unregister_acc: |
776 | iio_device_unregister(data->acc_indio_dev); | 1052 | iio_device_unregister(data->acc_indio_dev); |
1053 | err_buffer_cleanup: | ||
1054 | if (client->irq >= 0) { | ||
1055 | iio_triggered_buffer_cleanup(data->acc_indio_dev); | ||
1056 | iio_triggered_buffer_cleanup(data->mag_indio_dev); | ||
1057 | } | ||
1058 | err_trigger_unregister: | ||
1059 | if (data->acc_dready_trig) | ||
1060 | iio_trigger_unregister(data->acc_dready_trig); | ||
1061 | if (data->mag_dready_trig) | ||
1062 | iio_trigger_unregister(data->mag_dready_trig); | ||
777 | err_chip_uninit: | 1063 | err_chip_uninit: |
778 | kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); | 1064 | kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); |
779 | return ret; | 1065 | return ret; |
@@ -790,6 +1076,13 @@ static int kmx61_remove(struct i2c_client *client) | |||
790 | iio_device_unregister(data->acc_indio_dev); | 1076 | iio_device_unregister(data->acc_indio_dev); |
791 | iio_device_unregister(data->mag_indio_dev); | 1077 | iio_device_unregister(data->mag_indio_dev); |
792 | 1078 | ||
1079 | if (client->irq >= 0) { | ||
1080 | iio_triggered_buffer_cleanup(data->acc_indio_dev); | ||
1081 | iio_triggered_buffer_cleanup(data->mag_indio_dev); | ||
1082 | iio_trigger_unregister(data->acc_dready_trig); | ||
1083 | iio_trigger_unregister(data->mag_dready_trig); | ||
1084 | } | ||
1085 | |||
793 | mutex_lock(&data->lock); | 1086 | mutex_lock(&data->lock); |
794 | kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); | 1087 | kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); |
795 | mutex_unlock(&data->lock); | 1088 | mutex_unlock(&data->lock); |