diff options
Diffstat (limited to 'drivers/iio')
51 files changed, 3249 insertions, 240 deletions
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 5dd0e120a504..345395e9dc6e 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | menuconfig IIO | 5 | menuconfig IIO |
6 | tristate "Industrial I/O support" | 6 | tristate "Industrial I/O support" |
7 | select ANON_INODES | ||
7 | help | 8 | help |
8 | The industrial I/O subsystem provides a unified framework for | 9 | The industrial I/O subsystem provides a unified framework for |
9 | drivers for many different types of embedded sensors using a | 10 | drivers for many different types of embedded sensors using a |
@@ -74,6 +75,7 @@ if IIO_TRIGGER | |||
74 | source "drivers/iio/trigger/Kconfig" | 75 | source "drivers/iio/trigger/Kconfig" |
75 | endif #IIO_TRIGGER | 76 | endif #IIO_TRIGGER |
76 | source "drivers/iio/pressure/Kconfig" | 77 | source "drivers/iio/pressure/Kconfig" |
78 | source "drivers/iio/proximity/Kconfig" | ||
77 | source "drivers/iio/temperature/Kconfig" | 79 | source "drivers/iio/temperature/Kconfig" |
78 | 80 | ||
79 | endif # IIO | 81 | endif # IIO |
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 887d39090d75..698afc2d17ce 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile | |||
@@ -24,5 +24,6 @@ obj-y += light/ | |||
24 | obj-y += magnetometer/ | 24 | obj-y += magnetometer/ |
25 | obj-y += orientation/ | 25 | obj-y += orientation/ |
26 | obj-y += pressure/ | 26 | obj-y += pressure/ |
27 | obj-y += proximity/ | ||
27 | obj-y += temperature/ | 28 | obj-y += temperature/ |
28 | obj-y += trigger/ | 29 | obj-y += trigger/ |
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index e23e50850655..1e120fa1e156 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig | |||
@@ -65,4 +65,16 @@ config KXSD9 | |||
65 | Say yes here to build support for the Kionix KXSD9 accelerometer. | 65 | Say yes here to build support for the Kionix KXSD9 accelerometer. |
66 | Currently this only supports the device via an SPI interface. | 66 | Currently this only supports the device via an SPI interface. |
67 | 67 | ||
68 | config MMA8452 | ||
69 | tristate "Freescale MMA8452Q Accelerometer Driver" | ||
70 | depends on I2C | ||
71 | select IIO_BUFFER | ||
72 | select IIO_TRIGGERED_BUFFER | ||
73 | help | ||
74 | Say yes here to build support for the Freescale MMA8452Q 3-axis | ||
75 | accelerometer. | ||
76 | |||
77 | To compile this driver as a module, choose M here: the module | ||
78 | will be called mma8452. | ||
79 | |||
68 | endmenu | 80 | endmenu |
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index c48d15f25616..dc0e379c2592 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile | |||
@@ -6,6 +6,7 @@ | |||
6 | obj-$(CONFIG_BMA180) += bma180.o | 6 | obj-$(CONFIG_BMA180) += bma180.o |
7 | obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o | 7 | obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o |
8 | obj-$(CONFIG_KXSD9) += kxsd9.o | 8 | obj-$(CONFIG_KXSD9) += kxsd9.o |
9 | obj-$(CONFIG_MMA8452) += mma8452.o | ||
9 | 10 | ||
10 | obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o | 11 | obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o |
11 | st_accel-y := st_accel_core.o | 12 | st_accel-y := st_accel_core.o |
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 3dcdbad65456..69abf9163df7 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/delay.h> | ||
25 | #include <linux/hid-sensor-hub.h> | 26 | #include <linux/hid-sensor-hub.h> |
26 | #include <linux/iio/iio.h> | 27 | #include <linux/iio/iio.h> |
27 | #include <linux/iio/sysfs.h> | 28 | #include <linux/iio/sysfs.h> |
@@ -42,6 +43,10 @@ struct accel_3d_state { | |||
42 | struct hid_sensor_common common_attributes; | 43 | struct hid_sensor_common common_attributes; |
43 | struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX]; | 44 | struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX]; |
44 | u32 accel_val[ACCEL_3D_CHANNEL_MAX]; | 45 | u32 accel_val[ACCEL_3D_CHANNEL_MAX]; |
46 | int scale_pre_decml; | ||
47 | int scale_post_decml; | ||
48 | int scale_precision; | ||
49 | int value_offset; | ||
45 | }; | 50 | }; |
46 | 51 | ||
47 | static const u32 accel_3d_addresses[ACCEL_3D_CHANNEL_MAX] = { | 52 | static const u32 accel_3d_addresses[ACCEL_3D_CHANNEL_MAX] = { |
@@ -56,6 +61,7 @@ static const struct iio_chan_spec accel_3d_channels[] = { | |||
56 | .type = IIO_ACCEL, | 61 | .type = IIO_ACCEL, |
57 | .modified = 1, | 62 | .modified = 1, |
58 | .channel2 = IIO_MOD_X, | 63 | .channel2 = IIO_MOD_X, |
64 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
59 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 65 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
60 | BIT(IIO_CHAN_INFO_SCALE) | | 66 | BIT(IIO_CHAN_INFO_SCALE) | |
61 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 67 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
@@ -65,6 +71,7 @@ static const struct iio_chan_spec accel_3d_channels[] = { | |||
65 | .type = IIO_ACCEL, | 71 | .type = IIO_ACCEL, |
66 | .modified = 1, | 72 | .modified = 1, |
67 | .channel2 = IIO_MOD_Y, | 73 | .channel2 = IIO_MOD_Y, |
74 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
68 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 75 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
69 | BIT(IIO_CHAN_INFO_SCALE) | | 76 | BIT(IIO_CHAN_INFO_SCALE) | |
70 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 77 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
@@ -74,6 +81,7 @@ static const struct iio_chan_spec accel_3d_channels[] = { | |||
74 | .type = IIO_ACCEL, | 81 | .type = IIO_ACCEL, |
75 | .modified = 1, | 82 | .modified = 1, |
76 | .channel2 = IIO_MOD_Z, | 83 | .channel2 = IIO_MOD_Z, |
84 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
77 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 85 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
78 | BIT(IIO_CHAN_INFO_SCALE) | | 86 | BIT(IIO_CHAN_INFO_SCALE) | |
79 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 87 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
@@ -104,31 +112,42 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev, | |||
104 | u32 address; | 112 | u32 address; |
105 | int ret; | 113 | int ret; |
106 | int ret_type; | 114 | int ret_type; |
115 | s32 poll_value; | ||
107 | 116 | ||
108 | *val = 0; | 117 | *val = 0; |
109 | *val2 = 0; | 118 | *val2 = 0; |
110 | switch (mask) { | 119 | switch (mask) { |
111 | case 0: | 120 | case 0: |
121 | poll_value = hid_sensor_read_poll_value( | ||
122 | &accel_state->common_attributes); | ||
123 | if (poll_value < 0) | ||
124 | return -EINVAL; | ||
125 | |||
126 | hid_sensor_power_state(&accel_state->common_attributes, true); | ||
127 | msleep_interruptible(poll_value * 2); | ||
112 | report_id = accel_state->accel[chan->scan_index].report_id; | 128 | report_id = accel_state->accel[chan->scan_index].report_id; |
113 | address = accel_3d_addresses[chan->scan_index]; | 129 | address = accel_3d_addresses[chan->scan_index]; |
114 | if (report_id >= 0) | 130 | if (report_id >= 0) |
115 | *val = sensor_hub_input_attr_get_raw_value( | 131 | *val = sensor_hub_input_attr_get_raw_value( |
116 | accel_state->common_attributes.hsdev, | 132 | accel_state->common_attributes.hsdev, |
117 | HID_USAGE_SENSOR_ACCEL_3D, address, | 133 | HID_USAGE_SENSOR_ACCEL_3D, address, |
118 | report_id); | 134 | report_id); |
119 | else { | 135 | else { |
120 | *val = 0; | 136 | *val = 0; |
137 | hid_sensor_power_state(&accel_state->common_attributes, | ||
138 | false); | ||
121 | return -EINVAL; | 139 | return -EINVAL; |
122 | } | 140 | } |
141 | hid_sensor_power_state(&accel_state->common_attributes, false); | ||
123 | ret_type = IIO_VAL_INT; | 142 | ret_type = IIO_VAL_INT; |
124 | break; | 143 | break; |
125 | case IIO_CHAN_INFO_SCALE: | 144 | case IIO_CHAN_INFO_SCALE: |
126 | *val = accel_state->accel[CHANNEL_SCAN_INDEX_X].units; | 145 | *val = accel_state->scale_pre_decml; |
127 | ret_type = IIO_VAL_INT; | 146 | *val2 = accel_state->scale_post_decml; |
147 | ret_type = accel_state->scale_precision; | ||
128 | break; | 148 | break; |
129 | case IIO_CHAN_INFO_OFFSET: | 149 | case IIO_CHAN_INFO_OFFSET: |
130 | *val = hid_sensor_convert_exponent( | 150 | *val = accel_state->value_offset; |
131 | accel_state->accel[CHANNEL_SCAN_INDEX_X].unit_expo); | ||
132 | ret_type = IIO_VAL_INT; | 151 | ret_type = IIO_VAL_INT; |
133 | break; | 152 | break; |
134 | case IIO_CHAN_INFO_SAMP_FREQ: | 153 | case IIO_CHAN_INFO_SAMP_FREQ: |
@@ -197,9 +216,8 @@ static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev, | |||
197 | struct iio_dev *indio_dev = platform_get_drvdata(priv); | 216 | struct iio_dev *indio_dev = platform_get_drvdata(priv); |
198 | struct accel_3d_state *accel_state = iio_priv(indio_dev); | 217 | struct accel_3d_state *accel_state = iio_priv(indio_dev); |
199 | 218 | ||
200 | dev_dbg(&indio_dev->dev, "accel_3d_proc_event [%d]\n", | 219 | dev_dbg(&indio_dev->dev, "accel_3d_proc_event\n"); |
201 | accel_state->common_attributes.data_ready); | 220 | if (atomic_read(&accel_state->common_attributes.data_ready)) |
202 | if (accel_state->common_attributes.data_ready) | ||
203 | hid_sensor_push_data(indio_dev, | 221 | hid_sensor_push_data(indio_dev, |
204 | accel_state->accel_val, | 222 | accel_state->accel_val, |
205 | sizeof(accel_state->accel_val)); | 223 | sizeof(accel_state->accel_val)); |
@@ -262,6 +280,11 @@ static int accel_3d_parse_report(struct platform_device *pdev, | |||
262 | st->accel[1].index, st->accel[1].report_id, | 280 | st->accel[1].index, st->accel[1].report_id, |
263 | st->accel[2].index, st->accel[2].report_id); | 281 | st->accel[2].index, st->accel[2].report_id); |
264 | 282 | ||
283 | st->scale_precision = hid_sensor_format_scale( | ||
284 | HID_USAGE_SENSOR_ACCEL_3D, | ||
285 | &st->accel[CHANNEL_SCAN_INDEX_X], | ||
286 | &st->scale_pre_decml, &st->scale_post_decml); | ||
287 | |||
265 | /* Set Sensitivity field ids, when there is no individual modifier */ | 288 | /* Set Sensitivity field ids, when there is no individual modifier */ |
266 | if (st->common_attributes.sensitivity.index < 0) { | 289 | if (st->common_attributes.sensitivity.index < 0) { |
267 | sensor_hub_input_get_attribute_info(hsdev, | 290 | sensor_hub_input_get_attribute_info(hsdev, |
@@ -333,7 +356,7 @@ static int hid_accel_3d_probe(struct platform_device *pdev) | |||
333 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | 356 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); |
334 | goto error_free_dev_mem; | 357 | goto error_free_dev_mem; |
335 | } | 358 | } |
336 | accel_state->common_attributes.data_ready = false; | 359 | atomic_set(&accel_state->common_attributes.data_ready, 0); |
337 | ret = hid_sensor_setup_trigger(indio_dev, name, | 360 | ret = hid_sensor_setup_trigger(indio_dev, name, |
338 | &accel_state->common_attributes); | 361 | &accel_state->common_attributes); |
339 | if (ret < 0) { | 362 | if (ret < 0) { |
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c new file mode 100644 index 000000000000..17aeea170566 --- /dev/null +++ b/drivers/iio/accel/mma8452.c | |||
@@ -0,0 +1,439 @@ | |||
1 | /* | ||
2 | * mma8452.c - Support for Freescale MMA8452Q 3-axis 12-bit accelerometer | ||
3 | * | ||
4 | * Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net> | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of version 2 of | ||
7 | * the GNU General Public License. See the file COPYING in the main | ||
8 | * directory of this archive for more details. | ||
9 | * | ||
10 | * 7-bit I2C slave address 0x1c/0x1d (pin selectable) | ||
11 | * | ||
12 | * TODO: interrupt, thresholding, orientation / freefall events, autosleep | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/iio/iio.h> | ||
18 | #include <linux/iio/sysfs.h> | ||
19 | #include <linux/iio/trigger_consumer.h> | ||
20 | #include <linux/iio/buffer.h> | ||
21 | #include <linux/iio/triggered_buffer.h> | ||
22 | #include <linux/delay.h> | ||
23 | |||
24 | #define MMA8452_STATUS 0x00 | ||
25 | #define MMA8452_OUT_X 0x01 /* MSB first, 12-bit */ | ||
26 | #define MMA8452_OUT_Y 0x03 | ||
27 | #define MMA8452_OUT_Z 0x05 | ||
28 | #define MMA8452_WHO_AM_I 0x0d | ||
29 | #define MMA8452_DATA_CFG 0x0e | ||
30 | #define MMA8452_OFF_X 0x2f | ||
31 | #define MMA8452_OFF_Y 0x30 | ||
32 | #define MMA8452_OFF_Z 0x31 | ||
33 | #define MMA8452_CTRL_REG1 0x2a | ||
34 | #define MMA8452_CTRL_REG2 0x2b | ||
35 | |||
36 | #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) | ||
37 | |||
38 | #define MMA8452_CTRL_DR_MASK (BIT(5) | BIT(4) | BIT(3)) | ||
39 | #define MMA8452_CTRL_DR_SHIFT 3 | ||
40 | #define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */ | ||
41 | #define MMA8452_CTRL_ACTIVE BIT(0) | ||
42 | |||
43 | #define MMA8452_DATA_CFG_FS_MASK (BIT(1) | BIT(0)) | ||
44 | #define MMA8452_DATA_CFG_FS_2G 0 | ||
45 | #define MMA8452_DATA_CFG_FS_4G 1 | ||
46 | #define MMA8452_DATA_CFG_FS_8G 2 | ||
47 | |||
48 | #define MMA8452_DEVICE_ID 0x2a | ||
49 | |||
50 | struct mma8452_data { | ||
51 | struct i2c_client *client; | ||
52 | struct mutex lock; | ||
53 | u8 ctrl_reg1; | ||
54 | u8 data_cfg; | ||
55 | }; | ||
56 | |||
57 | static int mma8452_drdy(struct mma8452_data *data) | ||
58 | { | ||
59 | int tries = 150; | ||
60 | |||
61 | while (tries-- > 0) { | ||
62 | int ret = i2c_smbus_read_byte_data(data->client, | ||
63 | MMA8452_STATUS); | ||
64 | if (ret < 0) | ||
65 | return ret; | ||
66 | if ((ret & MMA8452_STATUS_DRDY) == MMA8452_STATUS_DRDY) | ||
67 | return 0; | ||
68 | msleep(20); | ||
69 | } | ||
70 | |||
71 | dev_err(&data->client->dev, "data not ready\n"); | ||
72 | return -EIO; | ||
73 | } | ||
74 | |||
75 | static int mma8452_read(struct mma8452_data *data, __be16 buf[3]) | ||
76 | { | ||
77 | int ret = mma8452_drdy(data); | ||
78 | if (ret < 0) | ||
79 | return ret; | ||
80 | return i2c_smbus_read_i2c_block_data(data->client, | ||
81 | MMA8452_OUT_X, 3 * sizeof(__be16), (u8 *) buf); | ||
82 | } | ||
83 | |||
84 | static ssize_t mma8452_show_int_plus_micros(char *buf, | ||
85 | const int (*vals)[2], int n) | ||
86 | { | ||
87 | size_t len = 0; | ||
88 | |||
89 | while (n-- > 0) | ||
90 | len += scnprintf(buf + len, PAGE_SIZE - len, | ||
91 | "%d.%06d ", vals[n][0], vals[n][1]); | ||
92 | |||
93 | /* replace trailing space by newline */ | ||
94 | buf[len - 1] = '\n'; | ||
95 | |||
96 | return len; | ||
97 | } | ||
98 | |||
99 | static int mma8452_get_int_plus_micros_index(const int (*vals)[2], int n, | ||
100 | int val, int val2) | ||
101 | { | ||
102 | while (n-- > 0) | ||
103 | if (val == vals[n][0] && val2 == vals[n][1]) | ||
104 | return n; | ||
105 | |||
106 | return -EINVAL; | ||
107 | } | ||
108 | |||
109 | static const int mma8452_samp_freq[8][2] = { | ||
110 | {800, 0}, {400, 0}, {200, 0}, {100, 0}, {50, 0}, {12, 500000}, | ||
111 | {6, 250000}, {1, 560000} | ||
112 | }; | ||
113 | |||
114 | static const int mma8452_scales[3][2] = { | ||
115 | {0, 977}, {0, 1953}, {0, 3906} | ||
116 | }; | ||
117 | |||
118 | static ssize_t mma8452_show_samp_freq_avail(struct device *dev, | ||
119 | struct device_attribute *attr, char *buf) | ||
120 | { | ||
121 | return mma8452_show_int_plus_micros(buf, mma8452_samp_freq, | ||
122 | ARRAY_SIZE(mma8452_samp_freq)); | ||
123 | } | ||
124 | |||
125 | static ssize_t mma8452_show_scale_avail(struct device *dev, | ||
126 | struct device_attribute *attr, char *buf) | ||
127 | { | ||
128 | return mma8452_show_int_plus_micros(buf, mma8452_scales, | ||
129 | ARRAY_SIZE(mma8452_scales)); | ||
130 | } | ||
131 | |||
132 | static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail); | ||
133 | static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO, | ||
134 | mma8452_show_scale_avail, NULL, 0); | ||
135 | |||
136 | static int mma8452_get_samp_freq_index(struct mma8452_data *data, | ||
137 | int val, int val2) | ||
138 | { | ||
139 | return mma8452_get_int_plus_micros_index(mma8452_samp_freq, | ||
140 | ARRAY_SIZE(mma8452_samp_freq), val, val2); | ||
141 | } | ||
142 | |||
143 | static int mma8452_get_scale_index(struct mma8452_data *data, | ||
144 | int val, int val2) | ||
145 | { | ||
146 | return mma8452_get_int_plus_micros_index(mma8452_scales, | ||
147 | ARRAY_SIZE(mma8452_scales), val, val2); | ||
148 | } | ||
149 | |||
150 | static int mma8452_read_raw(struct iio_dev *indio_dev, | ||
151 | struct iio_chan_spec const *chan, | ||
152 | int *val, int *val2, long mask) | ||
153 | { | ||
154 | struct mma8452_data *data = iio_priv(indio_dev); | ||
155 | __be16 buffer[3]; | ||
156 | int i, ret; | ||
157 | |||
158 | switch (mask) { | ||
159 | case IIO_CHAN_INFO_RAW: | ||
160 | if (iio_buffer_enabled(indio_dev)) | ||
161 | return -EBUSY; | ||
162 | |||
163 | mutex_lock(&data->lock); | ||
164 | ret = mma8452_read(data, buffer); | ||
165 | mutex_unlock(&data->lock); | ||
166 | if (ret < 0) | ||
167 | return ret; | ||
168 | *val = sign_extend32( | ||
169 | be16_to_cpu(buffer[chan->scan_index]) >> 4, 11); | ||
170 | return IIO_VAL_INT; | ||
171 | case IIO_CHAN_INFO_SCALE: | ||
172 | i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK; | ||
173 | *val = mma8452_scales[i][0]; | ||
174 | *val2 = mma8452_scales[i][1]; | ||
175 | return IIO_VAL_INT_PLUS_MICRO; | ||
176 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
177 | i = (data->ctrl_reg1 & MMA8452_CTRL_DR_MASK) >> | ||
178 | MMA8452_CTRL_DR_SHIFT; | ||
179 | *val = mma8452_samp_freq[i][0]; | ||
180 | *val2 = mma8452_samp_freq[i][1]; | ||
181 | return IIO_VAL_INT_PLUS_MICRO; | ||
182 | case IIO_CHAN_INFO_CALIBBIAS: | ||
183 | ret = i2c_smbus_read_byte_data(data->client, MMA8452_OFF_X + | ||
184 | chan->scan_index); | ||
185 | if (ret < 0) | ||
186 | return ret; | ||
187 | *val = sign_extend32(ret, 7); | ||
188 | return IIO_VAL_INT; | ||
189 | } | ||
190 | return -EINVAL; | ||
191 | } | ||
192 | |||
193 | static int mma8452_standby(struct mma8452_data *data) | ||
194 | { | ||
195 | return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1, | ||
196 | data->ctrl_reg1 & ~MMA8452_CTRL_ACTIVE); | ||
197 | } | ||
198 | |||
199 | static int mma8452_active(struct mma8452_data *data) | ||
200 | { | ||
201 | return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1, | ||
202 | data->ctrl_reg1); | ||
203 | } | ||
204 | |||
205 | static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val) | ||
206 | { | ||
207 | int ret; | ||
208 | |||
209 | mutex_lock(&data->lock); | ||
210 | |||
211 | /* config can only be changed when in standby */ | ||
212 | ret = mma8452_standby(data); | ||
213 | if (ret < 0) | ||
214 | goto fail; | ||
215 | |||
216 | ret = i2c_smbus_write_byte_data(data->client, reg, val); | ||
217 | if (ret < 0) | ||
218 | goto fail; | ||
219 | |||
220 | ret = mma8452_active(data); | ||
221 | if (ret < 0) | ||
222 | goto fail; | ||
223 | |||
224 | ret = 0; | ||
225 | fail: | ||
226 | mutex_unlock(&data->lock); | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | static int mma8452_write_raw(struct iio_dev *indio_dev, | ||
231 | struct iio_chan_spec const *chan, | ||
232 | int val, int val2, long mask) | ||
233 | { | ||
234 | struct mma8452_data *data = iio_priv(indio_dev); | ||
235 | int i; | ||
236 | |||
237 | if (iio_buffer_enabled(indio_dev)) | ||
238 | return -EBUSY; | ||
239 | |||
240 | switch (mask) { | ||
241 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
242 | i = mma8452_get_samp_freq_index(data, val, val2); | ||
243 | if (i < 0) | ||
244 | return -EINVAL; | ||
245 | |||
246 | data->ctrl_reg1 &= ~MMA8452_CTRL_DR_MASK; | ||
247 | data->ctrl_reg1 |= i << MMA8452_CTRL_DR_SHIFT; | ||
248 | return mma8452_change_config(data, MMA8452_CTRL_REG1, | ||
249 | data->ctrl_reg1); | ||
250 | case IIO_CHAN_INFO_SCALE: | ||
251 | i = mma8452_get_scale_index(data, val, val2); | ||
252 | if (i < 0) | ||
253 | return -EINVAL; | ||
254 | data->data_cfg &= ~MMA8452_DATA_CFG_FS_MASK; | ||
255 | data->data_cfg |= i; | ||
256 | return mma8452_change_config(data, MMA8452_DATA_CFG, | ||
257 | data->data_cfg); | ||
258 | case IIO_CHAN_INFO_CALIBBIAS: | ||
259 | if (val < -128 || val > 127) | ||
260 | return -EINVAL; | ||
261 | return mma8452_change_config(data, MMA8452_OFF_X + | ||
262 | chan->scan_index, val); | ||
263 | default: | ||
264 | return -EINVAL; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | static irqreturn_t mma8452_trigger_handler(int irq, void *p) | ||
269 | { | ||
270 | struct iio_poll_func *pf = p; | ||
271 | struct iio_dev *indio_dev = pf->indio_dev; | ||
272 | struct mma8452_data *data = iio_priv(indio_dev); | ||
273 | u8 buffer[16]; /* 3 16-bit channels + padding + ts */ | ||
274 | int ret; | ||
275 | |||
276 | ret = mma8452_read(data, (__be16 *) buffer); | ||
277 | if (ret < 0) | ||
278 | goto done; | ||
279 | |||
280 | iio_push_to_buffers_with_timestamp(indio_dev, buffer, | ||
281 | iio_get_time_ns()); | ||
282 | |||
283 | done: | ||
284 | iio_trigger_notify_done(indio_dev->trig); | ||
285 | return IRQ_HANDLED; | ||
286 | } | ||
287 | |||
288 | #define MMA8452_CHANNEL(axis, idx) { \ | ||
289 | .type = IIO_ACCEL, \ | ||
290 | .modified = 1, \ | ||
291 | .channel2 = IIO_MOD_##axis, \ | ||
292 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | ||
293 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ | ||
294 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | ||
295 | BIT(IIO_CHAN_INFO_SCALE), \ | ||
296 | .scan_index = idx, \ | ||
297 | .scan_type = { \ | ||
298 | .sign = 's', \ | ||
299 | .realbits = 12, \ | ||
300 | .storagebits = 16, \ | ||
301 | .shift = 4, \ | ||
302 | .endianness = IIO_BE, \ | ||
303 | }, \ | ||
304 | } | ||
305 | |||
306 | static const struct iio_chan_spec mma8452_channels[] = { | ||
307 | MMA8452_CHANNEL(X, 0), | ||
308 | MMA8452_CHANNEL(Y, 1), | ||
309 | MMA8452_CHANNEL(Z, 2), | ||
310 | IIO_CHAN_SOFT_TIMESTAMP(3), | ||
311 | }; | ||
312 | |||
313 | static struct attribute *mma8452_attributes[] = { | ||
314 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, | ||
315 | &iio_dev_attr_in_accel_scale_available.dev_attr.attr, | ||
316 | NULL | ||
317 | }; | ||
318 | |||
319 | static const struct attribute_group mma8452_group = { | ||
320 | .attrs = mma8452_attributes, | ||
321 | }; | ||
322 | |||
323 | static const struct iio_info mma8452_info = { | ||
324 | .attrs = &mma8452_group, | ||
325 | .read_raw = &mma8452_read_raw, | ||
326 | .write_raw = &mma8452_write_raw, | ||
327 | .driver_module = THIS_MODULE, | ||
328 | }; | ||
329 | |||
330 | static const unsigned long mma8452_scan_masks[] = {0x7, 0}; | ||
331 | |||
332 | static int mma8452_probe(struct i2c_client *client, | ||
333 | const struct i2c_device_id *id) | ||
334 | { | ||
335 | struct mma8452_data *data; | ||
336 | struct iio_dev *indio_dev; | ||
337 | int ret; | ||
338 | |||
339 | ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I); | ||
340 | if (ret < 0) | ||
341 | return ret; | ||
342 | if (ret != MMA8452_DEVICE_ID) | ||
343 | return -ENODEV; | ||
344 | |||
345 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
346 | if (!indio_dev) | ||
347 | return -ENOMEM; | ||
348 | |||
349 | data = iio_priv(indio_dev); | ||
350 | data->client = client; | ||
351 | mutex_init(&data->lock); | ||
352 | |||
353 | i2c_set_clientdata(client, indio_dev); | ||
354 | indio_dev->info = &mma8452_info; | ||
355 | indio_dev->name = id->name; | ||
356 | indio_dev->dev.parent = &client->dev; | ||
357 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
358 | indio_dev->channels = mma8452_channels; | ||
359 | indio_dev->num_channels = ARRAY_SIZE(mma8452_channels); | ||
360 | indio_dev->available_scan_masks = mma8452_scan_masks; | ||
361 | |||
362 | data->ctrl_reg1 = MMA8452_CTRL_ACTIVE | | ||
363 | (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT); | ||
364 | ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1, | ||
365 | data->ctrl_reg1); | ||
366 | if (ret < 0) | ||
367 | return ret; | ||
368 | |||
369 | data->data_cfg = MMA8452_DATA_CFG_FS_2G; | ||
370 | ret = i2c_smbus_write_byte_data(client, MMA8452_DATA_CFG, | ||
371 | data->data_cfg); | ||
372 | if (ret < 0) | ||
373 | return ret; | ||
374 | |||
375 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | ||
376 | mma8452_trigger_handler, NULL); | ||
377 | if (ret < 0) | ||
378 | return ret; | ||
379 | |||
380 | ret = iio_device_register(indio_dev); | ||
381 | if (ret < 0) | ||
382 | goto buffer_cleanup; | ||
383 | return 0; | ||
384 | |||
385 | buffer_cleanup: | ||
386 | iio_triggered_buffer_cleanup(indio_dev); | ||
387 | return ret; | ||
388 | } | ||
389 | |||
390 | static int mma8452_remove(struct i2c_client *client) | ||
391 | { | ||
392 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
393 | |||
394 | iio_device_unregister(indio_dev); | ||
395 | iio_triggered_buffer_cleanup(indio_dev); | ||
396 | mma8452_standby(iio_priv(indio_dev)); | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | #ifdef CONFIG_PM_SLEEP | ||
402 | static int mma8452_suspend(struct device *dev) | ||
403 | { | ||
404 | return mma8452_standby(iio_priv(i2c_get_clientdata( | ||
405 | to_i2c_client(dev)))); | ||
406 | } | ||
407 | |||
408 | static int mma8452_resume(struct device *dev) | ||
409 | { | ||
410 | return mma8452_active(iio_priv(i2c_get_clientdata( | ||
411 | to_i2c_client(dev)))); | ||
412 | } | ||
413 | |||
414 | static SIMPLE_DEV_PM_OPS(mma8452_pm_ops, mma8452_suspend, mma8452_resume); | ||
415 | #define MMA8452_PM_OPS (&mma8452_pm_ops) | ||
416 | #else | ||
417 | #define MMA8452_PM_OPS NULL | ||
418 | #endif | ||
419 | |||
420 | static const struct i2c_device_id mma8452_id[] = { | ||
421 | { "mma8452", 0 }, | ||
422 | { } | ||
423 | }; | ||
424 | MODULE_DEVICE_TABLE(i2c, mma8452_id); | ||
425 | |||
426 | static struct i2c_driver mma8452_driver = { | ||
427 | .driver = { | ||
428 | .name = "mma8452", | ||
429 | .pm = MMA8452_PM_OPS, | ||
430 | }, | ||
431 | .probe = mma8452_probe, | ||
432 | .remove = mma8452_remove, | ||
433 | .id_table = mma8452_id, | ||
434 | }; | ||
435 | module_i2c_driver(mma8452_driver); | ||
436 | |||
437 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); | ||
438 | MODULE_DESCRIPTION("Freescale MMA8452 accelerometer driver"); | ||
439 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 38caedc76b98..a2abf7c2ce3b 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c | |||
@@ -459,6 +459,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev, | |||
459 | indio_dev->modes = INDIO_DIRECT_MODE; | 459 | indio_dev->modes = INDIO_DIRECT_MODE; |
460 | indio_dev->info = &accel_info; | 460 | indio_dev->info = &accel_info; |
461 | 461 | ||
462 | st_sensors_power_enable(indio_dev); | ||
463 | |||
462 | err = st_sensors_check_device_support(indio_dev, | 464 | err = st_sensors_check_device_support(indio_dev, |
463 | ARRAY_SIZE(st_accel_sensors), st_accel_sensors); | 465 | ARRAY_SIZE(st_accel_sensors), st_accel_sensors); |
464 | if (err < 0) | 466 | if (err < 0) |
@@ -496,6 +498,9 @@ int st_accel_common_probe(struct iio_dev *indio_dev, | |||
496 | if (err) | 498 | if (err) |
497 | goto st_accel_device_register_error; | 499 | goto st_accel_device_register_error; |
498 | 500 | ||
501 | dev_info(&indio_dev->dev, "registered accelerometer %s\n", | ||
502 | indio_dev->name); | ||
503 | |||
499 | return 0; | 504 | return 0; |
500 | 505 | ||
501 | st_accel_device_register_error: | 506 | st_accel_device_register_error: |
@@ -512,6 +517,8 @@ void st_accel_common_remove(struct iio_dev *indio_dev) | |||
512 | { | 517 | { |
513 | struct st_sensor_data *adata = iio_priv(indio_dev); | 518 | struct st_sensor_data *adata = iio_priv(indio_dev); |
514 | 519 | ||
520 | st_sensors_power_disable(indio_dev); | ||
521 | |||
515 | iio_device_unregister(indio_dev); | 522 | iio_device_unregister(indio_dev); |
516 | if (adata->get_irq_data_ready(indio_dev) > 0) | 523 | if (adata->get_irq_data_ready(indio_dev) > 0) |
517 | st_sensors_deallocate_trigger(indio_dev); | 524 | st_sensors_deallocate_trigger(indio_dev); |
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 24c28e3f93a3..a80d23628f14 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig | |||
@@ -96,9 +96,21 @@ config AD7923 | |||
96 | To compile this driver as a module, choose M here: the | 96 | To compile this driver as a module, choose M here: the |
97 | module will be called ad7923. | 97 | module will be called ad7923. |
98 | 98 | ||
99 | config AD799X | ||
100 | tristate "Analog Devices AD799x ADC driver" | ||
101 | depends on I2C | ||
102 | select IIO_BUFFER | ||
103 | select IIO_TRIGGERED_BUFFER | ||
104 | help | ||
105 | Say yes here to build support for Analog Devices: | ||
106 | ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997, ad7998 | ||
107 | i2c analog to digital converters (ADC). Provides direct access | ||
108 | via sysfs. | ||
109 | |||
99 | config AT91_ADC | 110 | config AT91_ADC |
100 | tristate "Atmel AT91 ADC" | 111 | tristate "Atmel AT91 ADC" |
101 | depends on ARCH_AT91 | 112 | depends on ARCH_AT91 |
113 | depends on INPUT | ||
102 | select IIO_BUFFER | 114 | select IIO_BUFFER |
103 | select IIO_TRIGGERED_BUFFER | 115 | select IIO_TRIGGERED_BUFFER |
104 | select SYSFS | 116 | select SYSFS |
@@ -107,7 +119,7 @@ config AT91_ADC | |||
107 | 119 | ||
108 | config EXYNOS_ADC | 120 | config EXYNOS_ADC |
109 | tristate "Exynos ADC driver support" | 121 | tristate "Exynos ADC driver support" |
110 | depends on OF | 122 | depends on ARCH_EXYNOS || (OF && COMPILE_TEST) |
111 | help | 123 | help |
112 | Core support for the ADC block found in the Samsung EXYNOS series | 124 | Core support for the ADC block found in the Samsung EXYNOS series |
113 | of SoCs for drivers such as the touchscreen and hwmon to use to share | 125 | of SoCs for drivers such as the touchscreen and hwmon to use to share |
@@ -146,11 +158,12 @@ config MCP320X | |||
146 | called mcp320x. | 158 | called mcp320x. |
147 | 159 | ||
148 | config MCP3422 | 160 | config MCP3422 |
149 | tristate "Microchip Technology MCP3422/3/4 driver" | 161 | tristate "Microchip Technology MCP3422/3/4/6/7/8 driver" |
150 | depends on I2C | 162 | depends on I2C |
151 | help | 163 | help |
152 | Say yes here to build support for Microchip Technology's MCP3422, | 164 | Say yes here to build support for Microchip Technology's |
153 | MCP3423 or MCP3424 analog to digital converters. | 165 | MCP3422, MCP3423, MCP3424, MCP3426, MCP3427 or MCP3428 |
166 | analog to digital converters. | ||
154 | 167 | ||
155 | This driver can also be built as a module. If so, the module will be | 168 | This driver can also be built as a module. If so, the module will be |
156 | called mcp3422. | 169 | called mcp3422. |
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index ab346d88c688..9d60f2deaaaf 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile | |||
@@ -11,6 +11,7 @@ obj-$(CONFIG_AD7476) += ad7476.o | |||
11 | obj-$(CONFIG_AD7791) += ad7791.o | 11 | obj-$(CONFIG_AD7791) += ad7791.o |
12 | obj-$(CONFIG_AD7793) += ad7793.o | 12 | obj-$(CONFIG_AD7793) += ad7793.o |
13 | obj-$(CONFIG_AD7887) += ad7887.o | 13 | obj-$(CONFIG_AD7887) += ad7887.o |
14 | obj-$(CONFIG_AD799X) += ad799x.o | ||
14 | obj-$(CONFIG_AT91_ADC) += at91_adc.o | 15 | obj-$(CONFIG_AT91_ADC) += at91_adc.o |
15 | obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o | 16 | obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o |
16 | obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o | 17 | obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o |
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c new file mode 100644 index 000000000000..39b4cb48d738 --- /dev/null +++ b/drivers/iio/adc/ad799x.c | |||
@@ -0,0 +1,791 @@ | |||
1 | /* | ||
2 | * iio/adc/ad799x.c | ||
3 | * Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc. | ||
4 | * | ||
5 | * based on iio/adc/max1363 | ||
6 | * Copyright (C) 2008-2010 Jonathan Cameron | ||
7 | * | ||
8 | * based on linux/drivers/i2c/chips/max123x | ||
9 | * Copyright (C) 2002-2004 Stefan Eletzhofer | ||
10 | * | ||
11 | * based on linux/drivers/acron/char/pcf8583.c | ||
12 | * Copyright (C) 2000 Russell King | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | * | ||
18 | * ad799x.c | ||
19 | * | ||
20 | * Support for ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997, | ||
21 | * ad7998 and similar chips. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/sysfs.h> | ||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/regulator/consumer.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/err.h> | ||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <linux/iio/iio.h> | ||
37 | #include <linux/iio/sysfs.h> | ||
38 | #include <linux/iio/events.h> | ||
39 | #include <linux/iio/buffer.h> | ||
40 | #include <linux/iio/trigger_consumer.h> | ||
41 | #include <linux/iio/triggered_buffer.h> | ||
42 | |||
43 | #define AD799X_CHANNEL_SHIFT 4 | ||
44 | #define AD799X_STORAGEBITS 16 | ||
45 | /* | ||
46 | * AD7991, AD7995 and AD7999 defines | ||
47 | */ | ||
48 | |||
49 | #define AD7991_REF_SEL 0x08 | ||
50 | #define AD7991_FLTR 0x04 | ||
51 | #define AD7991_BIT_TRIAL_DELAY 0x02 | ||
52 | #define AD7991_SAMPLE_DELAY 0x01 | ||
53 | |||
54 | /* | ||
55 | * AD7992, AD7993, AD7994, AD7997 and AD7998 defines | ||
56 | */ | ||
57 | |||
58 | #define AD7998_FLTR 0x08 | ||
59 | #define AD7998_ALERT_EN 0x04 | ||
60 | #define AD7998_BUSY_ALERT 0x02 | ||
61 | #define AD7998_BUSY_ALERT_POL 0x01 | ||
62 | |||
63 | #define AD7998_CONV_RES_REG 0x0 | ||
64 | #define AD7998_ALERT_STAT_REG 0x1 | ||
65 | #define AD7998_CONF_REG 0x2 | ||
66 | #define AD7998_CYCLE_TMR_REG 0x3 | ||
67 | |||
68 | #define AD7998_DATALOW_REG(x) ((x) * 3 + 0x4) | ||
69 | #define AD7998_DATAHIGH_REG(x) ((x) * 3 + 0x5) | ||
70 | #define AD7998_HYST_REG(x) ((x) * 3 + 0x6) | ||
71 | |||
72 | #define AD7998_CYC_MASK 0x7 | ||
73 | #define AD7998_CYC_DIS 0x0 | ||
74 | #define AD7998_CYC_TCONF_32 0x1 | ||
75 | #define AD7998_CYC_TCONF_64 0x2 | ||
76 | #define AD7998_CYC_TCONF_128 0x3 | ||
77 | #define AD7998_CYC_TCONF_256 0x4 | ||
78 | #define AD7998_CYC_TCONF_512 0x5 | ||
79 | #define AD7998_CYC_TCONF_1024 0x6 | ||
80 | #define AD7998_CYC_TCONF_2048 0x7 | ||
81 | |||
82 | #define AD7998_ALERT_STAT_CLEAR 0xFF | ||
83 | |||
84 | /* | ||
85 | * AD7997 and AD7997 defines | ||
86 | */ | ||
87 | |||
88 | #define AD7997_8_READ_SINGLE 0x80 | ||
89 | #define AD7997_8_READ_SEQUENCE 0x70 | ||
90 | /* TODO: move this into a common header */ | ||
91 | #define RES_MASK(bits) ((1 << (bits)) - 1) | ||
92 | |||
93 | enum { | ||
94 | ad7991, | ||
95 | ad7995, | ||
96 | ad7999, | ||
97 | ad7992, | ||
98 | ad7993, | ||
99 | ad7994, | ||
100 | ad7997, | ||
101 | ad7998 | ||
102 | }; | ||
103 | |||
104 | /** | ||
105 | * struct ad799x_chip_info - chip specific information | ||
106 | * @channel: channel specification | ||
107 | * @num_channels: number of channels | ||
108 | * @monitor_mode: whether the chip supports monitor interrupts | ||
109 | * @default_config: device default configuration | ||
110 | * @event_attrs: pointer to the monitor event attribute group | ||
111 | */ | ||
112 | struct ad799x_chip_info { | ||
113 | struct iio_chan_spec channel[9]; | ||
114 | int num_channels; | ||
115 | u16 default_config; | ||
116 | const struct iio_info *info; | ||
117 | }; | ||
118 | |||
119 | struct ad799x_state { | ||
120 | struct i2c_client *client; | ||
121 | const struct ad799x_chip_info *chip_info; | ||
122 | struct regulator *reg; | ||
123 | struct regulator *vref; | ||
124 | unsigned id; | ||
125 | u16 config; | ||
126 | |||
127 | u8 *rx_buf; | ||
128 | unsigned int transfer_size; | ||
129 | }; | ||
130 | |||
131 | /** | ||
132 | * ad799x_trigger_handler() bh of trigger launched polling to ring buffer | ||
133 | * | ||
134 | * Currently there is no option in this driver to disable the saving of | ||
135 | * timestamps within the ring. | ||
136 | **/ | ||
137 | static irqreturn_t ad799x_trigger_handler(int irq, void *p) | ||
138 | { | ||
139 | struct iio_poll_func *pf = p; | ||
140 | struct iio_dev *indio_dev = pf->indio_dev; | ||
141 | struct ad799x_state *st = iio_priv(indio_dev); | ||
142 | int b_sent; | ||
143 | u8 cmd; | ||
144 | |||
145 | switch (st->id) { | ||
146 | case ad7991: | ||
147 | case ad7995: | ||
148 | case ad7999: | ||
149 | cmd = st->config | | ||
150 | (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT); | ||
151 | break; | ||
152 | case ad7992: | ||
153 | case ad7993: | ||
154 | case ad7994: | ||
155 | cmd = (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT) | | ||
156 | AD7998_CONV_RES_REG; | ||
157 | break; | ||
158 | case ad7997: | ||
159 | case ad7998: | ||
160 | cmd = AD7997_8_READ_SEQUENCE | AD7998_CONV_RES_REG; | ||
161 | break; | ||
162 | default: | ||
163 | cmd = 0; | ||
164 | } | ||
165 | |||
166 | b_sent = i2c_smbus_read_i2c_block_data(st->client, | ||
167 | cmd, st->transfer_size, st->rx_buf); | ||
168 | if (b_sent < 0) | ||
169 | goto out; | ||
170 | |||
171 | iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, | ||
172 | iio_get_time_ns()); | ||
173 | out: | ||
174 | iio_trigger_notify_done(indio_dev->trig); | ||
175 | |||
176 | return IRQ_HANDLED; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * ad799x register access by I2C | ||
181 | */ | ||
182 | static int ad799x_i2c_read16(struct ad799x_state *st, u8 reg, u16 *data) | ||
183 | { | ||
184 | struct i2c_client *client = st->client; | ||
185 | int ret = 0; | ||
186 | |||
187 | ret = i2c_smbus_read_word_swapped(client, reg); | ||
188 | if (ret < 0) { | ||
189 | dev_err(&client->dev, "I2C read error\n"); | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | *data = (u16)ret; | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static int ad799x_i2c_read8(struct ad799x_state *st, u8 reg, u8 *data) | ||
199 | { | ||
200 | struct i2c_client *client = st->client; | ||
201 | int ret = 0; | ||
202 | |||
203 | ret = i2c_smbus_read_byte_data(client, reg); | ||
204 | if (ret < 0) { | ||
205 | dev_err(&client->dev, "I2C read error\n"); | ||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | *data = (u8)ret; | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int ad799x_i2c_write16(struct ad799x_state *st, u8 reg, u16 data) | ||
215 | { | ||
216 | struct i2c_client *client = st->client; | ||
217 | int ret = 0; | ||
218 | |||
219 | ret = i2c_smbus_write_word_swapped(client, reg, data); | ||
220 | if (ret < 0) | ||
221 | dev_err(&client->dev, "I2C write error\n"); | ||
222 | |||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static int ad799x_i2c_write8(struct ad799x_state *st, u8 reg, u8 data) | ||
227 | { | ||
228 | struct i2c_client *client = st->client; | ||
229 | int ret = 0; | ||
230 | |||
231 | ret = i2c_smbus_write_byte_data(client, reg, data); | ||
232 | if (ret < 0) | ||
233 | dev_err(&client->dev, "I2C write error\n"); | ||
234 | |||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | static int ad7997_8_update_scan_mode(struct iio_dev *indio_dev, | ||
239 | const unsigned long *scan_mask) | ||
240 | { | ||
241 | struct ad799x_state *st = iio_priv(indio_dev); | ||
242 | |||
243 | kfree(st->rx_buf); | ||
244 | st->rx_buf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); | ||
245 | if (!st->rx_buf) | ||
246 | return -ENOMEM; | ||
247 | |||
248 | st->transfer_size = bitmap_weight(scan_mask, indio_dev->masklength) * 2; | ||
249 | |||
250 | switch (st->id) { | ||
251 | case ad7997: | ||
252 | case ad7998: | ||
253 | return ad799x_i2c_write16(st, AD7998_CONF_REG, | ||
254 | st->config | (*scan_mask << AD799X_CHANNEL_SHIFT)); | ||
255 | default: | ||
256 | break; | ||
257 | } | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch) | ||
263 | { | ||
264 | u16 rxbuf; | ||
265 | u8 cmd; | ||
266 | int ret; | ||
267 | |||
268 | switch (st->id) { | ||
269 | case ad7991: | ||
270 | case ad7995: | ||
271 | case ad7999: | ||
272 | cmd = st->config | ((1 << ch) << AD799X_CHANNEL_SHIFT); | ||
273 | break; | ||
274 | case ad7992: | ||
275 | case ad7993: | ||
276 | case ad7994: | ||
277 | cmd = (1 << ch) << AD799X_CHANNEL_SHIFT; | ||
278 | break; | ||
279 | case ad7997: | ||
280 | case ad7998: | ||
281 | cmd = (ch << AD799X_CHANNEL_SHIFT) | AD7997_8_READ_SINGLE; | ||
282 | break; | ||
283 | default: | ||
284 | return -EINVAL; | ||
285 | } | ||
286 | |||
287 | ret = ad799x_i2c_read16(st, cmd, &rxbuf); | ||
288 | if (ret < 0) | ||
289 | return ret; | ||
290 | |||
291 | return rxbuf; | ||
292 | } | ||
293 | |||
294 | static int ad799x_read_raw(struct iio_dev *indio_dev, | ||
295 | struct iio_chan_spec const *chan, | ||
296 | int *val, | ||
297 | int *val2, | ||
298 | long m) | ||
299 | { | ||
300 | int ret; | ||
301 | struct ad799x_state *st = iio_priv(indio_dev); | ||
302 | |||
303 | switch (m) { | ||
304 | case IIO_CHAN_INFO_RAW: | ||
305 | mutex_lock(&indio_dev->mlock); | ||
306 | if (iio_buffer_enabled(indio_dev)) | ||
307 | ret = -EBUSY; | ||
308 | else | ||
309 | ret = ad799x_scan_direct(st, chan->scan_index); | ||
310 | mutex_unlock(&indio_dev->mlock); | ||
311 | |||
312 | if (ret < 0) | ||
313 | return ret; | ||
314 | *val = (ret >> chan->scan_type.shift) & | ||
315 | RES_MASK(chan->scan_type.realbits); | ||
316 | return IIO_VAL_INT; | ||
317 | case IIO_CHAN_INFO_SCALE: | ||
318 | ret = regulator_get_voltage(st->vref); | ||
319 | if (ret < 0) | ||
320 | return ret; | ||
321 | *val = ret / 1000; | ||
322 | *val2 = chan->scan_type.realbits; | ||
323 | return IIO_VAL_FRACTIONAL_LOG2; | ||
324 | } | ||
325 | return -EINVAL; | ||
326 | } | ||
327 | static const unsigned int ad7998_frequencies[] = { | ||
328 | [AD7998_CYC_DIS] = 0, | ||
329 | [AD7998_CYC_TCONF_32] = 15625, | ||
330 | [AD7998_CYC_TCONF_64] = 7812, | ||
331 | [AD7998_CYC_TCONF_128] = 3906, | ||
332 | [AD7998_CYC_TCONF_512] = 976, | ||
333 | [AD7998_CYC_TCONF_1024] = 488, | ||
334 | [AD7998_CYC_TCONF_2048] = 244, | ||
335 | }; | ||
336 | static ssize_t ad799x_read_frequency(struct device *dev, | ||
337 | struct device_attribute *attr, | ||
338 | char *buf) | ||
339 | { | ||
340 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
341 | struct ad799x_state *st = iio_priv(indio_dev); | ||
342 | |||
343 | int ret; | ||
344 | u8 val; | ||
345 | ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &val); | ||
346 | if (ret) | ||
347 | return ret; | ||
348 | |||
349 | val &= AD7998_CYC_MASK; | ||
350 | |||
351 | return sprintf(buf, "%u\n", ad7998_frequencies[val]); | ||
352 | } | ||
353 | |||
354 | static ssize_t ad799x_write_frequency(struct device *dev, | ||
355 | struct device_attribute *attr, | ||
356 | const char *buf, | ||
357 | size_t len) | ||
358 | { | ||
359 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
360 | struct ad799x_state *st = iio_priv(indio_dev); | ||
361 | |||
362 | long val; | ||
363 | int ret, i; | ||
364 | u8 t; | ||
365 | |||
366 | ret = kstrtol(buf, 10, &val); | ||
367 | if (ret) | ||
368 | return ret; | ||
369 | |||
370 | mutex_lock(&indio_dev->mlock); | ||
371 | ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &t); | ||
372 | if (ret) | ||
373 | goto error_ret_mutex; | ||
374 | /* Wipe the bits clean */ | ||
375 | t &= ~AD7998_CYC_MASK; | ||
376 | |||
377 | for (i = 0; i < ARRAY_SIZE(ad7998_frequencies); i++) | ||
378 | if (val == ad7998_frequencies[i]) | ||
379 | break; | ||
380 | if (i == ARRAY_SIZE(ad7998_frequencies)) { | ||
381 | ret = -EINVAL; | ||
382 | goto error_ret_mutex; | ||
383 | } | ||
384 | t |= i; | ||
385 | ret = ad799x_i2c_write8(st, AD7998_CYCLE_TMR_REG, t); | ||
386 | |||
387 | error_ret_mutex: | ||
388 | mutex_unlock(&indio_dev->mlock); | ||
389 | |||
390 | return ret ? ret : len; | ||
391 | } | ||
392 | |||
393 | static int ad799x_read_event_config(struct iio_dev *indio_dev, | ||
394 | const struct iio_chan_spec *chan, | ||
395 | enum iio_event_type type, | ||
396 | enum iio_event_direction dir) | ||
397 | { | ||
398 | return 1; | ||
399 | } | ||
400 | |||
401 | static unsigned int ad799x_threshold_reg(const struct iio_chan_spec *chan, | ||
402 | enum iio_event_direction dir, | ||
403 | enum iio_event_info info) | ||
404 | { | ||
405 | switch (info) { | ||
406 | case IIO_EV_INFO_VALUE: | ||
407 | if (dir == IIO_EV_DIR_FALLING) | ||
408 | return AD7998_DATALOW_REG(chan->channel); | ||
409 | else | ||
410 | return AD7998_DATAHIGH_REG(chan->channel); | ||
411 | case IIO_EV_INFO_HYSTERESIS: | ||
412 | return AD7998_HYST_REG(chan->channel); | ||
413 | default: | ||
414 | return -EINVAL; | ||
415 | } | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int ad799x_write_event_value(struct iio_dev *indio_dev, | ||
421 | const struct iio_chan_spec *chan, | ||
422 | enum iio_event_type type, | ||
423 | enum iio_event_direction dir, | ||
424 | enum iio_event_info info, | ||
425 | int val, int val2) | ||
426 | { | ||
427 | int ret; | ||
428 | struct ad799x_state *st = iio_priv(indio_dev); | ||
429 | |||
430 | mutex_lock(&indio_dev->mlock); | ||
431 | ret = ad799x_i2c_write16(st, ad799x_threshold_reg(chan, dir, info), | ||
432 | val); | ||
433 | mutex_unlock(&indio_dev->mlock); | ||
434 | |||
435 | return ret; | ||
436 | } | ||
437 | |||
438 | static int ad799x_read_event_value(struct iio_dev *indio_dev, | ||
439 | const struct iio_chan_spec *chan, | ||
440 | enum iio_event_type type, | ||
441 | enum iio_event_direction dir, | ||
442 | enum iio_event_info info, | ||
443 | int *val, int *val2) | ||
444 | { | ||
445 | int ret; | ||
446 | struct ad799x_state *st = iio_priv(indio_dev); | ||
447 | u16 valin; | ||
448 | |||
449 | mutex_lock(&indio_dev->mlock); | ||
450 | ret = ad799x_i2c_read16(st, ad799x_threshold_reg(chan, dir, info), | ||
451 | &valin); | ||
452 | mutex_unlock(&indio_dev->mlock); | ||
453 | if (ret < 0) | ||
454 | return ret; | ||
455 | *val = valin; | ||
456 | |||
457 | return IIO_VAL_INT; | ||
458 | } | ||
459 | |||
460 | static irqreturn_t ad799x_event_handler(int irq, void *private) | ||
461 | { | ||
462 | struct iio_dev *indio_dev = private; | ||
463 | struct ad799x_state *st = iio_priv(private); | ||
464 | u8 status; | ||
465 | int i, ret; | ||
466 | |||
467 | ret = ad799x_i2c_read8(st, AD7998_ALERT_STAT_REG, &status); | ||
468 | if (ret) | ||
469 | goto done; | ||
470 | |||
471 | if (!status) | ||
472 | goto done; | ||
473 | |||
474 | ad799x_i2c_write8(st, AD7998_ALERT_STAT_REG, AD7998_ALERT_STAT_CLEAR); | ||
475 | |||
476 | for (i = 0; i < 8; i++) { | ||
477 | if (status & (1 << i)) | ||
478 | iio_push_event(indio_dev, | ||
479 | i & 0x1 ? | ||
480 | IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, | ||
481 | (i >> 1), | ||
482 | IIO_EV_TYPE_THRESH, | ||
483 | IIO_EV_DIR_RISING) : | ||
484 | IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, | ||
485 | (i >> 1), | ||
486 | IIO_EV_TYPE_THRESH, | ||
487 | IIO_EV_DIR_FALLING), | ||
488 | iio_get_time_ns()); | ||
489 | } | ||
490 | |||
491 | done: | ||
492 | return IRQ_HANDLED; | ||
493 | } | ||
494 | |||
495 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, | ||
496 | ad799x_read_frequency, | ||
497 | ad799x_write_frequency); | ||
498 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("15625 7812 3906 1953 976 488 244 0"); | ||
499 | |||
500 | static struct attribute *ad799x_event_attributes[] = { | ||
501 | &iio_dev_attr_sampling_frequency.dev_attr.attr, | ||
502 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | ||
503 | NULL, | ||
504 | }; | ||
505 | |||
506 | static struct attribute_group ad799x_event_attrs_group = { | ||
507 | .attrs = ad799x_event_attributes, | ||
508 | .name = "events", | ||
509 | }; | ||
510 | |||
511 | static const struct iio_info ad7991_info = { | ||
512 | .read_raw = &ad799x_read_raw, | ||
513 | .driver_module = THIS_MODULE, | ||
514 | }; | ||
515 | |||
516 | static const struct iio_info ad7993_4_7_8_info = { | ||
517 | .read_raw = &ad799x_read_raw, | ||
518 | .event_attrs = &ad799x_event_attrs_group, | ||
519 | .read_event_config = &ad799x_read_event_config, | ||
520 | .read_event_value = &ad799x_read_event_value, | ||
521 | .write_event_value = &ad799x_write_event_value, | ||
522 | .driver_module = THIS_MODULE, | ||
523 | .update_scan_mode = ad7997_8_update_scan_mode, | ||
524 | }; | ||
525 | |||
526 | static const struct iio_event_spec ad799x_events[] = { | ||
527 | { | ||
528 | .type = IIO_EV_TYPE_THRESH, | ||
529 | .dir = IIO_EV_DIR_RISING, | ||
530 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | | ||
531 | BIT(IIO_EV_INFO_ENABLE), | ||
532 | }, { | ||
533 | .type = IIO_EV_TYPE_THRESH, | ||
534 | .dir = IIO_EV_DIR_FALLING, | ||
535 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | | ||
536 | BIT(IIO_EV_INFO_ENABLE), | ||
537 | }, { | ||
538 | .type = IIO_EV_TYPE_THRESH, | ||
539 | .dir = IIO_EV_DIR_EITHER, | ||
540 | .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS), | ||
541 | }, | ||
542 | }; | ||
543 | |||
544 | #define _AD799X_CHANNEL(_index, _realbits, _ev_spec, _num_ev_spec) { \ | ||
545 | .type = IIO_VOLTAGE, \ | ||
546 | .indexed = 1, \ | ||
547 | .channel = (_index), \ | ||
548 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
549 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | ||
550 | .scan_index = (_index), \ | ||
551 | .scan_type = { \ | ||
552 | .sign = 'u', \ | ||
553 | .realbits = (_realbits), \ | ||
554 | .storagebits = 16, \ | ||
555 | .shift = 12 - (_realbits), \ | ||
556 | .endianness = IIO_BE, \ | ||
557 | }, \ | ||
558 | .event_spec = _ev_spec, \ | ||
559 | .num_event_specs = _num_ev_spec, \ | ||
560 | } | ||
561 | |||
562 | #define AD799X_CHANNEL(_index, _realbits) \ | ||
563 | _AD799X_CHANNEL(_index, _realbits, NULL, 0) | ||
564 | |||
565 | #define AD799X_CHANNEL_WITH_EVENTS(_index, _realbits) \ | ||
566 | _AD799X_CHANNEL(_index, _realbits, ad799x_events, \ | ||
567 | ARRAY_SIZE(ad799x_events)) | ||
568 | |||
569 | static const struct ad799x_chip_info ad799x_chip_info_tbl[] = { | ||
570 | [ad7991] = { | ||
571 | .channel = { | ||
572 | AD799X_CHANNEL(0, 12), | ||
573 | AD799X_CHANNEL(1, 12), | ||
574 | AD799X_CHANNEL(2, 12), | ||
575 | AD799X_CHANNEL(3, 12), | ||
576 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
577 | }, | ||
578 | .num_channels = 5, | ||
579 | .info = &ad7991_info, | ||
580 | }, | ||
581 | [ad7995] = { | ||
582 | .channel = { | ||
583 | AD799X_CHANNEL(0, 10), | ||
584 | AD799X_CHANNEL(1, 10), | ||
585 | AD799X_CHANNEL(2, 10), | ||
586 | AD799X_CHANNEL(3, 10), | ||
587 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
588 | }, | ||
589 | .num_channels = 5, | ||
590 | .info = &ad7991_info, | ||
591 | }, | ||
592 | [ad7999] = { | ||
593 | .channel = { | ||
594 | AD799X_CHANNEL(0, 8), | ||
595 | AD799X_CHANNEL(1, 8), | ||
596 | AD799X_CHANNEL(2, 8), | ||
597 | AD799X_CHANNEL(3, 8), | ||
598 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
599 | }, | ||
600 | .num_channels = 5, | ||
601 | .info = &ad7991_info, | ||
602 | }, | ||
603 | [ad7992] = { | ||
604 | .channel = { | ||
605 | AD799X_CHANNEL_WITH_EVENTS(0, 12), | ||
606 | AD799X_CHANNEL_WITH_EVENTS(1, 12), | ||
607 | IIO_CHAN_SOFT_TIMESTAMP(3), | ||
608 | }, | ||
609 | .num_channels = 3, | ||
610 | .default_config = AD7998_ALERT_EN, | ||
611 | .info = &ad7993_4_7_8_info, | ||
612 | }, | ||
613 | [ad7993] = { | ||
614 | .channel = { | ||
615 | AD799X_CHANNEL_WITH_EVENTS(0, 10), | ||
616 | AD799X_CHANNEL_WITH_EVENTS(1, 10), | ||
617 | AD799X_CHANNEL_WITH_EVENTS(2, 10), | ||
618 | AD799X_CHANNEL_WITH_EVENTS(3, 10), | ||
619 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
620 | }, | ||
621 | .num_channels = 5, | ||
622 | .default_config = AD7998_ALERT_EN, | ||
623 | .info = &ad7993_4_7_8_info, | ||
624 | }, | ||
625 | [ad7994] = { | ||
626 | .channel = { | ||
627 | AD799X_CHANNEL_WITH_EVENTS(0, 12), | ||
628 | AD799X_CHANNEL_WITH_EVENTS(1, 12), | ||
629 | AD799X_CHANNEL_WITH_EVENTS(2, 12), | ||
630 | AD799X_CHANNEL_WITH_EVENTS(3, 12), | ||
631 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
632 | }, | ||
633 | .num_channels = 5, | ||
634 | .default_config = AD7998_ALERT_EN, | ||
635 | .info = &ad7993_4_7_8_info, | ||
636 | }, | ||
637 | [ad7997] = { | ||
638 | .channel = { | ||
639 | AD799X_CHANNEL_WITH_EVENTS(0, 10), | ||
640 | AD799X_CHANNEL_WITH_EVENTS(1, 10), | ||
641 | AD799X_CHANNEL_WITH_EVENTS(2, 10), | ||
642 | AD799X_CHANNEL_WITH_EVENTS(3, 10), | ||
643 | AD799X_CHANNEL(4, 10), | ||
644 | AD799X_CHANNEL(5, 10), | ||
645 | AD799X_CHANNEL(6, 10), | ||
646 | AD799X_CHANNEL(7, 10), | ||
647 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
648 | }, | ||
649 | .num_channels = 9, | ||
650 | .default_config = AD7998_ALERT_EN, | ||
651 | .info = &ad7993_4_7_8_info, | ||
652 | }, | ||
653 | [ad7998] = { | ||
654 | .channel = { | ||
655 | AD799X_CHANNEL_WITH_EVENTS(0, 12), | ||
656 | AD799X_CHANNEL_WITH_EVENTS(1, 12), | ||
657 | AD799X_CHANNEL_WITH_EVENTS(2, 12), | ||
658 | AD799X_CHANNEL_WITH_EVENTS(3, 12), | ||
659 | AD799X_CHANNEL(4, 12), | ||
660 | AD799X_CHANNEL(5, 12), | ||
661 | AD799X_CHANNEL(6, 12), | ||
662 | AD799X_CHANNEL(7, 12), | ||
663 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
664 | }, | ||
665 | .num_channels = 9, | ||
666 | .default_config = AD7998_ALERT_EN, | ||
667 | .info = &ad7993_4_7_8_info, | ||
668 | }, | ||
669 | }; | ||
670 | |||
671 | static int ad799x_probe(struct i2c_client *client, | ||
672 | const struct i2c_device_id *id) | ||
673 | { | ||
674 | int ret; | ||
675 | struct ad799x_state *st; | ||
676 | struct iio_dev *indio_dev; | ||
677 | |||
678 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); | ||
679 | if (indio_dev == NULL) | ||
680 | return -ENOMEM; | ||
681 | |||
682 | st = iio_priv(indio_dev); | ||
683 | /* this is only used for device removal purposes */ | ||
684 | i2c_set_clientdata(client, indio_dev); | ||
685 | |||
686 | st->id = id->driver_data; | ||
687 | st->chip_info = &ad799x_chip_info_tbl[st->id]; | ||
688 | st->config = st->chip_info->default_config; | ||
689 | |||
690 | /* TODO: Add pdata options for filtering and bit delay */ | ||
691 | |||
692 | st->reg = devm_regulator_get(&client->dev, "vcc"); | ||
693 | if (IS_ERR(st->reg)) | ||
694 | return PTR_ERR(st->reg); | ||
695 | ret = regulator_enable(st->reg); | ||
696 | if (ret) | ||
697 | return ret; | ||
698 | st->vref = devm_regulator_get(&client->dev, "vref"); | ||
699 | if (IS_ERR(st->vref)) { | ||
700 | ret = PTR_ERR(st->vref); | ||
701 | goto error_disable_reg; | ||
702 | } | ||
703 | ret = regulator_enable(st->vref); | ||
704 | if (ret) | ||
705 | goto error_disable_reg; | ||
706 | |||
707 | st->client = client; | ||
708 | |||
709 | indio_dev->dev.parent = &client->dev; | ||
710 | indio_dev->name = id->name; | ||
711 | indio_dev->info = st->chip_info->info; | ||
712 | |||
713 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
714 | indio_dev->channels = st->chip_info->channel; | ||
715 | indio_dev->num_channels = st->chip_info->num_channels; | ||
716 | |||
717 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | ||
718 | &ad799x_trigger_handler, NULL); | ||
719 | if (ret) | ||
720 | goto error_disable_vref; | ||
721 | |||
722 | if (client->irq > 0) { | ||
723 | ret = devm_request_threaded_irq(&client->dev, | ||
724 | client->irq, | ||
725 | NULL, | ||
726 | ad799x_event_handler, | ||
727 | IRQF_TRIGGER_FALLING | | ||
728 | IRQF_ONESHOT, | ||
729 | client->name, | ||
730 | indio_dev); | ||
731 | if (ret) | ||
732 | goto error_cleanup_ring; | ||
733 | } | ||
734 | ret = iio_device_register(indio_dev); | ||
735 | if (ret) | ||
736 | goto error_cleanup_ring; | ||
737 | |||
738 | return 0; | ||
739 | |||
740 | error_cleanup_ring: | ||
741 | iio_triggered_buffer_cleanup(indio_dev); | ||
742 | error_disable_vref: | ||
743 | regulator_disable(st->vref); | ||
744 | error_disable_reg: | ||
745 | regulator_disable(st->reg); | ||
746 | |||
747 | return ret; | ||
748 | } | ||
749 | |||
750 | static int ad799x_remove(struct i2c_client *client) | ||
751 | { | ||
752 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
753 | struct ad799x_state *st = iio_priv(indio_dev); | ||
754 | |||
755 | iio_device_unregister(indio_dev); | ||
756 | |||
757 | iio_triggered_buffer_cleanup(indio_dev); | ||
758 | regulator_disable(st->vref); | ||
759 | regulator_disable(st->reg); | ||
760 | kfree(st->rx_buf); | ||
761 | |||
762 | return 0; | ||
763 | } | ||
764 | |||
765 | static const struct i2c_device_id ad799x_id[] = { | ||
766 | { "ad7991", ad7991 }, | ||
767 | { "ad7995", ad7995 }, | ||
768 | { "ad7999", ad7999 }, | ||
769 | { "ad7992", ad7992 }, | ||
770 | { "ad7993", ad7993 }, | ||
771 | { "ad7994", ad7994 }, | ||
772 | { "ad7997", ad7997 }, | ||
773 | { "ad7998", ad7998 }, | ||
774 | {} | ||
775 | }; | ||
776 | |||
777 | MODULE_DEVICE_TABLE(i2c, ad799x_id); | ||
778 | |||
779 | static struct i2c_driver ad799x_driver = { | ||
780 | .driver = { | ||
781 | .name = "ad799x", | ||
782 | }, | ||
783 | .probe = ad799x_probe, | ||
784 | .remove = ad799x_remove, | ||
785 | .id_table = ad799x_id, | ||
786 | }; | ||
787 | module_i2c_driver(ad799x_driver); | ||
788 | |||
789 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
790 | MODULE_DESCRIPTION("Analog Devices AD799x ADC"); | ||
791 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index affa93f51789..010578f1d762 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c | |||
@@ -82,7 +82,7 @@ enum adc_version { | |||
82 | #define ADC_CON_EN_START (1u << 0) | 82 | #define ADC_CON_EN_START (1u << 0) |
83 | #define ADC_DATX_MASK 0xFFF | 83 | #define ADC_DATX_MASK 0xFFF |
84 | 84 | ||
85 | #define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(1000)) | 85 | #define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(100)) |
86 | 86 | ||
87 | struct exynos_adc { | 87 | struct exynos_adc { |
88 | void __iomem *regs; | 88 | void __iomem *regs; |
@@ -112,6 +112,30 @@ static inline unsigned int exynos_adc_get_version(struct platform_device *pdev) | |||
112 | return (unsigned int)match->data; | 112 | return (unsigned int)match->data; |
113 | } | 113 | } |
114 | 114 | ||
115 | static void exynos_adc_hw_init(struct exynos_adc *info) | ||
116 | { | ||
117 | u32 con1, con2; | ||
118 | |||
119 | if (info->version == ADC_V2) { | ||
120 | con1 = ADC_V2_CON1_SOFT_RESET; | ||
121 | writel(con1, ADC_V2_CON1(info->regs)); | ||
122 | |||
123 | con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL | | ||
124 | ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0); | ||
125 | writel(con2, ADC_V2_CON2(info->regs)); | ||
126 | |||
127 | /* Enable interrupts */ | ||
128 | writel(1, ADC_V2_INT_EN(info->regs)); | ||
129 | } else { | ||
130 | /* set default prescaler values and Enable prescaler */ | ||
131 | con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN; | ||
132 | |||
133 | /* Enable 12-bit ADC resolution */ | ||
134 | con1 |= ADC_V1_CON_RES; | ||
135 | writel(con1, ADC_V1_CON(info->regs)); | ||
136 | } | ||
137 | } | ||
138 | |||
115 | static int exynos_read_raw(struct iio_dev *indio_dev, | 139 | static int exynos_read_raw(struct iio_dev *indio_dev, |
116 | struct iio_chan_spec const *chan, | 140 | struct iio_chan_spec const *chan, |
117 | int *val, | 141 | int *val, |
@@ -121,11 +145,13 @@ static int exynos_read_raw(struct iio_dev *indio_dev, | |||
121 | struct exynos_adc *info = iio_priv(indio_dev); | 145 | struct exynos_adc *info = iio_priv(indio_dev); |
122 | unsigned long timeout; | 146 | unsigned long timeout; |
123 | u32 con1, con2; | 147 | u32 con1, con2; |
148 | int ret; | ||
124 | 149 | ||
125 | if (mask != IIO_CHAN_INFO_RAW) | 150 | if (mask != IIO_CHAN_INFO_RAW) |
126 | return -EINVAL; | 151 | return -EINVAL; |
127 | 152 | ||
128 | mutex_lock(&indio_dev->mlock); | 153 | mutex_lock(&indio_dev->mlock); |
154 | reinit_completion(&info->completion); | ||
129 | 155 | ||
130 | /* Select the channel to be used and Trigger conversion */ | 156 | /* Select the channel to be used and Trigger conversion */ |
131 | if (info->version == ADC_V2) { | 157 | if (info->version == ADC_V2) { |
@@ -145,16 +171,21 @@ static int exynos_read_raw(struct iio_dev *indio_dev, | |||
145 | ADC_V1_CON(info->regs)); | 171 | ADC_V1_CON(info->regs)); |
146 | } | 172 | } |
147 | 173 | ||
148 | timeout = wait_for_completion_interruptible_timeout | 174 | timeout = wait_for_completion_timeout |
149 | (&info->completion, EXYNOS_ADC_TIMEOUT); | 175 | (&info->completion, EXYNOS_ADC_TIMEOUT); |
150 | *val = info->value; | 176 | if (timeout == 0) { |
177 | dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n"); | ||
178 | exynos_adc_hw_init(info); | ||
179 | ret = -ETIMEDOUT; | ||
180 | } else { | ||
181 | *val = info->value; | ||
182 | *val2 = 0; | ||
183 | ret = IIO_VAL_INT; | ||
184 | } | ||
151 | 185 | ||
152 | mutex_unlock(&indio_dev->mlock); | 186 | mutex_unlock(&indio_dev->mlock); |
153 | 187 | ||
154 | if (timeout == 0) | 188 | return ret; |
155 | return -ETIMEDOUT; | ||
156 | |||
157 | return IIO_VAL_INT; | ||
158 | } | 189 | } |
159 | 190 | ||
160 | static irqreturn_t exynos_adc_isr(int irq, void *dev_id) | 191 | static irqreturn_t exynos_adc_isr(int irq, void *dev_id) |
@@ -226,30 +257,6 @@ static int exynos_adc_remove_devices(struct device *dev, void *c) | |||
226 | return 0; | 257 | return 0; |
227 | } | 258 | } |
228 | 259 | ||
229 | static void exynos_adc_hw_init(struct exynos_adc *info) | ||
230 | { | ||
231 | u32 con1, con2; | ||
232 | |||
233 | if (info->version == ADC_V2) { | ||
234 | con1 = ADC_V2_CON1_SOFT_RESET; | ||
235 | writel(con1, ADC_V2_CON1(info->regs)); | ||
236 | |||
237 | con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL | | ||
238 | ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0); | ||
239 | writel(con2, ADC_V2_CON2(info->regs)); | ||
240 | |||
241 | /* Enable interrupts */ | ||
242 | writel(1, ADC_V2_INT_EN(info->regs)); | ||
243 | } else { | ||
244 | /* set default prescaler values and Enable prescaler */ | ||
245 | con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN; | ||
246 | |||
247 | /* Enable 12-bit ADC resolution */ | ||
248 | con1 |= ADC_V1_CON_RES; | ||
249 | writel(con1, ADC_V1_CON(info->regs)); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | static int exynos_adc_probe(struct platform_device *pdev) | 260 | static int exynos_adc_probe(struct platform_device *pdev) |
254 | { | 261 | { |
255 | struct exynos_adc *info = NULL; | 262 | struct exynos_adc *info = NULL; |
@@ -290,32 +297,30 @@ static int exynos_adc_probe(struct platform_device *pdev) | |||
290 | 297 | ||
291 | init_completion(&info->completion); | 298 | init_completion(&info->completion); |
292 | 299 | ||
293 | ret = request_irq(info->irq, exynos_adc_isr, | ||
294 | 0, dev_name(&pdev->dev), info); | ||
295 | if (ret < 0) { | ||
296 | dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", | ||
297 | info->irq); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | writel(1, info->enable_reg); | ||
302 | |||
303 | info->clk = devm_clk_get(&pdev->dev, "adc"); | 300 | info->clk = devm_clk_get(&pdev->dev, "adc"); |
304 | if (IS_ERR(info->clk)) { | 301 | if (IS_ERR(info->clk)) { |
305 | dev_err(&pdev->dev, "failed getting clock, err = %ld\n", | 302 | dev_err(&pdev->dev, "failed getting clock, err = %ld\n", |
306 | PTR_ERR(info->clk)); | 303 | PTR_ERR(info->clk)); |
307 | ret = PTR_ERR(info->clk); | 304 | return PTR_ERR(info->clk); |
308 | goto err_irq; | ||
309 | } | 305 | } |
310 | 306 | ||
311 | info->vdd = devm_regulator_get(&pdev->dev, "vdd"); | 307 | info->vdd = devm_regulator_get(&pdev->dev, "vdd"); |
312 | if (IS_ERR(info->vdd)) { | 308 | if (IS_ERR(info->vdd)) { |
313 | dev_err(&pdev->dev, "failed getting regulator, err = %ld\n", | 309 | dev_err(&pdev->dev, "failed getting regulator, err = %ld\n", |
314 | PTR_ERR(info->vdd)); | 310 | PTR_ERR(info->vdd)); |
315 | ret = PTR_ERR(info->vdd); | 311 | return PTR_ERR(info->vdd); |
316 | goto err_irq; | ||
317 | } | 312 | } |
318 | 313 | ||
314 | ret = regulator_enable(info->vdd); | ||
315 | if (ret) | ||
316 | return ret; | ||
317 | |||
318 | ret = clk_prepare_enable(info->clk); | ||
319 | if (ret) | ||
320 | goto err_disable_reg; | ||
321 | |||
322 | writel(1, info->enable_reg); | ||
323 | |||
319 | info->version = exynos_adc_get_version(pdev); | 324 | info->version = exynos_adc_get_version(pdev); |
320 | 325 | ||
321 | platform_set_drvdata(pdev, indio_dev); | 326 | platform_set_drvdata(pdev, indio_dev); |
@@ -332,16 +337,18 @@ static int exynos_adc_probe(struct platform_device *pdev) | |||
332 | else | 337 | else |
333 | indio_dev->num_channels = MAX_ADC_V2_CHANNELS; | 338 | indio_dev->num_channels = MAX_ADC_V2_CHANNELS; |
334 | 339 | ||
340 | ret = request_irq(info->irq, exynos_adc_isr, | ||
341 | 0, dev_name(&pdev->dev), info); | ||
342 | if (ret < 0) { | ||
343 | dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", | ||
344 | info->irq); | ||
345 | goto err_disable_clk; | ||
346 | } | ||
347 | |||
335 | ret = iio_device_register(indio_dev); | 348 | ret = iio_device_register(indio_dev); |
336 | if (ret) | 349 | if (ret) |
337 | goto err_irq; | 350 | goto err_irq; |
338 | 351 | ||
339 | ret = regulator_enable(info->vdd); | ||
340 | if (ret) | ||
341 | goto err_iio_dev; | ||
342 | |||
343 | clk_prepare_enable(info->clk); | ||
344 | |||
345 | exynos_adc_hw_init(info); | 352 | exynos_adc_hw_init(info); |
346 | 353 | ||
347 | ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev); | 354 | ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev); |
@@ -355,12 +362,14 @@ static int exynos_adc_probe(struct platform_device *pdev) | |||
355 | err_of_populate: | 362 | err_of_populate: |
356 | device_for_each_child(&indio_dev->dev, NULL, | 363 | device_for_each_child(&indio_dev->dev, NULL, |
357 | exynos_adc_remove_devices); | 364 | exynos_adc_remove_devices); |
358 | regulator_disable(info->vdd); | ||
359 | clk_disable_unprepare(info->clk); | ||
360 | err_iio_dev: | ||
361 | iio_device_unregister(indio_dev); | 365 | iio_device_unregister(indio_dev); |
362 | err_irq: | 366 | err_irq: |
363 | free_irq(info->irq, info); | 367 | free_irq(info->irq, info); |
368 | err_disable_clk: | ||
369 | writel(0, info->enable_reg); | ||
370 | clk_disable_unprepare(info->clk); | ||
371 | err_disable_reg: | ||
372 | regulator_disable(info->vdd); | ||
364 | return ret; | 373 | return ret; |
365 | } | 374 | } |
366 | 375 | ||
@@ -371,11 +380,11 @@ static int exynos_adc_remove(struct platform_device *pdev) | |||
371 | 380 | ||
372 | device_for_each_child(&indio_dev->dev, NULL, | 381 | device_for_each_child(&indio_dev->dev, NULL, |
373 | exynos_adc_remove_devices); | 382 | exynos_adc_remove_devices); |
374 | regulator_disable(info->vdd); | ||
375 | clk_disable_unprepare(info->clk); | ||
376 | writel(0, info->enable_reg); | ||
377 | iio_device_unregister(indio_dev); | 383 | iio_device_unregister(indio_dev); |
378 | free_irq(info->irq, info); | 384 | free_irq(info->irq, info); |
385 | writel(0, info->enable_reg); | ||
386 | clk_disable_unprepare(info->clk); | ||
387 | regulator_disable(info->vdd); | ||
379 | 388 | ||
380 | return 0; | 389 | return 0; |
381 | } | 390 | } |
@@ -397,8 +406,8 @@ static int exynos_adc_suspend(struct device *dev) | |||
397 | writel(con, ADC_V1_CON(info->regs)); | 406 | writel(con, ADC_V1_CON(info->regs)); |
398 | } | 407 | } |
399 | 408 | ||
400 | clk_disable_unprepare(info->clk); | ||
401 | writel(0, info->enable_reg); | 409 | writel(0, info->enable_reg); |
410 | clk_disable_unprepare(info->clk); | ||
402 | regulator_disable(info->vdd); | 411 | regulator_disable(info->vdd); |
403 | 412 | ||
404 | return 0; | 413 | return 0; |
@@ -414,9 +423,11 @@ static int exynos_adc_resume(struct device *dev) | |||
414 | if (ret) | 423 | if (ret) |
415 | return ret; | 424 | return ret; |
416 | 425 | ||
417 | writel(1, info->enable_reg); | 426 | ret = clk_prepare_enable(info->clk); |
418 | clk_prepare_enable(info->clk); | 427 | if (ret) |
428 | return ret; | ||
419 | 429 | ||
430 | writel(1, info->enable_reg); | ||
420 | exynos_adc_hw_init(info); | 431 | exynos_adc_hw_init(info); |
421 | 432 | ||
422 | return 0; | 433 | return 0; |
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index 9cf3229a7272..1b3b74be5c20 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c | |||
@@ -1252,8 +1252,8 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = { | |||
1252 | .num_modes = ARRAY_SIZE(max1238_mode_list), | 1252 | .num_modes = ARRAY_SIZE(max1238_mode_list), |
1253 | .default_mode = s0to11, | 1253 | .default_mode = s0to11, |
1254 | .info = &max1238_info, | 1254 | .info = &max1238_info, |
1255 | .channels = max1238_channels, | 1255 | .channels = max1038_channels, |
1256 | .num_channels = ARRAY_SIZE(max1238_channels), | 1256 | .num_channels = ARRAY_SIZE(max1038_channels), |
1257 | }, | 1257 | }, |
1258 | [max11605] = { | 1258 | [max11605] = { |
1259 | .bits = 8, | 1259 | .bits = 8, |
@@ -1262,8 +1262,8 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = { | |||
1262 | .num_modes = ARRAY_SIZE(max1238_mode_list), | 1262 | .num_modes = ARRAY_SIZE(max1238_mode_list), |
1263 | .default_mode = s0to11, | 1263 | .default_mode = s0to11, |
1264 | .info = &max1238_info, | 1264 | .info = &max1238_info, |
1265 | .channels = max1238_channels, | 1265 | .channels = max1038_channels, |
1266 | .num_channels = ARRAY_SIZE(max1238_channels), | 1266 | .num_channels = ARRAY_SIZE(max1038_channels), |
1267 | }, | 1267 | }, |
1268 | [max11606] = { | 1268 | [max11606] = { |
1269 | .bits = 10, | 1269 | .bits = 10, |
@@ -1312,8 +1312,8 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = { | |||
1312 | .num_modes = ARRAY_SIZE(max1238_mode_list), | 1312 | .num_modes = ARRAY_SIZE(max1238_mode_list), |
1313 | .default_mode = s0to11, | 1313 | .default_mode = s0to11, |
1314 | .info = &max1238_info, | 1314 | .info = &max1238_info, |
1315 | .channels = max1238_channels, | 1315 | .channels = max1138_channels, |
1316 | .num_channels = ARRAY_SIZE(max1238_channels), | 1316 | .num_channels = ARRAY_SIZE(max1138_channels), |
1317 | }, | 1317 | }, |
1318 | [max11611] = { | 1318 | [max11611] = { |
1319 | .bits = 10, | 1319 | .bits = 10, |
@@ -1322,8 +1322,8 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = { | |||
1322 | .num_modes = ARRAY_SIZE(max1238_mode_list), | 1322 | .num_modes = ARRAY_SIZE(max1238_mode_list), |
1323 | .default_mode = s0to11, | 1323 | .default_mode = s0to11, |
1324 | .info = &max1238_info, | 1324 | .info = &max1238_info, |
1325 | .channels = max1238_channels, | 1325 | .channels = max1138_channels, |
1326 | .num_channels = ARRAY_SIZE(max1238_channels), | 1326 | .num_channels = ARRAY_SIZE(max1138_channels), |
1327 | }, | 1327 | }, |
1328 | [max11612] = { | 1328 | [max11612] = { |
1329 | .bits = 12, | 1329 | .bits = 12, |
diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index 47dcb34ff44c..51672256072b 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c | |||
@@ -1,10 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * mcp3422.c - driver for the Microchip mcp3422/3/4 chip family | 2 | * mcp3422.c - driver for the Microchip mcp3422/3/4/6/7/8 chip family |
3 | * | 3 | * |
4 | * Copyright (C) 2013, Angelo Compagnucci | 4 | * Copyright (C) 2013, Angelo Compagnucci |
5 | * Author: Angelo Compagnucci <angelo.compagnucci@gmail.com> | 5 | * Author: Angelo Compagnucci <angelo.compagnucci@gmail.com> |
6 | * | 6 | * |
7 | * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf | 7 | * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf |
8 | * http://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf | ||
8 | * | 9 | * |
9 | * This driver exports the value of analog input voltage to sysfs, the | 10 | * This driver exports the value of analog input voltage to sysfs, the |
10 | * voltage unit is nV. | 11 | * voltage unit is nV. |
@@ -96,6 +97,7 @@ static const int mcp3422_sign_extend[4] = { | |||
96 | /* Client data (each client gets its own) */ | 97 | /* Client data (each client gets its own) */ |
97 | struct mcp3422 { | 98 | struct mcp3422 { |
98 | struct i2c_client *i2c; | 99 | struct i2c_client *i2c; |
100 | u8 id; | ||
99 | u8 config; | 101 | u8 config; |
100 | u8 pga[4]; | 102 | u8 pga[4]; |
101 | struct mutex lock; | 103 | struct mutex lock; |
@@ -238,6 +240,8 @@ static int mcp3422_write_raw(struct iio_dev *iio, | |||
238 | temp = MCP3422_SRATE_15; | 240 | temp = MCP3422_SRATE_15; |
239 | break; | 241 | break; |
240 | case 3: | 242 | case 3: |
243 | if (adc->id > 4) | ||
244 | return -EINVAL; | ||
241 | temp = MCP3422_SRATE_3; | 245 | temp = MCP3422_SRATE_3; |
242 | break; | 246 | break; |
243 | default: | 247 | default: |
@@ -271,6 +275,17 @@ static int mcp3422_write_raw_get_fmt(struct iio_dev *indio_dev, | |||
271 | } | 275 | } |
272 | } | 276 | } |
273 | 277 | ||
278 | static ssize_t mcp3422_show_samp_freqs(struct device *dev, | ||
279 | struct device_attribute *attr, char *buf) | ||
280 | { | ||
281 | struct mcp3422 *adc = iio_priv(dev_to_iio_dev(dev)); | ||
282 | |||
283 | if (adc->id > 4) | ||
284 | return sprintf(buf, "240 60 15\n"); | ||
285 | |||
286 | return sprintf(buf, "240 60 15 3\n"); | ||
287 | } | ||
288 | |||
274 | static ssize_t mcp3422_show_scales(struct device *dev, | 289 | static ssize_t mcp3422_show_scales(struct device *dev, |
275 | struct device_attribute *attr, char *buf) | 290 | struct device_attribute *attr, char *buf) |
276 | { | 291 | { |
@@ -284,12 +299,13 @@ static ssize_t mcp3422_show_scales(struct device *dev, | |||
284 | mcp3422_scales[sample_rate][3]); | 299 | mcp3422_scales[sample_rate][3]); |
285 | } | 300 | } |
286 | 301 | ||
287 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("240 60 15 3"); | 302 | static IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO, |
303 | mcp3422_show_samp_freqs, NULL, 0); | ||
288 | static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, | 304 | static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, |
289 | mcp3422_show_scales, NULL, 0); | 305 | mcp3422_show_scales, NULL, 0); |
290 | 306 | ||
291 | static struct attribute *mcp3422_attributes[] = { | 307 | static struct attribute *mcp3422_attributes[] = { |
292 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | 308 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, |
293 | &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, | 309 | &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, |
294 | NULL, | 310 | NULL, |
295 | }; | 311 | }; |
@@ -335,6 +351,7 @@ static int mcp3422_probe(struct i2c_client *client, | |||
335 | 351 | ||
336 | adc = iio_priv(indio_dev); | 352 | adc = iio_priv(indio_dev); |
337 | adc->i2c = client; | 353 | adc->i2c = client; |
354 | adc->id = (u8)(id->driver_data); | ||
338 | 355 | ||
339 | mutex_init(&adc->lock); | 356 | mutex_init(&adc->lock); |
340 | 357 | ||
@@ -343,13 +360,16 @@ static int mcp3422_probe(struct i2c_client *client, | |||
343 | indio_dev->modes = INDIO_DIRECT_MODE; | 360 | indio_dev->modes = INDIO_DIRECT_MODE; |
344 | indio_dev->info = &mcp3422_info; | 361 | indio_dev->info = &mcp3422_info; |
345 | 362 | ||
346 | switch ((unsigned int)(id->driver_data)) { | 363 | switch (adc->id) { |
347 | case 2: | 364 | case 2: |
348 | case 3: | 365 | case 3: |
366 | case 6: | ||
367 | case 7: | ||
349 | indio_dev->channels = mcp3422_channels; | 368 | indio_dev->channels = mcp3422_channels; |
350 | indio_dev->num_channels = ARRAY_SIZE(mcp3422_channels); | 369 | indio_dev->num_channels = ARRAY_SIZE(mcp3422_channels); |
351 | break; | 370 | break; |
352 | case 4: | 371 | case 4: |
372 | case 8: | ||
353 | indio_dev->channels = mcp3424_channels; | 373 | indio_dev->channels = mcp3424_channels; |
354 | indio_dev->num_channels = ARRAY_SIZE(mcp3424_channels); | 374 | indio_dev->num_channels = ARRAY_SIZE(mcp3424_channels); |
355 | break; | 375 | break; |
@@ -375,6 +395,9 @@ static const struct i2c_device_id mcp3422_id[] = { | |||
375 | { "mcp3422", 2 }, | 395 | { "mcp3422", 2 }, |
376 | { "mcp3423", 3 }, | 396 | { "mcp3423", 3 }, |
377 | { "mcp3424", 4 }, | 397 | { "mcp3424", 4 }, |
398 | { "mcp3426", 6 }, | ||
399 | { "mcp3427", 7 }, | ||
400 | { "mcp3428", 8 }, | ||
378 | { } | 401 | { } |
379 | }; | 402 | }; |
380 | MODULE_DEVICE_TABLE(i2c, mcp3422_id); | 403 | MODULE_DEVICE_TABLE(i2c, mcp3422_id); |
@@ -399,5 +422,5 @@ static struct i2c_driver mcp3422_driver = { | |||
399 | module_i2c_driver(mcp3422_driver); | 422 | module_i2c_driver(mcp3422_driver); |
400 | 423 | ||
401 | MODULE_AUTHOR("Angelo Compagnucci <angelo.compagnucci@gmail.com>"); | 424 | MODULE_AUTHOR("Angelo Compagnucci <angelo.compagnucci@gmail.com>"); |
402 | MODULE_DESCRIPTION("Microchip mcp3422/3/4 driver"); | 425 | MODULE_DESCRIPTION("Microchip mcp3422/3/4/6/7/8 driver"); |
403 | MODULE_LICENSE("GPL v2"); | 426 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index 75b54730a963..403dd3d8986e 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c | |||
@@ -26,6 +26,40 @@ | |||
26 | #include <linux/iio/iio.h> | 26 | #include <linux/iio/iio.h> |
27 | #include <linux/iio/sysfs.h> | 27 | #include <linux/iio/sysfs.h> |
28 | 28 | ||
29 | struct { | ||
30 | u32 usage_id; | ||
31 | int unit; /* 0 for default others from HID sensor spec */ | ||
32 | int scale_val0; /* scale, whole number */ | ||
33 | int scale_val1; /* scale, fraction in micros */ | ||
34 | } static unit_conversion[] = { | ||
35 | {HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650}, | ||
36 | {HID_USAGE_SENSOR_ACCEL_3D, | ||
37 | HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0}, | ||
38 | {HID_USAGE_SENSOR_ACCEL_3D, | ||
39 | HID_USAGE_SENSOR_UNITS_G, 9, 806650}, | ||
40 | |||
41 | {HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453}, | ||
42 | {HID_USAGE_SENSOR_GYRO_3D, | ||
43 | HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND, 1, 0}, | ||
44 | {HID_USAGE_SENSOR_GYRO_3D, | ||
45 | HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453}, | ||
46 | |||
47 | {HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000}, | ||
48 | {HID_USAGE_SENSOR_COMPASS_3D, HID_USAGE_SENSOR_UNITS_GAUSS, 1, 0}, | ||
49 | |||
50 | {HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453}, | ||
51 | {HID_USAGE_SENSOR_INCLINOMETER_3D, | ||
52 | HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453}, | ||
53 | {HID_USAGE_SENSOR_INCLINOMETER_3D, | ||
54 | HID_USAGE_SENSOR_UNITS_RADIANS, 1, 0}, | ||
55 | |||
56 | {HID_USAGE_SENSOR_ALS, 0, 1, 0}, | ||
57 | {HID_USAGE_SENSOR_ALS, HID_USAGE_SENSOR_UNITS_LUX, 1, 0}, | ||
58 | |||
59 | {HID_USAGE_SENSOR_PRESSURE, 0, 100000, 0}, | ||
60 | {HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 1, 0}, | ||
61 | }; | ||
62 | |||
29 | static int pow_10(unsigned power) | 63 | static int pow_10(unsigned power) |
30 | { | 64 | { |
31 | int i; | 65 | int i; |
@@ -113,6 +147,26 @@ static u32 convert_to_vtf_format(int size, int exp, int val1, int val2) | |||
113 | return value; | 147 | return value; |
114 | } | 148 | } |
115 | 149 | ||
150 | s32 hid_sensor_read_poll_value(struct hid_sensor_common *st) | ||
151 | { | ||
152 | s32 value = 0; | ||
153 | int ret; | ||
154 | |||
155 | ret = sensor_hub_get_feature(st->hsdev, | ||
156 | st->poll.report_id, | ||
157 | st->poll.index, &value); | ||
158 | |||
159 | if (ret < 0 || value < 0) { | ||
160 | return -EINVAL; | ||
161 | } else { | ||
162 | if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) | ||
163 | value = value * 1000; | ||
164 | } | ||
165 | |||
166 | return value; | ||
167 | } | ||
168 | EXPORT_SYMBOL(hid_sensor_read_poll_value); | ||
169 | |||
116 | int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, | 170 | int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, |
117 | int *val1, int *val2) | 171 | int *val1, int *val2) |
118 | { | 172 | { |
@@ -209,15 +263,108 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, | |||
209 | } | 263 | } |
210 | EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); | 264 | EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); |
211 | 265 | ||
212 | int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, | 266 | /* |
267 | * This fuction applies the unit exponent to the scale. | ||
268 | * For example: | ||
269 | * 9.806650 ->exp:2-> val0[980]val1[665000] | ||
270 | * 9.000806 ->exp:2-> val0[900]val1[80600] | ||
271 | * 0.174535 ->exp:2-> val0[17]val1[453500] | ||
272 | * 1.001745 ->exp:0-> val0[1]val1[1745] | ||
273 | * 1.001745 ->exp:2-> val0[100]val1[174500] | ||
274 | * 1.001745 ->exp:4-> val0[10017]val1[450000] | ||
275 | * 9.806650 ->exp:-2-> val0[0]val1[98066] | ||
276 | */ | ||
277 | static void adjust_exponent_micro(int *val0, int *val1, int scale0, | ||
278 | int scale1, int exp) | ||
279 | { | ||
280 | int i; | ||
281 | int x; | ||
282 | int res; | ||
283 | int rem; | ||
284 | |||
285 | if (exp > 0) { | ||
286 | *val0 = scale0 * pow_10(exp); | ||
287 | res = 0; | ||
288 | if (exp > 6) { | ||
289 | *val1 = 0; | ||
290 | return; | ||
291 | } | ||
292 | for (i = 0; i < exp; ++i) { | ||
293 | x = scale1 / pow_10(5 - i); | ||
294 | res += (pow_10(exp - 1 - i) * x); | ||
295 | scale1 = scale1 % pow_10(5 - i); | ||
296 | } | ||
297 | *val0 += res; | ||
298 | *val1 = scale1 * pow_10(exp); | ||
299 | } else if (exp < 0) { | ||
300 | exp = abs(exp); | ||
301 | if (exp > 6) { | ||
302 | *val0 = *val1 = 0; | ||
303 | return; | ||
304 | } | ||
305 | *val0 = scale0 / pow_10(exp); | ||
306 | rem = scale0 % pow_10(exp); | ||
307 | res = 0; | ||
308 | for (i = 0; i < (6 - exp); ++i) { | ||
309 | x = scale1 / pow_10(5 - i); | ||
310 | res += (pow_10(5 - exp - i) * x); | ||
311 | scale1 = scale1 % pow_10(5 - i); | ||
312 | } | ||
313 | *val1 = rem * pow_10(6 - exp) + res; | ||
314 | } else { | ||
315 | *val0 = scale0; | ||
316 | *val1 = scale1; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | int hid_sensor_format_scale(u32 usage_id, | ||
321 | struct hid_sensor_hub_attribute_info *attr_info, | ||
322 | int *val0, int *val1) | ||
323 | { | ||
324 | int i; | ||
325 | int exp; | ||
326 | |||
327 | *val0 = 1; | ||
328 | *val1 = 0; | ||
329 | |||
330 | for (i = 0; i < ARRAY_SIZE(unit_conversion); ++i) { | ||
331 | if (unit_conversion[i].usage_id == usage_id && | ||
332 | unit_conversion[i].unit == attr_info->units) { | ||
333 | exp = hid_sensor_convert_exponent( | ||
334 | attr_info->unit_expo); | ||
335 | adjust_exponent_micro(val0, val1, | ||
336 | unit_conversion[i].scale_val0, | ||
337 | unit_conversion[i].scale_val1, exp); | ||
338 | break; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | return IIO_VAL_INT_PLUS_MICRO; | ||
343 | } | ||
344 | EXPORT_SYMBOL(hid_sensor_format_scale); | ||
345 | |||
346 | int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev, | ||
213 | u32 usage_id, | 347 | u32 usage_id, |
214 | struct hid_sensor_common *st) | 348 | struct hid_sensor_common *st) |
215 | { | 349 | { |
216 | |||
217 | sensor_hub_input_get_attribute_info(hsdev, | 350 | sensor_hub_input_get_attribute_info(hsdev, |
218 | HID_FEATURE_REPORT, usage_id, | 351 | HID_FEATURE_REPORT, usage_id, |
219 | HID_USAGE_SENSOR_PROP_REPORT_INTERVAL, | 352 | HID_USAGE_SENSOR_PROP_REPORT_INTERVAL, |
220 | &st->poll); | 353 | &st->poll); |
354 | /* Default unit of measure is milliseconds */ | ||
355 | if (st->poll.units == 0) | ||
356 | st->poll.units = HID_USAGE_SENSOR_UNITS_MILLISECOND; | ||
357 | return 0; | ||
358 | |||
359 | } | ||
360 | |||
361 | int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, | ||
362 | u32 usage_id, | ||
363 | struct hid_sensor_common *st) | ||
364 | { | ||
365 | |||
366 | |||
367 | hid_sensor_get_reporting_interval(hsdev, usage_id, st); | ||
221 | 368 | ||
222 | sensor_hub_input_get_attribute_info(hsdev, | 369 | sensor_hub_input_get_attribute_info(hsdev, |
223 | HID_FEATURE_REPORT, usage_id, | 370 | HID_FEATURE_REPORT, usage_id, |
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index dbefbdaf7cd1..73282cee0c81 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c | |||
@@ -28,16 +28,17 @@ | |||
28 | #include <linux/iio/sysfs.h> | 28 | #include <linux/iio/sysfs.h> |
29 | #include "hid-sensor-trigger.h" | 29 | #include "hid-sensor-trigger.h" |
30 | 30 | ||
31 | static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | 31 | int hid_sensor_power_state(struct hid_sensor_common *st, bool state) |
32 | bool state) | ||
33 | { | 32 | { |
34 | struct hid_sensor_common *st = iio_trigger_get_drvdata(trig); | ||
35 | int state_val; | 33 | int state_val; |
36 | int report_val; | 34 | int report_val; |
37 | 35 | ||
38 | if (state) { | 36 | if (state) { |
39 | if (sensor_hub_device_open(st->hsdev)) | 37 | if (sensor_hub_device_open(st->hsdev)) |
40 | return -EIO; | 38 | return -EIO; |
39 | |||
40 | atomic_inc(&st->data_ready); | ||
41 | |||
41 | state_val = hid_sensor_get_usage_index(st->hsdev, | 42 | state_val = hid_sensor_get_usage_index(st->hsdev, |
42 | st->power_state.report_id, | 43 | st->power_state.report_id, |
43 | st->power_state.index, | 44 | st->power_state.index, |
@@ -47,6 +48,8 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
47 | st->report_state.index, | 48 | st->report_state.index, |
48 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); | 49 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); |
49 | } else { | 50 | } else { |
51 | if (!atomic_dec_and_test(&st->data_ready)) | ||
52 | return 0; | ||
50 | sensor_hub_device_close(st->hsdev); | 53 | sensor_hub_device_close(st->hsdev); |
51 | state_val = hid_sensor_get_usage_index(st->hsdev, | 54 | state_val = hid_sensor_get_usage_index(st->hsdev, |
52 | st->power_state.report_id, | 55 | st->power_state.report_id, |
@@ -57,7 +60,6 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
57 | st->report_state.index, | 60 | st->report_state.index, |
58 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM); | 61 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM); |
59 | } | 62 | } |
60 | st->data_ready = state; | ||
61 | 63 | ||
62 | if (state_val >= 0) { | 64 | if (state_val >= 0) { |
63 | state_val += st->power_state.logical_minimum; | 65 | state_val += st->power_state.logical_minimum; |
@@ -75,6 +77,13 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
75 | 77 | ||
76 | return 0; | 78 | return 0; |
77 | } | 79 | } |
80 | EXPORT_SYMBOL(hid_sensor_power_state); | ||
81 | |||
82 | static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | ||
83 | bool state) | ||
84 | { | ||
85 | return hid_sensor_power_state(iio_trigger_get_drvdata(trig), state); | ||
86 | } | ||
78 | 87 | ||
79 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) | 88 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) |
80 | { | 89 | { |
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h index ca02f7811aa8..0f8e78c249d3 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h | |||
@@ -22,5 +22,6 @@ | |||
22 | int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, | 22 | int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, |
23 | struct hid_sensor_common *attrb); | 23 | struct hid_sensor_common *attrb); |
24 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb); | 24 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb); |
25 | int hid_sensor_power_state(struct hid_sensor_common *st, bool state); | ||
25 | 26 | ||
26 | #endif | 27 | #endif |
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 7ba1ef270213..e8b932fed70e 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/iio/iio.h> | 15 | #include <linux/iio/iio.h> |
16 | #include <linux/regulator/consumer.h> | ||
16 | #include <asm/unaligned.h> | 17 | #include <asm/unaligned.h> |
17 | 18 | ||
18 | #include <linux/iio/common/st_sensors.h> | 19 | #include <linux/iio/common/st_sensors.h> |
@@ -198,6 +199,42 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable) | |||
198 | } | 199 | } |
199 | EXPORT_SYMBOL(st_sensors_set_axis_enable); | 200 | EXPORT_SYMBOL(st_sensors_set_axis_enable); |
200 | 201 | ||
202 | void st_sensors_power_enable(struct iio_dev *indio_dev) | ||
203 | { | ||
204 | struct st_sensor_data *pdata = iio_priv(indio_dev); | ||
205 | int err; | ||
206 | |||
207 | /* Regulators not mandatory, but if requested we should enable them. */ | ||
208 | pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd"); | ||
209 | if (!IS_ERR(pdata->vdd)) { | ||
210 | err = regulator_enable(pdata->vdd); | ||
211 | if (err != 0) | ||
212 | dev_warn(&indio_dev->dev, | ||
213 | "Failed to enable specified Vdd supply\n"); | ||
214 | } | ||
215 | |||
216 | pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio"); | ||
217 | if (!IS_ERR(pdata->vdd_io)) { | ||
218 | err = regulator_enable(pdata->vdd_io); | ||
219 | if (err != 0) | ||
220 | dev_warn(&indio_dev->dev, | ||
221 | "Failed to enable specified Vdd_IO supply\n"); | ||
222 | } | ||
223 | } | ||
224 | EXPORT_SYMBOL(st_sensors_power_enable); | ||
225 | |||
226 | void st_sensors_power_disable(struct iio_dev *indio_dev) | ||
227 | { | ||
228 | struct st_sensor_data *pdata = iio_priv(indio_dev); | ||
229 | |||
230 | if (!IS_ERR(pdata->vdd)) | ||
231 | regulator_disable(pdata->vdd); | ||
232 | |||
233 | if (!IS_ERR(pdata->vdd_io)) | ||
234 | regulator_disable(pdata->vdd_io); | ||
235 | } | ||
236 | EXPORT_SYMBOL(st_sensors_power_disable); | ||
237 | |||
201 | static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, | 238 | static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, |
202 | struct st_sensors_platform_data *pdata) | 239 | struct st_sensors_platform_data *pdata) |
203 | { | 240 | { |
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c index 59d6bc3e04df..40f4e4935d0d 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/delay.h> | ||
25 | #include <linux/hid-sensor-hub.h> | 26 | #include <linux/hid-sensor-hub.h> |
26 | #include <linux/iio/iio.h> | 27 | #include <linux/iio/iio.h> |
27 | #include <linux/iio/sysfs.h> | 28 | #include <linux/iio/sysfs.h> |
@@ -42,6 +43,10 @@ struct gyro_3d_state { | |||
42 | struct hid_sensor_common common_attributes; | 43 | struct hid_sensor_common common_attributes; |
43 | struct hid_sensor_hub_attribute_info gyro[GYRO_3D_CHANNEL_MAX]; | 44 | struct hid_sensor_hub_attribute_info gyro[GYRO_3D_CHANNEL_MAX]; |
44 | u32 gyro_val[GYRO_3D_CHANNEL_MAX]; | 45 | u32 gyro_val[GYRO_3D_CHANNEL_MAX]; |
46 | int scale_pre_decml; | ||
47 | int scale_post_decml; | ||
48 | int scale_precision; | ||
49 | int value_offset; | ||
45 | }; | 50 | }; |
46 | 51 | ||
47 | static const u32 gyro_3d_addresses[GYRO_3D_CHANNEL_MAX] = { | 52 | static const u32 gyro_3d_addresses[GYRO_3D_CHANNEL_MAX] = { |
@@ -56,6 +61,7 @@ static const struct iio_chan_spec gyro_3d_channels[] = { | |||
56 | .type = IIO_ANGL_VEL, | 61 | .type = IIO_ANGL_VEL, |
57 | .modified = 1, | 62 | .modified = 1, |
58 | .channel2 = IIO_MOD_X, | 63 | .channel2 = IIO_MOD_X, |
64 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
59 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 65 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
60 | BIT(IIO_CHAN_INFO_SCALE) | | 66 | BIT(IIO_CHAN_INFO_SCALE) | |
61 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 67 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
@@ -65,6 +71,7 @@ static const struct iio_chan_spec gyro_3d_channels[] = { | |||
65 | .type = IIO_ANGL_VEL, | 71 | .type = IIO_ANGL_VEL, |
66 | .modified = 1, | 72 | .modified = 1, |
67 | .channel2 = IIO_MOD_Y, | 73 | .channel2 = IIO_MOD_Y, |
74 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
68 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 75 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
69 | BIT(IIO_CHAN_INFO_SCALE) | | 76 | BIT(IIO_CHAN_INFO_SCALE) | |
70 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 77 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
@@ -74,6 +81,7 @@ static const struct iio_chan_spec gyro_3d_channels[] = { | |||
74 | .type = IIO_ANGL_VEL, | 81 | .type = IIO_ANGL_VEL, |
75 | .modified = 1, | 82 | .modified = 1, |
76 | .channel2 = IIO_MOD_Z, | 83 | .channel2 = IIO_MOD_Z, |
84 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
77 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 85 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
78 | BIT(IIO_CHAN_INFO_SCALE) | | 86 | BIT(IIO_CHAN_INFO_SCALE) | |
79 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 87 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
@@ -104,31 +112,42 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev, | |||
104 | u32 address; | 112 | u32 address; |
105 | int ret; | 113 | int ret; |
106 | int ret_type; | 114 | int ret_type; |
115 | s32 poll_value; | ||
107 | 116 | ||
108 | *val = 0; | 117 | *val = 0; |
109 | *val2 = 0; | 118 | *val2 = 0; |
110 | switch (mask) { | 119 | switch (mask) { |
111 | case 0: | 120 | case 0: |
121 | poll_value = hid_sensor_read_poll_value( | ||
122 | &gyro_state->common_attributes); | ||
123 | if (poll_value < 0) | ||
124 | return -EINVAL; | ||
125 | |||
126 | hid_sensor_power_state(&gyro_state->common_attributes, true); | ||
127 | msleep_interruptible(poll_value * 2); | ||
112 | report_id = gyro_state->gyro[chan->scan_index].report_id; | 128 | report_id = gyro_state->gyro[chan->scan_index].report_id; |
113 | address = gyro_3d_addresses[chan->scan_index]; | 129 | address = gyro_3d_addresses[chan->scan_index]; |
114 | if (report_id >= 0) | 130 | if (report_id >= 0) |
115 | *val = sensor_hub_input_attr_get_raw_value( | 131 | *val = sensor_hub_input_attr_get_raw_value( |
116 | gyro_state->common_attributes.hsdev, | 132 | gyro_state->common_attributes.hsdev, |
117 | HID_USAGE_SENSOR_GYRO_3D, address, | 133 | HID_USAGE_SENSOR_GYRO_3D, address, |
118 | report_id); | 134 | report_id); |
119 | else { | 135 | else { |
120 | *val = 0; | 136 | *val = 0; |
137 | hid_sensor_power_state(&gyro_state->common_attributes, | ||
138 | false); | ||
121 | return -EINVAL; | 139 | return -EINVAL; |
122 | } | 140 | } |
141 | hid_sensor_power_state(&gyro_state->common_attributes, false); | ||
123 | ret_type = IIO_VAL_INT; | 142 | ret_type = IIO_VAL_INT; |
124 | break; | 143 | break; |
125 | case IIO_CHAN_INFO_SCALE: | 144 | case IIO_CHAN_INFO_SCALE: |
126 | *val = gyro_state->gyro[CHANNEL_SCAN_INDEX_X].units; | 145 | *val = gyro_state->scale_pre_decml; |
127 | ret_type = IIO_VAL_INT; | 146 | *val2 = gyro_state->scale_post_decml; |
147 | ret_type = gyro_state->scale_precision; | ||
128 | break; | 148 | break; |
129 | case IIO_CHAN_INFO_OFFSET: | 149 | case IIO_CHAN_INFO_OFFSET: |
130 | *val = hid_sensor_convert_exponent( | 150 | *val = gyro_state->value_offset; |
131 | gyro_state->gyro[CHANNEL_SCAN_INDEX_X].unit_expo); | ||
132 | ret_type = IIO_VAL_INT; | 151 | ret_type = IIO_VAL_INT; |
133 | break; | 152 | break; |
134 | case IIO_CHAN_INFO_SAMP_FREQ: | 153 | case IIO_CHAN_INFO_SAMP_FREQ: |
@@ -197,9 +216,8 @@ static int gyro_3d_proc_event(struct hid_sensor_hub_device *hsdev, | |||
197 | struct iio_dev *indio_dev = platform_get_drvdata(priv); | 216 | struct iio_dev *indio_dev = platform_get_drvdata(priv); |
198 | struct gyro_3d_state *gyro_state = iio_priv(indio_dev); | 217 | struct gyro_3d_state *gyro_state = iio_priv(indio_dev); |
199 | 218 | ||
200 | dev_dbg(&indio_dev->dev, "gyro_3d_proc_event [%d]\n", | 219 | dev_dbg(&indio_dev->dev, "gyro_3d_proc_event\n"); |
201 | gyro_state->common_attributes.data_ready); | 220 | if (atomic_read(&gyro_state->common_attributes.data_ready)) |
202 | if (gyro_state->common_attributes.data_ready) | ||
203 | hid_sensor_push_data(indio_dev, | 221 | hid_sensor_push_data(indio_dev, |
204 | gyro_state->gyro_val, | 222 | gyro_state->gyro_val, |
205 | sizeof(gyro_state->gyro_val)); | 223 | sizeof(gyro_state->gyro_val)); |
@@ -262,6 +280,11 @@ static int gyro_3d_parse_report(struct platform_device *pdev, | |||
262 | st->gyro[1].index, st->gyro[1].report_id, | 280 | st->gyro[1].index, st->gyro[1].report_id, |
263 | st->gyro[2].index, st->gyro[2].report_id); | 281 | st->gyro[2].index, st->gyro[2].report_id); |
264 | 282 | ||
283 | st->scale_precision = hid_sensor_format_scale( | ||
284 | HID_USAGE_SENSOR_GYRO_3D, | ||
285 | &st->gyro[CHANNEL_SCAN_INDEX_X], | ||
286 | &st->scale_pre_decml, &st->scale_post_decml); | ||
287 | |||
265 | /* Set Sensitivity field ids, when there is no individual modifier */ | 288 | /* Set Sensitivity field ids, when there is no individual modifier */ |
266 | if (st->common_attributes.sensitivity.index < 0) { | 289 | if (st->common_attributes.sensitivity.index < 0) { |
267 | sensor_hub_input_get_attribute_info(hsdev, | 290 | sensor_hub_input_get_attribute_info(hsdev, |
@@ -330,7 +353,7 @@ static int hid_gyro_3d_probe(struct platform_device *pdev) | |||
330 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | 353 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); |
331 | goto error_free_dev_mem; | 354 | goto error_free_dev_mem; |
332 | } | 355 | } |
333 | gyro_state->common_attributes.data_ready = false; | 356 | atomic_set(&gyro_state->common_attributes.data_ready, 0); |
334 | ret = hid_sensor_setup_trigger(indio_dev, name, | 357 | ret = hid_sensor_setup_trigger(indio_dev, name, |
335 | &gyro_state->common_attributes); | 358 | &gyro_state->common_attributes); |
336 | if (ret < 0) { | 359 | if (ret < 0) { |
diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c index 4d3f3b92b361..8295e318399f 100644 --- a/drivers/iio/gyro/itg3200_core.c +++ b/drivers/iio/gyro/itg3200_core.c | |||
@@ -110,8 +110,6 @@ static int itg3200_read_raw(struct iio_dev *indio_dev, | |||
110 | default: | 110 | default: |
111 | return -EINVAL; | 111 | return -EINVAL; |
112 | } | 112 | } |
113 | |||
114 | return ret; | ||
115 | } | 113 | } |
116 | 114 | ||
117 | static ssize_t itg3200_read_frequency(struct device *dev, | 115 | static ssize_t itg3200_read_frequency(struct device *dev, |
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index a8e174a47bc4..ed74a9069989 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c | |||
@@ -311,6 +311,8 @@ int st_gyro_common_probe(struct iio_dev *indio_dev, | |||
311 | indio_dev->modes = INDIO_DIRECT_MODE; | 311 | indio_dev->modes = INDIO_DIRECT_MODE; |
312 | indio_dev->info = &gyro_info; | 312 | indio_dev->info = &gyro_info; |
313 | 313 | ||
314 | st_sensors_power_enable(indio_dev); | ||
315 | |||
314 | err = st_sensors_check_device_support(indio_dev, | 316 | err = st_sensors_check_device_support(indio_dev, |
315 | ARRAY_SIZE(st_gyro_sensors), st_gyro_sensors); | 317 | ARRAY_SIZE(st_gyro_sensors), st_gyro_sensors); |
316 | if (err < 0) | 318 | if (err < 0) |
@@ -344,6 +346,9 @@ int st_gyro_common_probe(struct iio_dev *indio_dev, | |||
344 | if (err) | 346 | if (err) |
345 | goto st_gyro_device_register_error; | 347 | goto st_gyro_device_register_error; |
346 | 348 | ||
349 | dev_info(&indio_dev->dev, "registered gyroscope %s\n", | ||
350 | indio_dev->name); | ||
351 | |||
347 | return 0; | 352 | return 0; |
348 | 353 | ||
349 | st_gyro_device_register_error: | 354 | st_gyro_device_register_error: |
@@ -360,6 +365,8 @@ void st_gyro_common_remove(struct iio_dev *indio_dev) | |||
360 | { | 365 | { |
361 | struct st_sensor_data *gdata = iio_priv(indio_dev); | 366 | struct st_sensor_data *gdata = iio_priv(indio_dev); |
362 | 367 | ||
368 | st_sensors_power_disable(indio_dev); | ||
369 | |||
363 | iio_device_unregister(indio_dev); | 370 | iio_device_unregister(indio_dev); |
364 | if (gdata->get_irq_data_ready(indio_dev) > 0) | 371 | if (gdata->get_irq_data_ready(indio_dev) > 0) |
365 | st_sensors_deallocate_trigger(indio_dev); | 372 | st_sensors_deallocate_trigger(indio_dev); |
diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h index f6db6af36ba6..5f0ea77fe717 100644 --- a/drivers/iio/iio_core.h +++ b/drivers/iio/iio_core.h | |||
@@ -35,7 +35,7 @@ int __iio_add_chan_devattr(const char *postfix, | |||
35 | struct list_head *attr_list); | 35 | struct list_head *attr_list); |
36 | void iio_free_chan_devattr_list(struct list_head *attr_list); | 36 | void iio_free_chan_devattr_list(struct list_head *attr_list); |
37 | 37 | ||
38 | ssize_t iio_format_value(char *buf, unsigned int type, int val, int val2); | 38 | ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals); |
39 | 39 | ||
40 | /* Event interface flags */ | 40 | /* Event interface flags */ |
41 | #define IIO_BUSY_BIT_POS 1 | 41 | #define IIO_BUSY_BIT_POS 1 |
diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index 361b2328453d..2d0608ba88d7 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig | |||
@@ -9,6 +9,8 @@ config INV_MPU6050_IIO | |||
9 | select IIO_TRIGGERED_BUFFER | 9 | select IIO_TRIGGERED_BUFFER |
10 | help | 10 | help |
11 | This driver supports the Invensense MPU6050 devices. | 11 | This driver supports the Invensense MPU6050 devices. |
12 | This driver can also support MPU6500 in MPU6050 compatibility mode | ||
13 | and also in MPU6500 mode with some limitations. | ||
12 | It is a gyroscope/accelerometer combo device. | 14 | It is a gyroscope/accelerometer combo device. |
13 | This driver can be built as a module. The module will be called | 15 | This driver can be built as a module. The module will be called |
14 | inv-mpu6050. | 16 | inv-mpu6050. |
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index d8ad606c7cd0..0c6517c94a9d 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | |||
@@ -767,6 +767,7 @@ static SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume); | |||
767 | */ | 767 | */ |
768 | static const struct i2c_device_id inv_mpu_id[] = { | 768 | static const struct i2c_device_id inv_mpu_id[] = { |
769 | {"mpu6050", INV_MPU6050}, | 769 | {"mpu6050", INV_MPU6050}, |
770 | {"mpu6500", INV_MPU6500}, | ||
770 | {} | 771 | {} |
771 | }; | 772 | }; |
772 | 773 | ||
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index 0ab382be1e64..e7799315d4dc 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | |||
@@ -59,6 +59,7 @@ struct inv_mpu6050_reg_map { | |||
59 | /*device enum */ | 59 | /*device enum */ |
60 | enum inv_devices { | 60 | enum inv_devices { |
61 | INV_MPU6050, | 61 | INV_MPU6050, |
62 | INV_MPU6500, | ||
62 | INV_NUM_PARTS | 63 | INV_NUM_PARTS |
63 | }; | 64 | }; |
64 | 65 | ||
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index e472cff6eeae..36b1ae92e239 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c | |||
@@ -150,7 +150,16 @@ static ssize_t iio_show_fixed_type(struct device *dev, | |||
150 | type = IIO_BE; | 150 | type = IIO_BE; |
151 | #endif | 151 | #endif |
152 | } | 152 | } |
153 | return sprintf(buf, "%s:%c%d/%d>>%u\n", | 153 | if (this_attr->c->scan_type.repeat > 1) |
154 | return sprintf(buf, "%s:%c%d/%dX%d>>%u\n", | ||
155 | iio_endian_prefix[type], | ||
156 | this_attr->c->scan_type.sign, | ||
157 | this_attr->c->scan_type.realbits, | ||
158 | this_attr->c->scan_type.storagebits, | ||
159 | this_attr->c->scan_type.repeat, | ||
160 | this_attr->c->scan_type.shift); | ||
161 | else | ||
162 | return sprintf(buf, "%s:%c%d/%d>>%u\n", | ||
154 | iio_endian_prefix[type], | 163 | iio_endian_prefix[type], |
155 | this_attr->c->scan_type.sign, | 164 | this_attr->c->scan_type.sign, |
156 | this_attr->c->scan_type.realbits, | 165 | this_attr->c->scan_type.realbits, |
@@ -475,14 +484,22 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, | |||
475 | for_each_set_bit(i, mask, | 484 | for_each_set_bit(i, mask, |
476 | indio_dev->masklength) { | 485 | indio_dev->masklength) { |
477 | ch = iio_find_channel_from_si(indio_dev, i); | 486 | ch = iio_find_channel_from_si(indio_dev, i); |
478 | length = ch->scan_type.storagebits / 8; | 487 | if (ch->scan_type.repeat > 1) |
488 | length = ch->scan_type.storagebits / 8 * | ||
489 | ch->scan_type.repeat; | ||
490 | else | ||
491 | length = ch->scan_type.storagebits / 8; | ||
479 | bytes = ALIGN(bytes, length); | 492 | bytes = ALIGN(bytes, length); |
480 | bytes += length; | 493 | bytes += length; |
481 | } | 494 | } |
482 | if (timestamp) { | 495 | if (timestamp) { |
483 | ch = iio_find_channel_from_si(indio_dev, | 496 | ch = iio_find_channel_from_si(indio_dev, |
484 | indio_dev->scan_index_timestamp); | 497 | indio_dev->scan_index_timestamp); |
485 | length = ch->scan_type.storagebits / 8; | 498 | if (ch->scan_type.repeat > 1) |
499 | length = ch->scan_type.storagebits / 8 * | ||
500 | ch->scan_type.repeat; | ||
501 | else | ||
502 | length = ch->scan_type.storagebits / 8; | ||
486 | bytes = ALIGN(bytes, length); | 503 | bytes = ALIGN(bytes, length); |
487 | bytes += length; | 504 | bytes += length; |
488 | } | 505 | } |
@@ -959,7 +976,11 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, | |||
959 | indio_dev->masklength, | 976 | indio_dev->masklength, |
960 | in_ind + 1); | 977 | in_ind + 1); |
961 | ch = iio_find_channel_from_si(indio_dev, in_ind); | 978 | ch = iio_find_channel_from_si(indio_dev, in_ind); |
962 | length = ch->scan_type.storagebits/8; | 979 | if (ch->scan_type.repeat > 1) |
980 | length = ch->scan_type.storagebits / 8 * | ||
981 | ch->scan_type.repeat; | ||
982 | else | ||
983 | length = ch->scan_type.storagebits / 8; | ||
963 | /* Make sure we are aligned */ | 984 | /* Make sure we are aligned */ |
964 | in_loc += length; | 985 | in_loc += length; |
965 | if (in_loc % length) | 986 | if (in_loc % length) |
@@ -971,7 +992,11 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, | |||
971 | goto error_clear_mux_table; | 992 | goto error_clear_mux_table; |
972 | } | 993 | } |
973 | ch = iio_find_channel_from_si(indio_dev, in_ind); | 994 | ch = iio_find_channel_from_si(indio_dev, in_ind); |
974 | length = ch->scan_type.storagebits/8; | 995 | if (ch->scan_type.repeat > 1) |
996 | length = ch->scan_type.storagebits / 8 * | ||
997 | ch->scan_type.repeat; | ||
998 | else | ||
999 | length = ch->scan_type.storagebits / 8; | ||
975 | if (out_loc % length) | 1000 | if (out_loc % length) |
976 | out_loc += length - out_loc % length; | 1001 | out_loc += length - out_loc % length; |
977 | if (in_loc % length) | 1002 | if (in_loc % length) |
@@ -992,7 +1017,11 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, | |||
992 | } | 1017 | } |
993 | ch = iio_find_channel_from_si(indio_dev, | 1018 | ch = iio_find_channel_from_si(indio_dev, |
994 | indio_dev->scan_index_timestamp); | 1019 | indio_dev->scan_index_timestamp); |
995 | length = ch->scan_type.storagebits/8; | 1020 | if (ch->scan_type.repeat > 1) |
1021 | length = ch->scan_type.storagebits / 8 * | ||
1022 | ch->scan_type.repeat; | ||
1023 | else | ||
1024 | length = ch->scan_type.storagebits / 8; | ||
996 | if (out_loc % length) | 1025 | if (out_loc % length) |
997 | out_loc += length - out_loc % length; | 1026 | out_loc += length - out_loc % length; |
998 | if (in_loc % length) | 1027 | if (in_loc % length) |
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index ede16aec20fb..4b1f375c5659 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c | |||
@@ -84,6 +84,9 @@ static const char * const iio_modifier_names[] = { | |||
84 | [IIO_MOD_LIGHT_RED] = "red", | 84 | [IIO_MOD_LIGHT_RED] = "red", |
85 | [IIO_MOD_LIGHT_GREEN] = "green", | 85 | [IIO_MOD_LIGHT_GREEN] = "green", |
86 | [IIO_MOD_LIGHT_BLUE] = "blue", | 86 | [IIO_MOD_LIGHT_BLUE] = "blue", |
87 | [IIO_MOD_QUATERNION] = "quaternion", | ||
88 | [IIO_MOD_TEMP_AMBIENT] = "ambient", | ||
89 | [IIO_MOD_TEMP_OBJECT] = "object", | ||
87 | }; | 90 | }; |
88 | 91 | ||
89 | /* relies on pairs of these shared then separate */ | 92 | /* relies on pairs of these shared then separate */ |
@@ -340,7 +343,7 @@ ssize_t iio_enum_read(struct iio_dev *indio_dev, | |||
340 | else if (i >= e->num_items) | 343 | else if (i >= e->num_items) |
341 | return -EINVAL; | 344 | return -EINVAL; |
342 | 345 | ||
343 | return sprintf(buf, "%s\n", e->items[i]); | 346 | return snprintf(buf, PAGE_SIZE, "%s\n", e->items[i]); |
344 | } | 347 | } |
345 | EXPORT_SYMBOL_GPL(iio_enum_read); | 348 | EXPORT_SYMBOL_GPL(iio_enum_read); |
346 | 349 | ||
@@ -373,41 +376,53 @@ EXPORT_SYMBOL_GPL(iio_enum_write); | |||
373 | * @buf: The buffer to which the formated value gets written | 376 | * @buf: The buffer to which the formated value gets written |
374 | * @type: One of the IIO_VAL_... constants. This decides how the val and val2 | 377 | * @type: One of the IIO_VAL_... constants. This decides how the val and val2 |
375 | * parameters are formatted. | 378 | * parameters are formatted. |
376 | * @val: First part of the value, exact meaning depends on the type parameter. | 379 | * @vals: pointer to the values, exact meaning depends on the type parameter. |
377 | * @val2: Second part of the value, exact meaning depends on the type parameter. | ||
378 | */ | 380 | */ |
379 | ssize_t iio_format_value(char *buf, unsigned int type, int val, int val2) | 381 | ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals) |
380 | { | 382 | { |
381 | unsigned long long tmp; | 383 | unsigned long long tmp; |
382 | bool scale_db = false; | 384 | bool scale_db = false; |
383 | 385 | ||
384 | switch (type) { | 386 | switch (type) { |
385 | case IIO_VAL_INT: | 387 | case IIO_VAL_INT: |
386 | return sprintf(buf, "%d\n", val); | 388 | return sprintf(buf, "%d\n", vals[0]); |
387 | case IIO_VAL_INT_PLUS_MICRO_DB: | 389 | case IIO_VAL_INT_PLUS_MICRO_DB: |
388 | scale_db = true; | 390 | scale_db = true; |
389 | case IIO_VAL_INT_PLUS_MICRO: | 391 | case IIO_VAL_INT_PLUS_MICRO: |
390 | if (val2 < 0) | 392 | if (vals[1] < 0) |
391 | return sprintf(buf, "-%ld.%06u%s\n", abs(val), -val2, | 393 | return sprintf(buf, "-%ld.%06u%s\n", abs(vals[0]), |
394 | -vals[1], | ||
392 | scale_db ? " dB" : ""); | 395 | scale_db ? " dB" : ""); |
393 | else | 396 | else |
394 | return sprintf(buf, "%d.%06u%s\n", val, val2, | 397 | return sprintf(buf, "%d.%06u%s\n", vals[0], vals[1], |
395 | scale_db ? " dB" : ""); | 398 | scale_db ? " dB" : ""); |
396 | case IIO_VAL_INT_PLUS_NANO: | 399 | case IIO_VAL_INT_PLUS_NANO: |
397 | if (val2 < 0) | 400 | if (vals[1] < 0) |
398 | return sprintf(buf, "-%ld.%09u\n", abs(val), -val2); | 401 | return sprintf(buf, "-%ld.%09u\n", abs(vals[0]), |
402 | -vals[1]); | ||
399 | else | 403 | else |
400 | return sprintf(buf, "%d.%09u\n", val, val2); | 404 | return sprintf(buf, "%d.%09u\n", vals[0], vals[1]); |
401 | case IIO_VAL_FRACTIONAL: | 405 | case IIO_VAL_FRACTIONAL: |
402 | tmp = div_s64((s64)val * 1000000000LL, val2); | 406 | tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]); |
403 | val2 = do_div(tmp, 1000000000LL); | 407 | vals[1] = do_div(tmp, 1000000000LL); |
404 | val = tmp; | 408 | vals[0] = tmp; |
405 | return sprintf(buf, "%d.%09u\n", val, val2); | 409 | return sprintf(buf, "%d.%09u\n", vals[0], vals[1]); |
406 | case IIO_VAL_FRACTIONAL_LOG2: | 410 | case IIO_VAL_FRACTIONAL_LOG2: |
407 | tmp = (s64)val * 1000000000LL >> val2; | 411 | tmp = (s64)vals[0] * 1000000000LL >> vals[1]; |
408 | val2 = do_div(tmp, 1000000000LL); | 412 | vals[1] = do_div(tmp, 1000000000LL); |
409 | val = tmp; | 413 | vals[0] = tmp; |
410 | return sprintf(buf, "%d.%09u\n", val, val2); | 414 | return sprintf(buf, "%d.%09u\n", vals[0], vals[1]); |
415 | case IIO_VAL_INT_MULTIPLE: | ||
416 | { | ||
417 | int i; | ||
418 | int len = 0; | ||
419 | |||
420 | for (i = 0; i < size; ++i) | ||
421 | len += snprintf(&buf[len], PAGE_SIZE - len, "%d ", | ||
422 | vals[i]); | ||
423 | len += snprintf(&buf[len], PAGE_SIZE - len, "\n"); | ||
424 | return len; | ||
425 | } | ||
411 | default: | 426 | default: |
412 | return 0; | 427 | return 0; |
413 | } | 428 | } |
@@ -419,14 +434,23 @@ static ssize_t iio_read_channel_info(struct device *dev, | |||
419 | { | 434 | { |
420 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 435 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
421 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | 436 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
422 | int val, val2; | 437 | int vals[INDIO_MAX_RAW_ELEMENTS]; |
423 | int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, | 438 | int ret; |
424 | &val, &val2, this_attr->address); | 439 | int val_len = 2; |
440 | |||
441 | if (indio_dev->info->read_raw_multi) | ||
442 | ret = indio_dev->info->read_raw_multi(indio_dev, this_attr->c, | ||
443 | INDIO_MAX_RAW_ELEMENTS, | ||
444 | vals, &val_len, | ||
445 | this_attr->address); | ||
446 | else | ||
447 | ret = indio_dev->info->read_raw(indio_dev, this_attr->c, | ||
448 | &vals[0], &vals[1], this_attr->address); | ||
425 | 449 | ||
426 | if (ret < 0) | 450 | if (ret < 0) |
427 | return ret; | 451 | return ret; |
428 | 452 | ||
429 | return iio_format_value(buf, ret, val, val2); | 453 | return iio_format_value(buf, ret, val_len, vals); |
430 | } | 454 | } |
431 | 455 | ||
432 | /** | 456 | /** |
@@ -716,6 +740,8 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev, | |||
716 | int i, ret, attrcount = 0; | 740 | int i, ret, attrcount = 0; |
717 | 741 | ||
718 | for_each_set_bit(i, infomask, sizeof(infomask)*8) { | 742 | for_each_set_bit(i, infomask, sizeof(infomask)*8) { |
743 | if (i >= ARRAY_SIZE(iio_chan_info_postfix)) | ||
744 | return -EINVAL; | ||
719 | ret = __iio_add_chan_devattr(iio_chan_info_postfix[i], | 745 | ret = __iio_add_chan_devattr(iio_chan_info_postfix[i], |
720 | chan, | 746 | chan, |
721 | &iio_read_channel_info, | 747 | &iio_read_channel_info, |
@@ -820,7 +846,7 @@ static ssize_t iio_show_dev_name(struct device *dev, | |||
820 | char *buf) | 846 | char *buf) |
821 | { | 847 | { |
822 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 848 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
823 | return sprintf(buf, "%s\n", indio_dev->name); | 849 | return snprintf(buf, PAGE_SIZE, "%s\n", indio_dev->name); |
824 | } | 850 | } |
825 | 851 | ||
826 | static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); | 852 | static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); |
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index ea6e06b9c7d4..258a973a1fb8 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c | |||
@@ -270,7 +270,7 @@ static ssize_t iio_ev_value_show(struct device *dev, | |||
270 | { | 270 | { |
271 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 271 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
272 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | 272 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
273 | int val, val2; | 273 | int val, val2, val_arr[2]; |
274 | int ret; | 274 | int ret; |
275 | 275 | ||
276 | ret = indio_dev->info->read_event_value(indio_dev, | 276 | ret = indio_dev->info->read_event_value(indio_dev, |
@@ -279,7 +279,9 @@ static ssize_t iio_ev_value_show(struct device *dev, | |||
279 | &val, &val2); | 279 | &val, &val2); |
280 | if (ret < 0) | 280 | if (ret < 0) |
281 | return ret; | 281 | return ret; |
282 | return iio_format_value(buf, ret, val, val2); | 282 | val_arr[0] = val; |
283 | val_arr[1] = val2; | ||
284 | return iio_format_value(buf, ret, 2, val_arr); | ||
283 | } | 285 | } |
284 | 286 | ||
285 | static ssize_t iio_ev_value_store(struct device *dev, | 287 | static ssize_t iio_ev_value_store(struct device *dev, |
@@ -321,7 +323,9 @@ static int iio_device_add_event(struct iio_dev *indio_dev, | |||
321 | char *postfix; | 323 | char *postfix; |
322 | int ret; | 324 | int ret; |
323 | 325 | ||
324 | for_each_set_bit(i, mask, sizeof(*mask)) { | 326 | for_each_set_bit(i, mask, sizeof(*mask)*8) { |
327 | if (i >= ARRAY_SIZE(iio_ev_info_text)) | ||
328 | return -EINVAL; | ||
325 | postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", | 329 | postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", |
326 | iio_ev_type_text[type], iio_ev_dir_text[dir], | 330 | iio_ev_type_text[type], iio_ev_dir_text[dir], |
327 | iio_ev_info_text[i]); | 331 | iio_ev_info_text[i]); |
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 0cf5f8e06cfc..d833d55052ea 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c | |||
@@ -417,12 +417,24 @@ static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, | |||
417 | enum iio_chan_info_enum info) | 417 | enum iio_chan_info_enum info) |
418 | { | 418 | { |
419 | int unused; | 419 | int unused; |
420 | int vals[INDIO_MAX_RAW_ELEMENTS]; | ||
421 | int ret; | ||
422 | int val_len = 2; | ||
420 | 423 | ||
421 | if (val2 == NULL) | 424 | if (val2 == NULL) |
422 | val2 = &unused; | 425 | val2 = &unused; |
423 | 426 | ||
424 | return chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, | 427 | if (chan->indio_dev->info->read_raw_multi) { |
425 | val, val2, info); | 428 | ret = chan->indio_dev->info->read_raw_multi(chan->indio_dev, |
429 | chan->channel, INDIO_MAX_RAW_ELEMENTS, | ||
430 | vals, &val_len, info); | ||
431 | *val = vals[0]; | ||
432 | *val2 = vals[1]; | ||
433 | } else | ||
434 | ret = chan->indio_dev->info->read_raw(chan->indio_dev, | ||
435 | chan->channel, val, val2, info); | ||
436 | |||
437 | return ret; | ||
426 | } | 438 | } |
427 | 439 | ||
428 | int iio_read_channel_raw(struct iio_channel *chan, int *val) | 440 | int iio_read_channel_raw(struct iio_channel *chan, int *val) |
@@ -443,6 +455,24 @@ err_unlock: | |||
443 | } | 455 | } |
444 | EXPORT_SYMBOL_GPL(iio_read_channel_raw); | 456 | EXPORT_SYMBOL_GPL(iio_read_channel_raw); |
445 | 457 | ||
458 | int iio_read_channel_average_raw(struct iio_channel *chan, int *val) | ||
459 | { | ||
460 | int ret; | ||
461 | |||
462 | mutex_lock(&chan->indio_dev->info_exist_lock); | ||
463 | if (chan->indio_dev->info == NULL) { | ||
464 | ret = -ENODEV; | ||
465 | goto err_unlock; | ||
466 | } | ||
467 | |||
468 | ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_AVERAGE_RAW); | ||
469 | err_unlock: | ||
470 | mutex_unlock(&chan->indio_dev->info_exist_lock); | ||
471 | |||
472 | return ret; | ||
473 | } | ||
474 | EXPORT_SYMBOL_GPL(iio_read_channel_average_raw); | ||
475 | |||
446 | static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, | 476 | static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, |
447 | int raw, int *processed, unsigned int scale) | 477 | int raw, int *processed, unsigned int scale) |
448 | { | 478 | { |
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c index 5ea4a03c7e71..04bdb85d2d9f 100644 --- a/drivers/iio/light/gp2ap020a00f.c +++ b/drivers/iio/light/gp2ap020a00f.c | |||
@@ -5,13 +5,13 @@ | |||
5 | * IIO features supported by the driver: | 5 | * IIO features supported by the driver: |
6 | * | 6 | * |
7 | * Read-only raw channels: | 7 | * Read-only raw channels: |
8 | * - illiminance_clear [lux] | 8 | * - illuminance_clear [lux] |
9 | * - illiminance_ir | 9 | * - illuminance_ir |
10 | * - proximity | 10 | * - proximity |
11 | * | 11 | * |
12 | * Triggered buffer: | 12 | * Triggered buffer: |
13 | * - illiminance_clear | 13 | * - illuminance_clear |
14 | * - illiminance_ir | 14 | * - illuminance_ir |
15 | * - proximity | 15 | * - proximity |
16 | * | 16 | * |
17 | * Events: | 17 | * Events: |
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index 621541fb10a9..f34c94380b41 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/delay.h> | ||
25 | #include <linux/hid-sensor-hub.h> | 26 | #include <linux/hid-sensor-hub.h> |
26 | #include <linux/iio/iio.h> | 27 | #include <linux/iio/iio.h> |
27 | #include <linux/iio/sysfs.h> | 28 | #include <linux/iio/sysfs.h> |
@@ -37,6 +38,10 @@ struct als_state { | |||
37 | struct hid_sensor_common common_attributes; | 38 | struct hid_sensor_common common_attributes; |
38 | struct hid_sensor_hub_attribute_info als_illum; | 39 | struct hid_sensor_hub_attribute_info als_illum; |
39 | u32 illum; | 40 | u32 illum; |
41 | int scale_pre_decml; | ||
42 | int scale_post_decml; | ||
43 | int scale_precision; | ||
44 | int value_offset; | ||
40 | }; | 45 | }; |
41 | 46 | ||
42 | /* Channel definitions */ | 47 | /* Channel definitions */ |
@@ -45,6 +50,7 @@ static const struct iio_chan_spec als_channels[] = { | |||
45 | .type = IIO_INTENSITY, | 50 | .type = IIO_INTENSITY, |
46 | .modified = 1, | 51 | .modified = 1, |
47 | .channel2 = IIO_MOD_LIGHT_BOTH, | 52 | .channel2 = IIO_MOD_LIGHT_BOTH, |
53 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
48 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 54 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
49 | BIT(IIO_CHAN_INFO_SCALE) | | 55 | BIT(IIO_CHAN_INFO_SCALE) | |
50 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 56 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
@@ -75,6 +81,7 @@ static int als_read_raw(struct iio_dev *indio_dev, | |||
75 | u32 address; | 81 | u32 address; |
76 | int ret; | 82 | int ret; |
77 | int ret_type; | 83 | int ret_type; |
84 | s32 poll_value; | ||
78 | 85 | ||
79 | *val = 0; | 86 | *val = 0; |
80 | *val2 = 0; | 87 | *val2 = 0; |
@@ -90,24 +97,35 @@ static int als_read_raw(struct iio_dev *indio_dev, | |||
90 | report_id = -1; | 97 | report_id = -1; |
91 | break; | 98 | break; |
92 | } | 99 | } |
93 | if (report_id >= 0) | 100 | if (report_id >= 0) { |
101 | poll_value = hid_sensor_read_poll_value( | ||
102 | &als_state->common_attributes); | ||
103 | if (poll_value < 0) | ||
104 | return -EINVAL; | ||
105 | |||
106 | hid_sensor_power_state(&als_state->common_attributes, | ||
107 | true); | ||
108 | msleep_interruptible(poll_value * 2); | ||
109 | |||
94 | *val = sensor_hub_input_attr_get_raw_value( | 110 | *val = sensor_hub_input_attr_get_raw_value( |
95 | als_state->common_attributes.hsdev, | 111 | als_state->common_attributes.hsdev, |
96 | HID_USAGE_SENSOR_ALS, address, | 112 | HID_USAGE_SENSOR_ALS, address, |
97 | report_id); | 113 | report_id); |
98 | else { | 114 | hid_sensor_power_state(&als_state->common_attributes, |
115 | false); | ||
116 | } else { | ||
99 | *val = 0; | 117 | *val = 0; |
100 | return -EINVAL; | 118 | return -EINVAL; |
101 | } | 119 | } |
102 | ret_type = IIO_VAL_INT; | 120 | ret_type = IIO_VAL_INT; |
103 | break; | 121 | break; |
104 | case IIO_CHAN_INFO_SCALE: | 122 | case IIO_CHAN_INFO_SCALE: |
105 | *val = als_state->als_illum.units; | 123 | *val = als_state->scale_pre_decml; |
106 | ret_type = IIO_VAL_INT; | 124 | *val2 = als_state->scale_post_decml; |
125 | ret_type = als_state->scale_precision; | ||
107 | break; | 126 | break; |
108 | case IIO_CHAN_INFO_OFFSET: | 127 | case IIO_CHAN_INFO_OFFSET: |
109 | *val = hid_sensor_convert_exponent( | 128 | *val = als_state->value_offset; |
110 | als_state->als_illum.unit_expo); | ||
111 | ret_type = IIO_VAL_INT; | 129 | ret_type = IIO_VAL_INT; |
112 | break; | 130 | break; |
113 | case IIO_CHAN_INFO_SAMP_FREQ: | 131 | case IIO_CHAN_INFO_SAMP_FREQ: |
@@ -176,9 +194,8 @@ static int als_proc_event(struct hid_sensor_hub_device *hsdev, | |||
176 | struct iio_dev *indio_dev = platform_get_drvdata(priv); | 194 | struct iio_dev *indio_dev = platform_get_drvdata(priv); |
177 | struct als_state *als_state = iio_priv(indio_dev); | 195 | struct als_state *als_state = iio_priv(indio_dev); |
178 | 196 | ||
179 | dev_dbg(&indio_dev->dev, "als_proc_event [%d]\n", | 197 | dev_dbg(&indio_dev->dev, "als_proc_event\n"); |
180 | als_state->common_attributes.data_ready); | 198 | if (atomic_read(&als_state->common_attributes.data_ready)) |
181 | if (als_state->common_attributes.data_ready) | ||
182 | hid_sensor_push_data(indio_dev, | 199 | hid_sensor_push_data(indio_dev, |
183 | &als_state->illum, | 200 | &als_state->illum, |
184 | sizeof(als_state->illum)); | 201 | sizeof(als_state->illum)); |
@@ -229,6 +246,11 @@ static int als_parse_report(struct platform_device *pdev, | |||
229 | dev_dbg(&pdev->dev, "als %x:%x\n", st->als_illum.index, | 246 | dev_dbg(&pdev->dev, "als %x:%x\n", st->als_illum.index, |
230 | st->als_illum.report_id); | 247 | st->als_illum.report_id); |
231 | 248 | ||
249 | st->scale_precision = hid_sensor_format_scale( | ||
250 | HID_USAGE_SENSOR_ALS, | ||
251 | &st->als_illum, | ||
252 | &st->scale_pre_decml, &st->scale_post_decml); | ||
253 | |||
232 | /* Set Sensitivity field ids, when there is no individual modifier */ | 254 | /* Set Sensitivity field ids, when there is no individual modifier */ |
233 | if (st->common_attributes.sensitivity.index < 0) { | 255 | if (st->common_attributes.sensitivity.index < 0) { |
234 | sensor_hub_input_get_attribute_info(hsdev, | 256 | sensor_hub_input_get_attribute_info(hsdev, |
@@ -296,7 +318,7 @@ static int hid_als_probe(struct platform_device *pdev) | |||
296 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | 318 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); |
297 | goto error_free_dev_mem; | 319 | goto error_free_dev_mem; |
298 | } | 320 | } |
299 | als_state->common_attributes.data_ready = false; | 321 | atomic_set(&als_state->common_attributes.data_ready, 0); |
300 | ret = hid_sensor_setup_trigger(indio_dev, name, | 322 | ret = hid_sensor_setup_trigger(indio_dev, name, |
301 | &als_state->common_attributes); | 323 | &als_state->common_attributes); |
302 | if (ret < 0) { | 324 | if (ret < 0) { |
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index 1894ab196f97..d203ef4d892f 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/delay.h> | ||
24 | #include <linux/hid-sensor-hub.h> | 25 | #include <linux/hid-sensor-hub.h> |
25 | #include <linux/iio/iio.h> | 26 | #include <linux/iio/iio.h> |
26 | #include <linux/iio/sysfs.h> | 27 | #include <linux/iio/sysfs.h> |
@@ -75,6 +76,7 @@ static int prox_read_raw(struct iio_dev *indio_dev, | |||
75 | u32 address; | 76 | u32 address; |
76 | int ret; | 77 | int ret; |
77 | int ret_type; | 78 | int ret_type; |
79 | s32 poll_value; | ||
78 | 80 | ||
79 | *val = 0; | 81 | *val = 0; |
80 | *val2 = 0; | 82 | *val2 = 0; |
@@ -90,12 +92,24 @@ static int prox_read_raw(struct iio_dev *indio_dev, | |||
90 | report_id = -1; | 92 | report_id = -1; |
91 | break; | 93 | break; |
92 | } | 94 | } |
93 | if (report_id >= 0) | 95 | if (report_id >= 0) { |
96 | poll_value = hid_sensor_read_poll_value( | ||
97 | &prox_state->common_attributes); | ||
98 | if (poll_value < 0) | ||
99 | return -EINVAL; | ||
100 | |||
101 | hid_sensor_power_state(&prox_state->common_attributes, | ||
102 | true); | ||
103 | |||
104 | msleep_interruptible(poll_value * 2); | ||
105 | |||
94 | *val = sensor_hub_input_attr_get_raw_value( | 106 | *val = sensor_hub_input_attr_get_raw_value( |
95 | prox_state->common_attributes.hsdev, | 107 | prox_state->common_attributes.hsdev, |
96 | HID_USAGE_SENSOR_PROX, address, | 108 | HID_USAGE_SENSOR_PROX, address, |
97 | report_id); | 109 | report_id); |
98 | else { | 110 | hid_sensor_power_state(&prox_state->common_attributes, |
111 | false); | ||
112 | } else { | ||
99 | *val = 0; | 113 | *val = 0; |
100 | return -EINVAL; | 114 | return -EINVAL; |
101 | } | 115 | } |
@@ -176,9 +190,8 @@ static int prox_proc_event(struct hid_sensor_hub_device *hsdev, | |||
176 | struct iio_dev *indio_dev = platform_get_drvdata(priv); | 190 | struct iio_dev *indio_dev = platform_get_drvdata(priv); |
177 | struct prox_state *prox_state = iio_priv(indio_dev); | 191 | struct prox_state *prox_state = iio_priv(indio_dev); |
178 | 192 | ||
179 | dev_dbg(&indio_dev->dev, "prox_proc_event [%d]\n", | 193 | dev_dbg(&indio_dev->dev, "prox_proc_event\n"); |
180 | prox_state->common_attributes.data_ready); | 194 | if (atomic_read(&prox_state->common_attributes.data_ready)) |
181 | if (prox_state->common_attributes.data_ready) | ||
182 | hid_sensor_push_data(indio_dev, | 195 | hid_sensor_push_data(indio_dev, |
183 | &prox_state->human_presence, | 196 | &prox_state->human_presence, |
184 | sizeof(prox_state->human_presence)); | 197 | sizeof(prox_state->human_presence)); |
@@ -297,7 +310,7 @@ static int hid_prox_probe(struct platform_device *pdev) | |||
297 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | 310 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); |
298 | goto error_free_dev_mem; | 311 | goto error_free_dev_mem; |
299 | } | 312 | } |
300 | prox_state->common_attributes.data_ready = false; | 313 | atomic_set(&prox_state->common_attributes.data_ready, 0); |
301 | ret = hid_sensor_setup_trigger(indio_dev, name, | 314 | ret = hid_sensor_setup_trigger(indio_dev, name, |
302 | &prox_state->common_attributes); | 315 | &prox_state->common_attributes); |
303 | if (ret) { | 316 | if (ret) { |
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index d86d226dcd67..05a364c543f8 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig | |||
@@ -11,7 +11,8 @@ config AK8975 | |||
11 | depends on GPIOLIB | 11 | depends on GPIOLIB |
12 | help | 12 | help |
13 | Say yes here to build support for Asahi Kasei AK8975 3-Axis | 13 | Say yes here to build support for Asahi Kasei AK8975 3-Axis |
14 | Magnetometer. | 14 | Magnetometer. This driver can also support AK8963, if i2c |
15 | device name is identified as ak8963. | ||
15 | 16 | ||
16 | To compile this driver as a module, choose M here: the module | 17 | To compile this driver as a module, choose M here: the module |
17 | will be called ak8975. | 18 | will be called ak8975. |
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 74866d1efd1b..09ea5c481f4c 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/bitops.h> | 31 | #include <linux/bitops.h> |
32 | #include <linux/gpio.h> | 32 | #include <linux/gpio.h> |
33 | #include <linux/of_gpio.h> | 33 | #include <linux/of_gpio.h> |
34 | #include <linux/acpi.h> | ||
34 | 35 | ||
35 | #include <linux/iio/iio.h> | 36 | #include <linux/iio/iio.h> |
36 | #include <linux/iio/sysfs.h> | 37 | #include <linux/iio/sysfs.h> |
@@ -85,7 +86,14 @@ | |||
85 | #define AK8975_MAX_CONVERSION_TIMEOUT 500 | 86 | #define AK8975_MAX_CONVERSION_TIMEOUT 500 |
86 | #define AK8975_CONVERSION_DONE_POLL_TIME 10 | 87 | #define AK8975_CONVERSION_DONE_POLL_TIME 10 |
87 | #define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000) | 88 | #define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000) |
88 | #define RAW_TO_GAUSS(asa) ((((asa) + 128) * 3000) / 256) | 89 | #define RAW_TO_GAUSS_8975(asa) ((((asa) + 128) * 3000) / 256) |
90 | #define RAW_TO_GAUSS_8963(asa) ((((asa) + 128) * 6000) / 256) | ||
91 | |||
92 | /* Compatible Asahi Kasei Compass parts */ | ||
93 | enum asahi_compass_chipset { | ||
94 | AK8975, | ||
95 | AK8963, | ||
96 | }; | ||
89 | 97 | ||
90 | /* | 98 | /* |
91 | * Per-instance context data for the device. | 99 | * Per-instance context data for the device. |
@@ -101,6 +109,7 @@ struct ak8975_data { | |||
101 | int eoc_irq; | 109 | int eoc_irq; |
102 | wait_queue_head_t data_ready_queue; | 110 | wait_queue_head_t data_ready_queue; |
103 | unsigned long flags; | 111 | unsigned long flags; |
112 | enum asahi_compass_chipset chipset; | ||
104 | }; | 113 | }; |
105 | 114 | ||
106 | static const int ak8975_index_to_reg[] = { | 115 | static const int ak8975_index_to_reg[] = { |
@@ -272,9 +281,21 @@ static int ak8975_setup(struct i2c_client *client) | |||
272 | * Since ASA doesn't change, we cache the resultant scale factor into the | 281 | * Since ASA doesn't change, we cache the resultant scale factor into the |
273 | * device context in ak8975_setup(). | 282 | * device context in ak8975_setup(). |
274 | */ | 283 | */ |
275 | data->raw_to_gauss[0] = RAW_TO_GAUSS(data->asa[0]); | 284 | if (data->chipset == AK8963) { |
276 | data->raw_to_gauss[1] = RAW_TO_GAUSS(data->asa[1]); | 285 | /* |
277 | data->raw_to_gauss[2] = RAW_TO_GAUSS(data->asa[2]); | 286 | * H range is +-8190 and magnetometer range is +-4912. |
287 | * So HuT using the above explanation for 8975, | ||
288 | * 4912/8190 = ~ 6/10. | ||
289 | * So the Hadj should use 6/10 instead of 3/10. | ||
290 | */ | ||
291 | data->raw_to_gauss[0] = RAW_TO_GAUSS_8963(data->asa[0]); | ||
292 | data->raw_to_gauss[1] = RAW_TO_GAUSS_8963(data->asa[1]); | ||
293 | data->raw_to_gauss[2] = RAW_TO_GAUSS_8963(data->asa[2]); | ||
294 | } else { | ||
295 | data->raw_to_gauss[0] = RAW_TO_GAUSS_8975(data->asa[0]); | ||
296 | data->raw_to_gauss[1] = RAW_TO_GAUSS_8975(data->asa[1]); | ||
297 | data->raw_to_gauss[2] = RAW_TO_GAUSS_8975(data->asa[2]); | ||
298 | } | ||
278 | 299 | ||
279 | return 0; | 300 | return 0; |
280 | } | 301 | } |
@@ -455,6 +476,27 @@ static const struct iio_info ak8975_info = { | |||
455 | .driver_module = THIS_MODULE, | 476 | .driver_module = THIS_MODULE, |
456 | }; | 477 | }; |
457 | 478 | ||
479 | static const struct acpi_device_id ak_acpi_match[] = { | ||
480 | {"AK8975", AK8975}, | ||
481 | {"AK8963", AK8963}, | ||
482 | {"INVN6500", AK8963}, | ||
483 | { }, | ||
484 | }; | ||
485 | MODULE_DEVICE_TABLE(acpi, ak_acpi_match); | ||
486 | |||
487 | static char *ak8975_match_acpi_device(struct device *dev, | ||
488 | enum asahi_compass_chipset *chipset) | ||
489 | { | ||
490 | const struct acpi_device_id *id; | ||
491 | |||
492 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
493 | if (!id) | ||
494 | return NULL; | ||
495 | *chipset = (int)id->driver_data; | ||
496 | |||
497 | return (char *)dev_name(dev); | ||
498 | } | ||
499 | |||
458 | static int ak8975_probe(struct i2c_client *client, | 500 | static int ak8975_probe(struct i2c_client *client, |
459 | const struct i2c_device_id *id) | 501 | const struct i2c_device_id *id) |
460 | { | 502 | { |
@@ -462,6 +504,7 @@ static int ak8975_probe(struct i2c_client *client, | |||
462 | struct iio_dev *indio_dev; | 504 | struct iio_dev *indio_dev; |
463 | int eoc_gpio; | 505 | int eoc_gpio; |
464 | int err; | 506 | int err; |
507 | char *name = NULL; | ||
465 | 508 | ||
466 | /* Grab and set up the supplied GPIO. */ | 509 | /* Grab and set up the supplied GPIO. */ |
467 | if (client->dev.platform_data) | 510 | if (client->dev.platform_data) |
@@ -499,6 +542,19 @@ static int ak8975_probe(struct i2c_client *client, | |||
499 | data->eoc_gpio = eoc_gpio; | 542 | data->eoc_gpio = eoc_gpio; |
500 | data->eoc_irq = 0; | 543 | data->eoc_irq = 0; |
501 | 544 | ||
545 | /* id will be NULL when enumerated via ACPI */ | ||
546 | if (id) { | ||
547 | data->chipset = | ||
548 | (enum asahi_compass_chipset)(id->driver_data); | ||
549 | name = (char *) id->name; | ||
550 | } else if (ACPI_HANDLE(&client->dev)) | ||
551 | name = ak8975_match_acpi_device(&client->dev, &data->chipset); | ||
552 | else { | ||
553 | err = -ENOSYS; | ||
554 | goto exit_free_iio; | ||
555 | } | ||
556 | dev_dbg(&client->dev, "Asahi compass chip %s\n", name); | ||
557 | |||
502 | /* Perform some basic start-of-day setup of the device. */ | 558 | /* Perform some basic start-of-day setup of the device. */ |
503 | err = ak8975_setup(client); | 559 | err = ak8975_setup(client); |
504 | if (err < 0) { | 560 | if (err < 0) { |
@@ -513,9 +569,8 @@ static int ak8975_probe(struct i2c_client *client, | |||
513 | indio_dev->channels = ak8975_channels; | 569 | indio_dev->channels = ak8975_channels; |
514 | indio_dev->num_channels = ARRAY_SIZE(ak8975_channels); | 570 | indio_dev->num_channels = ARRAY_SIZE(ak8975_channels); |
515 | indio_dev->info = &ak8975_info; | 571 | indio_dev->info = &ak8975_info; |
516 | indio_dev->name = id->name; | ||
517 | indio_dev->modes = INDIO_DIRECT_MODE; | 572 | indio_dev->modes = INDIO_DIRECT_MODE; |
518 | 573 | indio_dev->name = name; | |
519 | err = iio_device_register(indio_dev); | 574 | err = iio_device_register(indio_dev); |
520 | if (err < 0) | 575 | if (err < 0) |
521 | goto exit_free_iio; | 576 | goto exit_free_iio; |
@@ -552,7 +607,8 @@ static int ak8975_remove(struct i2c_client *client) | |||
552 | } | 607 | } |
553 | 608 | ||
554 | static const struct i2c_device_id ak8975_id[] = { | 609 | static const struct i2c_device_id ak8975_id[] = { |
555 | {"ak8975", 0}, | 610 | {"ak8975", AK8975}, |
611 | {"ak8963", AK8963}, | ||
556 | {} | 612 | {} |
557 | }; | 613 | }; |
558 | 614 | ||
@@ -569,6 +625,7 @@ static struct i2c_driver ak8975_driver = { | |||
569 | .driver = { | 625 | .driver = { |
570 | .name = "ak8975", | 626 | .name = "ak8975", |
571 | .of_match_table = ak8975_of_match, | 627 | .of_match_table = ak8975_of_match, |
628 | .acpi_match_table = ACPI_PTR(ak_acpi_match), | ||
572 | }, | 629 | }, |
573 | .probe = ak8975_probe, | 630 | .probe = ak8975_probe, |
574 | .remove = ak8975_remove, | 631 | .remove = ak8975_remove, |
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index 6d162b7e7af5..41cf29e2a371 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/delay.h> | ||
25 | #include <linux/hid-sensor-hub.h> | 26 | #include <linux/hid-sensor-hub.h> |
26 | #include <linux/iio/iio.h> | 27 | #include <linux/iio/iio.h> |
27 | #include <linux/iio/sysfs.h> | 28 | #include <linux/iio/sysfs.h> |
@@ -42,6 +43,10 @@ struct magn_3d_state { | |||
42 | struct hid_sensor_common common_attributes; | 43 | struct hid_sensor_common common_attributes; |
43 | struct hid_sensor_hub_attribute_info magn[MAGN_3D_CHANNEL_MAX]; | 44 | struct hid_sensor_hub_attribute_info magn[MAGN_3D_CHANNEL_MAX]; |
44 | u32 magn_val[MAGN_3D_CHANNEL_MAX]; | 45 | u32 magn_val[MAGN_3D_CHANNEL_MAX]; |
46 | int scale_pre_decml; | ||
47 | int scale_post_decml; | ||
48 | int scale_precision; | ||
49 | int value_offset; | ||
45 | }; | 50 | }; |
46 | 51 | ||
47 | static const u32 magn_3d_addresses[MAGN_3D_CHANNEL_MAX] = { | 52 | static const u32 magn_3d_addresses[MAGN_3D_CHANNEL_MAX] = { |
@@ -56,6 +61,7 @@ static const struct iio_chan_spec magn_3d_channels[] = { | |||
56 | .type = IIO_MAGN, | 61 | .type = IIO_MAGN, |
57 | .modified = 1, | 62 | .modified = 1, |
58 | .channel2 = IIO_MOD_X, | 63 | .channel2 = IIO_MOD_X, |
64 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
59 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 65 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
60 | BIT(IIO_CHAN_INFO_SCALE) | | 66 | BIT(IIO_CHAN_INFO_SCALE) | |
61 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 67 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
@@ -65,6 +71,7 @@ static const struct iio_chan_spec magn_3d_channels[] = { | |||
65 | .type = IIO_MAGN, | 71 | .type = IIO_MAGN, |
66 | .modified = 1, | 72 | .modified = 1, |
67 | .channel2 = IIO_MOD_Y, | 73 | .channel2 = IIO_MOD_Y, |
74 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
68 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 75 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
69 | BIT(IIO_CHAN_INFO_SCALE) | | 76 | BIT(IIO_CHAN_INFO_SCALE) | |
70 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 77 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
@@ -74,6 +81,7 @@ static const struct iio_chan_spec magn_3d_channels[] = { | |||
74 | .type = IIO_MAGN, | 81 | .type = IIO_MAGN, |
75 | .modified = 1, | 82 | .modified = 1, |
76 | .channel2 = IIO_MOD_Z, | 83 | .channel2 = IIO_MOD_Z, |
84 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
77 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 85 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
78 | BIT(IIO_CHAN_INFO_SCALE) | | 86 | BIT(IIO_CHAN_INFO_SCALE) | |
79 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 87 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
@@ -104,11 +112,20 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev, | |||
104 | u32 address; | 112 | u32 address; |
105 | int ret; | 113 | int ret; |
106 | int ret_type; | 114 | int ret_type; |
115 | s32 poll_value; | ||
107 | 116 | ||
108 | *val = 0; | 117 | *val = 0; |
109 | *val2 = 0; | 118 | *val2 = 0; |
110 | switch (mask) { | 119 | switch (mask) { |
111 | case 0: | 120 | case 0: |
121 | poll_value = hid_sensor_read_poll_value( | ||
122 | &magn_state->common_attributes); | ||
123 | if (poll_value < 0) | ||
124 | return -EINVAL; | ||
125 | |||
126 | hid_sensor_power_state(&magn_state->common_attributes, true); | ||
127 | msleep_interruptible(poll_value * 2); | ||
128 | |||
112 | report_id = | 129 | report_id = |
113 | magn_state->magn[chan->scan_index].report_id; | 130 | magn_state->magn[chan->scan_index].report_id; |
114 | address = magn_3d_addresses[chan->scan_index]; | 131 | address = magn_3d_addresses[chan->scan_index]; |
@@ -119,17 +136,20 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev, | |||
119 | report_id); | 136 | report_id); |
120 | else { | 137 | else { |
121 | *val = 0; | 138 | *val = 0; |
139 | hid_sensor_power_state(&magn_state->common_attributes, | ||
140 | false); | ||
122 | return -EINVAL; | 141 | return -EINVAL; |
123 | } | 142 | } |
143 | hid_sensor_power_state(&magn_state->common_attributes, false); | ||
124 | ret_type = IIO_VAL_INT; | 144 | ret_type = IIO_VAL_INT; |
125 | break; | 145 | break; |
126 | case IIO_CHAN_INFO_SCALE: | 146 | case IIO_CHAN_INFO_SCALE: |
127 | *val = magn_state->magn[CHANNEL_SCAN_INDEX_X].units; | 147 | *val = magn_state->scale_pre_decml; |
128 | ret_type = IIO_VAL_INT; | 148 | *val2 = magn_state->scale_post_decml; |
149 | ret_type = magn_state->scale_precision; | ||
129 | break; | 150 | break; |
130 | case IIO_CHAN_INFO_OFFSET: | 151 | case IIO_CHAN_INFO_OFFSET: |
131 | *val = hid_sensor_convert_exponent( | 152 | *val = magn_state->value_offset; |
132 | magn_state->magn[CHANNEL_SCAN_INDEX_X].unit_expo); | ||
133 | ret_type = IIO_VAL_INT; | 153 | ret_type = IIO_VAL_INT; |
134 | break; | 154 | break; |
135 | case IIO_CHAN_INFO_SAMP_FREQ: | 155 | case IIO_CHAN_INFO_SAMP_FREQ: |
@@ -198,9 +218,8 @@ static int magn_3d_proc_event(struct hid_sensor_hub_device *hsdev, | |||
198 | struct iio_dev *indio_dev = platform_get_drvdata(priv); | 218 | struct iio_dev *indio_dev = platform_get_drvdata(priv); |
199 | struct magn_3d_state *magn_state = iio_priv(indio_dev); | 219 | struct magn_3d_state *magn_state = iio_priv(indio_dev); |
200 | 220 | ||
201 | dev_dbg(&indio_dev->dev, "magn_3d_proc_event [%d]\n", | 221 | dev_dbg(&indio_dev->dev, "magn_3d_proc_event\n"); |
202 | magn_state->common_attributes.data_ready); | 222 | if (atomic_read(&magn_state->common_attributes.data_ready)) |
203 | if (magn_state->common_attributes.data_ready) | ||
204 | hid_sensor_push_data(indio_dev, | 223 | hid_sensor_push_data(indio_dev, |
205 | magn_state->magn_val, | 224 | magn_state->magn_val, |
206 | sizeof(magn_state->magn_val)); | 225 | sizeof(magn_state->magn_val)); |
@@ -263,6 +282,11 @@ static int magn_3d_parse_report(struct platform_device *pdev, | |||
263 | st->magn[1].index, st->magn[1].report_id, | 282 | st->magn[1].index, st->magn[1].report_id, |
264 | st->magn[2].index, st->magn[2].report_id); | 283 | st->magn[2].index, st->magn[2].report_id); |
265 | 284 | ||
285 | st->scale_precision = hid_sensor_format_scale( | ||
286 | HID_USAGE_SENSOR_COMPASS_3D, | ||
287 | &st->magn[CHANNEL_SCAN_INDEX_X], | ||
288 | &st->scale_pre_decml, &st->scale_post_decml); | ||
289 | |||
266 | /* Set Sensitivity field ids, when there is no individual modifier */ | 290 | /* Set Sensitivity field ids, when there is no individual modifier */ |
267 | if (st->common_attributes.sensitivity.index < 0) { | 291 | if (st->common_attributes.sensitivity.index < 0) { |
268 | sensor_hub_input_get_attribute_info(hsdev, | 292 | sensor_hub_input_get_attribute_info(hsdev, |
@@ -334,7 +358,7 @@ static int hid_magn_3d_probe(struct platform_device *pdev) | |||
334 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | 358 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); |
335 | goto error_free_dev_mem; | 359 | goto error_free_dev_mem; |
336 | } | 360 | } |
337 | magn_state->common_attributes.data_ready = false; | 361 | atomic_set(&magn_state->common_attributes.data_ready, 0); |
338 | ret = hid_sensor_setup_trigger(indio_dev, name, | 362 | ret = hid_sensor_setup_trigger(indio_dev, name, |
339 | &magn_state->common_attributes); | 363 | &magn_state->common_attributes); |
340 | if (ret < 0) { | 364 | if (ret < 0) { |
diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index 8b77782474d7..e3106b43ef48 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c | |||
@@ -199,6 +199,13 @@ static int mag3110_read_raw(struct iio_dev *indio_dev, | |||
199 | *val = mag3110_samp_freq[i][0]; | 199 | *val = mag3110_samp_freq[i][0]; |
200 | *val2 = mag3110_samp_freq[i][1]; | 200 | *val2 = mag3110_samp_freq[i][1]; |
201 | return IIO_VAL_INT_PLUS_MICRO; | 201 | return IIO_VAL_INT_PLUS_MICRO; |
202 | case IIO_CHAN_INFO_CALIBBIAS: | ||
203 | ret = i2c_smbus_read_word_swapped(data->client, | ||
204 | MAG3110_OFF_X + 2 * chan->scan_index); | ||
205 | if (ret < 0) | ||
206 | return ret; | ||
207 | *val = sign_extend32(ret >> 1, 14); | ||
208 | return IIO_VAL_INT; | ||
202 | } | 209 | } |
203 | return -EINVAL; | 210 | return -EINVAL; |
204 | } | 211 | } |
@@ -223,6 +230,11 @@ static int mag3110_write_raw(struct iio_dev *indio_dev, | |||
223 | data->ctrl_reg1 |= rate << MAG3110_CTRL_DR_SHIFT; | 230 | data->ctrl_reg1 |= rate << MAG3110_CTRL_DR_SHIFT; |
224 | return i2c_smbus_write_byte_data(data->client, | 231 | return i2c_smbus_write_byte_data(data->client, |
225 | MAG3110_CTRL_REG1, data->ctrl_reg1); | 232 | MAG3110_CTRL_REG1, data->ctrl_reg1); |
233 | case IIO_CHAN_INFO_CALIBBIAS: | ||
234 | if (val < -10000 || val > 10000) | ||
235 | return -EINVAL; | ||
236 | return i2c_smbus_write_word_swapped(data->client, | ||
237 | MAG3110_OFF_X + 2 * chan->scan_index, val << 1); | ||
226 | default: | 238 | default: |
227 | return -EINVAL; | 239 | return -EINVAL; |
228 | } | 240 | } |
@@ -260,7 +272,8 @@ done: | |||
260 | .type = IIO_MAGN, \ | 272 | .type = IIO_MAGN, \ |
261 | .modified = 1, \ | 273 | .modified = 1, \ |
262 | .channel2 = IIO_MOD_##axis, \ | 274 | .channel2 = IIO_MOD_##axis, \ |
263 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | 275 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
276 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ | ||
264 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | 277 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ |
265 | BIT(IIO_CHAN_INFO_SCALE), \ | 278 | BIT(IIO_CHAN_INFO_SCALE), \ |
266 | .scan_index = idx, \ | 279 | .scan_index = idx, \ |
@@ -338,14 +351,14 @@ static int mag3110_probe(struct i2c_client *client, | |||
338 | indio_dev->num_channels = ARRAY_SIZE(mag3110_channels); | 351 | indio_dev->num_channels = ARRAY_SIZE(mag3110_channels); |
339 | indio_dev->available_scan_masks = mag3110_scan_masks; | 352 | indio_dev->available_scan_masks = mag3110_scan_masks; |
340 | 353 | ||
341 | data->ctrl_reg1 = MAG3110_CTRL_DR_DEFAULT; | 354 | data->ctrl_reg1 = MAG3110_CTRL_DR_DEFAULT << MAG3110_CTRL_DR_SHIFT; |
342 | ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG1, | 355 | ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG1, |
343 | data->ctrl_reg1); | 356 | data->ctrl_reg1); |
344 | if (ret < 0) | 357 | if (ret < 0) |
345 | return ret; | 358 | return ret; |
346 | 359 | ||
347 | ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2, | 360 | ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2, |
348 | MAG3110_CTRL_AUTO_MRST_EN | MAG3110_CTRL_RAW); | 361 | MAG3110_CTRL_AUTO_MRST_EN); |
349 | if (ret < 0) | 362 | if (ret < 0) |
350 | return ret; | 363 | return ret; |
351 | 364 | ||
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 52bbcfa1e077..240a21dd0c61 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c | |||
@@ -355,6 +355,8 @@ int st_magn_common_probe(struct iio_dev *indio_dev, | |||
355 | indio_dev->modes = INDIO_DIRECT_MODE; | 355 | indio_dev->modes = INDIO_DIRECT_MODE; |
356 | indio_dev->info = &magn_info; | 356 | indio_dev->info = &magn_info; |
357 | 357 | ||
358 | st_sensors_power_enable(indio_dev); | ||
359 | |||
358 | err = st_sensors_check_device_support(indio_dev, | 360 | err = st_sensors_check_device_support(indio_dev, |
359 | ARRAY_SIZE(st_magn_sensors), st_magn_sensors); | 361 | ARRAY_SIZE(st_magn_sensors), st_magn_sensors); |
360 | if (err < 0) | 362 | if (err < 0) |
@@ -387,6 +389,9 @@ int st_magn_common_probe(struct iio_dev *indio_dev, | |||
387 | if (err) | 389 | if (err) |
388 | goto st_magn_device_register_error; | 390 | goto st_magn_device_register_error; |
389 | 391 | ||
392 | dev_info(&indio_dev->dev, "registered magnetometer %s\n", | ||
393 | indio_dev->name); | ||
394 | |||
390 | return 0; | 395 | return 0; |
391 | 396 | ||
392 | st_magn_device_register_error: | 397 | st_magn_device_register_error: |
@@ -403,6 +408,8 @@ void st_magn_common_remove(struct iio_dev *indio_dev) | |||
403 | { | 408 | { |
404 | struct st_sensor_data *mdata = iio_priv(indio_dev); | 409 | struct st_sensor_data *mdata = iio_priv(indio_dev); |
405 | 410 | ||
411 | st_sensors_power_disable(indio_dev); | ||
412 | |||
406 | iio_device_unregister(indio_dev); | 413 | iio_device_unregister(indio_dev); |
407 | if (mdata->get_irq_data_ready(indio_dev) > 0) | 414 | if (mdata->get_irq_data_ready(indio_dev) > 0) |
408 | st_sensors_deallocate_trigger(indio_dev); | 415 | st_sensors_deallocate_trigger(indio_dev); |
diff --git a/drivers/iio/orientation/Kconfig b/drivers/iio/orientation/Kconfig index 58c62c837e12..e3aa1e58d920 100644 --- a/drivers/iio/orientation/Kconfig +++ b/drivers/iio/orientation/Kconfig | |||
@@ -16,4 +16,16 @@ config HID_SENSOR_INCLINOMETER_3D | |||
16 | Say yes here to build support for the HID SENSOR | 16 | Say yes here to build support for the HID SENSOR |
17 | Inclinometer 3D. | 17 | Inclinometer 3D. |
18 | 18 | ||
19 | config HID_SENSOR_DEVICE_ROTATION | ||
20 | depends on HID_SENSOR_HUB | ||
21 | select IIO_BUFFER | ||
22 | select IIO_TRIGGERED_BUFFER | ||
23 | select HID_SENSOR_IIO_COMMON | ||
24 | select HID_SENSOR_IIO_TRIGGER | ||
25 | tristate "HID Device Rotation" | ||
26 | help | ||
27 | Say yes here to build support for the HID SENSOR | ||
28 | device rotation. The output of a device rotation sensor | ||
29 | is presented using quaternion format. | ||
30 | |||
19 | endmenu | 31 | endmenu |
diff --git a/drivers/iio/orientation/Makefile b/drivers/iio/orientation/Makefile index 2c97572ee919..4734dabbde13 100644 --- a/drivers/iio/orientation/Makefile +++ b/drivers/iio/orientation/Makefile | |||
@@ -4,3 +4,4 @@ | |||
4 | 4 | ||
5 | # When adding new entries keep the list in alphabetical order | 5 | # When adding new entries keep the list in alphabetical order |
6 | obj-$(CONFIG_HID_SENSOR_INCLINOMETER_3D) += hid-sensor-incl-3d.o | 6 | obj-$(CONFIG_HID_SENSOR_INCLINOMETER_3D) += hid-sensor-incl-3d.o |
7 | obj-$(CONFIG_HID_SENSOR_DEVICE_ROTATION) += hid-sensor-rotation.o | ||
diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c index 070feab08faa..2478f6c2ef25 100644 --- a/drivers/iio/orientation/hid-sensor-incl-3d.c +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/delay.h> | ||
25 | #include <linux/hid-sensor-hub.h> | 26 | #include <linux/hid-sensor-hub.h> |
26 | #include <linux/iio/iio.h> | 27 | #include <linux/iio/iio.h> |
27 | #include <linux/iio/sysfs.h> | 28 | #include <linux/iio/sysfs.h> |
@@ -42,6 +43,10 @@ struct incl_3d_state { | |||
42 | struct hid_sensor_common common_attributes; | 43 | struct hid_sensor_common common_attributes; |
43 | struct hid_sensor_hub_attribute_info incl[INCLI_3D_CHANNEL_MAX]; | 44 | struct hid_sensor_hub_attribute_info incl[INCLI_3D_CHANNEL_MAX]; |
44 | u32 incl_val[INCLI_3D_CHANNEL_MAX]; | 45 | u32 incl_val[INCLI_3D_CHANNEL_MAX]; |
46 | int scale_pre_decml; | ||
47 | int scale_post_decml; | ||
48 | int scale_precision; | ||
49 | int value_offset; | ||
45 | }; | 50 | }; |
46 | 51 | ||
47 | static const u32 incl_3d_addresses[INCLI_3D_CHANNEL_MAX] = { | 52 | static const u32 incl_3d_addresses[INCLI_3D_CHANNEL_MAX] = { |
@@ -106,11 +111,20 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev, | |||
106 | int report_id = -1; | 111 | int report_id = -1; |
107 | u32 address; | 112 | u32 address; |
108 | int ret_type; | 113 | int ret_type; |
114 | s32 poll_value; | ||
109 | 115 | ||
110 | *val = 0; | 116 | *val = 0; |
111 | *val2 = 0; | 117 | *val2 = 0; |
112 | switch (mask) { | 118 | switch (mask) { |
113 | case IIO_CHAN_INFO_RAW: | 119 | case IIO_CHAN_INFO_RAW: |
120 | poll_value = hid_sensor_read_poll_value( | ||
121 | &incl_state->common_attributes); | ||
122 | if (poll_value < 0) | ||
123 | return -EINVAL; | ||
124 | |||
125 | hid_sensor_power_state(&incl_state->common_attributes, true); | ||
126 | msleep_interruptible(poll_value * 2); | ||
127 | |||
114 | report_id = | 128 | report_id = |
115 | incl_state->incl[chan->scan_index].report_id; | 129 | incl_state->incl[chan->scan_index].report_id; |
116 | address = incl_3d_addresses[chan->scan_index]; | 130 | address = incl_3d_addresses[chan->scan_index]; |
@@ -120,17 +134,20 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev, | |||
120 | HID_USAGE_SENSOR_INCLINOMETER_3D, address, | 134 | HID_USAGE_SENSOR_INCLINOMETER_3D, address, |
121 | report_id); | 135 | report_id); |
122 | else { | 136 | else { |
137 | hid_sensor_power_state(&incl_state->common_attributes, | ||
138 | false); | ||
123 | return -EINVAL; | 139 | return -EINVAL; |
124 | } | 140 | } |
141 | hid_sensor_power_state(&incl_state->common_attributes, false); | ||
125 | ret_type = IIO_VAL_INT; | 142 | ret_type = IIO_VAL_INT; |
126 | break; | 143 | break; |
127 | case IIO_CHAN_INFO_SCALE: | 144 | case IIO_CHAN_INFO_SCALE: |
128 | *val = incl_state->incl[CHANNEL_SCAN_INDEX_X].units; | 145 | *val = incl_state->scale_pre_decml; |
129 | ret_type = IIO_VAL_INT; | 146 | *val2 = incl_state->scale_post_decml; |
147 | ret_type = incl_state->scale_precision; | ||
130 | break; | 148 | break; |
131 | case IIO_CHAN_INFO_OFFSET: | 149 | case IIO_CHAN_INFO_OFFSET: |
132 | *val = hid_sensor_convert_exponent( | 150 | *val = incl_state->value_offset; |
133 | incl_state->incl[CHANNEL_SCAN_INDEX_X].unit_expo); | ||
134 | ret_type = IIO_VAL_INT; | 151 | ret_type = IIO_VAL_INT; |
135 | break; | 152 | break; |
136 | case IIO_CHAN_INFO_SAMP_FREQ: | 153 | case IIO_CHAN_INFO_SAMP_FREQ: |
@@ -196,9 +213,8 @@ static int incl_3d_proc_event(struct hid_sensor_hub_device *hsdev, | |||
196 | struct iio_dev *indio_dev = platform_get_drvdata(priv); | 213 | struct iio_dev *indio_dev = platform_get_drvdata(priv); |
197 | struct incl_3d_state *incl_state = iio_priv(indio_dev); | 214 | struct incl_3d_state *incl_state = iio_priv(indio_dev); |
198 | 215 | ||
199 | dev_dbg(&indio_dev->dev, "incl_3d_proc_event [%d]\n", | 216 | dev_dbg(&indio_dev->dev, "incl_3d_proc_event\n"); |
200 | incl_state->common_attributes.data_ready); | 217 | if (atomic_read(&incl_state->common_attributes.data_ready)) |
201 | if (incl_state->common_attributes.data_ready) | ||
202 | hid_sensor_push_data(indio_dev, | 218 | hid_sensor_push_data(indio_dev, |
203 | (u8 *)incl_state->incl_val, | 219 | (u8 *)incl_state->incl_val, |
204 | sizeof(incl_state->incl_val)); | 220 | sizeof(incl_state->incl_val)); |
@@ -279,6 +295,11 @@ static int incl_3d_parse_report(struct platform_device *pdev, | |||
279 | st->incl[1].index, st->incl[1].report_id, | 295 | st->incl[1].index, st->incl[1].report_id, |
280 | st->incl[2].index, st->incl[2].report_id); | 296 | st->incl[2].index, st->incl[2].report_id); |
281 | 297 | ||
298 | st->scale_precision = hid_sensor_format_scale( | ||
299 | HID_USAGE_SENSOR_INCLINOMETER_3D, | ||
300 | &st->incl[CHANNEL_SCAN_INDEX_X], | ||
301 | &st->scale_pre_decml, &st->scale_post_decml); | ||
302 | |||
282 | /* Set Sensitivity field ids, when there is no individual modifier */ | 303 | /* Set Sensitivity field ids, when there is no individual modifier */ |
283 | if (st->common_attributes.sensitivity.index < 0) { | 304 | if (st->common_attributes.sensitivity.index < 0) { |
284 | sensor_hub_input_get_attribute_info(hsdev, | 305 | sensor_hub_input_get_attribute_info(hsdev, |
@@ -349,7 +370,7 @@ static int hid_incl_3d_probe(struct platform_device *pdev) | |||
349 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | 370 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); |
350 | goto error_free_dev_mem; | 371 | goto error_free_dev_mem; |
351 | } | 372 | } |
352 | incl_state->common_attributes.data_ready = false; | 373 | atomic_set(&incl_state->common_attributes.data_ready, 0); |
353 | ret = hid_sensor_setup_trigger(indio_dev, name, | 374 | ret = hid_sensor_setup_trigger(indio_dev, name, |
354 | &incl_state->common_attributes); | 375 | &incl_state->common_attributes); |
355 | if (ret) { | 376 | if (ret) { |
diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c new file mode 100644 index 000000000000..dccf848e8b0f --- /dev/null +++ b/drivers/iio/orientation/hid-sensor-rotation.c | |||
@@ -0,0 +1,346 @@ | |||
1 | /* | ||
2 | * HID Sensors Driver | ||
3 | * Copyright (c) 2014, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/hid-sensor-hub.h> | ||
22 | #include <linux/iio/iio.h> | ||
23 | #include <linux/iio/sysfs.h> | ||
24 | #include <linux/iio/buffer.h> | ||
25 | #include <linux/iio/trigger_consumer.h> | ||
26 | #include <linux/iio/triggered_buffer.h> | ||
27 | #include "../common/hid-sensors/hid-sensor-trigger.h" | ||
28 | |||
29 | struct dev_rot_state { | ||
30 | struct hid_sensor_hub_callbacks callbacks; | ||
31 | struct hid_sensor_common common_attributes; | ||
32 | struct hid_sensor_hub_attribute_info quaternion; | ||
33 | u32 sampled_vals[4]; | ||
34 | }; | ||
35 | |||
36 | /* Channel definitions */ | ||
37 | static const struct iio_chan_spec dev_rot_channels[] = { | ||
38 | { | ||
39 | .type = IIO_ROT, | ||
40 | .modified = 1, | ||
41 | .channel2 = IIO_MOD_QUATERNION, | ||
42 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
43 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | | ||
44 | BIT(IIO_CHAN_INFO_HYSTERESIS) | ||
45 | } | ||
46 | }; | ||
47 | |||
48 | /* Adjust channel real bits based on report descriptor */ | ||
49 | static void dev_rot_adjust_channel_bit_mask(struct iio_chan_spec *chan, | ||
50 | int size) | ||
51 | { | ||
52 | chan->scan_type.sign = 's'; | ||
53 | /* Real storage bits will change based on the report desc. */ | ||
54 | chan->scan_type.realbits = size * 8; | ||
55 | /* Maximum size of a sample to capture is u32 */ | ||
56 | chan->scan_type.storagebits = sizeof(u32) * 8; | ||
57 | chan->scan_type.repeat = 4; | ||
58 | } | ||
59 | |||
60 | /* Channel read_raw handler */ | ||
61 | static int dev_rot_read_raw(struct iio_dev *indio_dev, | ||
62 | struct iio_chan_spec const *chan, | ||
63 | int size, int *vals, int *val_len, | ||
64 | long mask) | ||
65 | { | ||
66 | struct dev_rot_state *rot_state = iio_priv(indio_dev); | ||
67 | int ret_type; | ||
68 | int i; | ||
69 | |||
70 | vals[0] = 0; | ||
71 | vals[1] = 0; | ||
72 | |||
73 | switch (mask) { | ||
74 | case IIO_CHAN_INFO_RAW: | ||
75 | if (size >= 4) { | ||
76 | for (i = 0; i < 4; ++i) | ||
77 | vals[i] = rot_state->sampled_vals[i]; | ||
78 | ret_type = IIO_VAL_INT_MULTIPLE; | ||
79 | *val_len = 4; | ||
80 | } else | ||
81 | ret_type = -EINVAL; | ||
82 | break; | ||
83 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
84 | ret_type = hid_sensor_read_samp_freq_value( | ||
85 | &rot_state->common_attributes, &vals[0], &vals[1]); | ||
86 | break; | ||
87 | case IIO_CHAN_INFO_HYSTERESIS: | ||
88 | ret_type = hid_sensor_read_raw_hyst_value( | ||
89 | &rot_state->common_attributes, &vals[0], &vals[1]); | ||
90 | break; | ||
91 | default: | ||
92 | ret_type = -EINVAL; | ||
93 | break; | ||
94 | } | ||
95 | |||
96 | return ret_type; | ||
97 | } | ||
98 | |||
99 | /* Channel write_raw handler */ | ||
100 | static int dev_rot_write_raw(struct iio_dev *indio_dev, | ||
101 | struct iio_chan_spec const *chan, | ||
102 | int val, | ||
103 | int val2, | ||
104 | long mask) | ||
105 | { | ||
106 | struct dev_rot_state *rot_state = iio_priv(indio_dev); | ||
107 | int ret; | ||
108 | |||
109 | switch (mask) { | ||
110 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
111 | ret = hid_sensor_write_samp_freq_value( | ||
112 | &rot_state->common_attributes, val, val2); | ||
113 | break; | ||
114 | case IIO_CHAN_INFO_HYSTERESIS: | ||
115 | ret = hid_sensor_write_raw_hyst_value( | ||
116 | &rot_state->common_attributes, val, val2); | ||
117 | break; | ||
118 | default: | ||
119 | ret = -EINVAL; | ||
120 | } | ||
121 | |||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static const struct iio_info dev_rot_info = { | ||
126 | .driver_module = THIS_MODULE, | ||
127 | .read_raw_multi = &dev_rot_read_raw, | ||
128 | .write_raw = &dev_rot_write_raw, | ||
129 | }; | ||
130 | |||
131 | /* Function to push data to buffer */ | ||
132 | static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) | ||
133 | { | ||
134 | dev_dbg(&indio_dev->dev, "hid_sensor_push_data >>\n"); | ||
135 | iio_push_to_buffers(indio_dev, (u8 *)data); | ||
136 | dev_dbg(&indio_dev->dev, "hid_sensor_push_data <<\n"); | ||
137 | |||
138 | } | ||
139 | |||
140 | /* Callback handler to send event after all samples are received and captured */ | ||
141 | static int dev_rot_proc_event(struct hid_sensor_hub_device *hsdev, | ||
142 | unsigned usage_id, | ||
143 | void *priv) | ||
144 | { | ||
145 | struct iio_dev *indio_dev = platform_get_drvdata(priv); | ||
146 | struct dev_rot_state *rot_state = iio_priv(indio_dev); | ||
147 | |||
148 | dev_dbg(&indio_dev->dev, "dev_rot_proc_event\n"); | ||
149 | if (atomic_read(&rot_state->common_attributes.data_ready)) | ||
150 | hid_sensor_push_data(indio_dev, | ||
151 | (u8 *)rot_state->sampled_vals, | ||
152 | sizeof(rot_state->sampled_vals)); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /* Capture samples in local storage */ | ||
158 | static int dev_rot_capture_sample(struct hid_sensor_hub_device *hsdev, | ||
159 | unsigned usage_id, | ||
160 | size_t raw_len, char *raw_data, | ||
161 | void *priv) | ||
162 | { | ||
163 | struct iio_dev *indio_dev = platform_get_drvdata(priv); | ||
164 | struct dev_rot_state *rot_state = iio_priv(indio_dev); | ||
165 | |||
166 | if (usage_id == HID_USAGE_SENSOR_ORIENT_QUATERNION) { | ||
167 | memcpy(rot_state->sampled_vals, raw_data, | ||
168 | sizeof(rot_state->sampled_vals)); | ||
169 | dev_dbg(&indio_dev->dev, "Recd Quat len:%zu::%zu\n", raw_len, | ||
170 | sizeof(rot_state->sampled_vals)); | ||
171 | } | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /* Parse report which is specific to an usage id*/ | ||
177 | static int dev_rot_parse_report(struct platform_device *pdev, | ||
178 | struct hid_sensor_hub_device *hsdev, | ||
179 | struct iio_chan_spec *channels, | ||
180 | unsigned usage_id, | ||
181 | struct dev_rot_state *st) | ||
182 | { | ||
183 | int ret; | ||
184 | |||
185 | ret = sensor_hub_input_get_attribute_info(hsdev, | ||
186 | HID_INPUT_REPORT, | ||
187 | usage_id, | ||
188 | HID_USAGE_SENSOR_ORIENT_QUATERNION, | ||
189 | &st->quaternion); | ||
190 | if (ret) | ||
191 | return ret; | ||
192 | |||
193 | dev_rot_adjust_channel_bit_mask(&channels[0], | ||
194 | st->quaternion.size / 4); | ||
195 | |||
196 | dev_dbg(&pdev->dev, "dev_rot %x:%x\n", st->quaternion.index, | ||
197 | st->quaternion.report_id); | ||
198 | |||
199 | dev_dbg(&pdev->dev, "dev_rot: attrib size %d\n", | ||
200 | st->quaternion.size); | ||
201 | |||
202 | /* Set Sensitivity field ids, when there is no individual modifier */ | ||
203 | if (st->common_attributes.sensitivity.index < 0) { | ||
204 | sensor_hub_input_get_attribute_info(hsdev, | ||
205 | HID_FEATURE_REPORT, usage_id, | ||
206 | HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | | ||
207 | HID_USAGE_SENSOR_DATA_ORIENTATION, | ||
208 | &st->common_attributes.sensitivity); | ||
209 | dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", | ||
210 | st->common_attributes.sensitivity.index, | ||
211 | st->common_attributes.sensitivity.report_id); | ||
212 | } | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | /* Function to initialize the processing for usage id */ | ||
218 | static int hid_dev_rot_probe(struct platform_device *pdev) | ||
219 | { | ||
220 | int ret; | ||
221 | static char *name = "dev_rotation"; | ||
222 | struct iio_dev *indio_dev; | ||
223 | struct dev_rot_state *rot_state; | ||
224 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | ||
225 | struct iio_chan_spec *channels; | ||
226 | |||
227 | indio_dev = devm_iio_device_alloc(&pdev->dev, | ||
228 | sizeof(struct dev_rot_state)); | ||
229 | if (indio_dev == NULL) | ||
230 | return -ENOMEM; | ||
231 | |||
232 | platform_set_drvdata(pdev, indio_dev); | ||
233 | |||
234 | rot_state = iio_priv(indio_dev); | ||
235 | rot_state->common_attributes.hsdev = hsdev; | ||
236 | rot_state->common_attributes.pdev = pdev; | ||
237 | |||
238 | ret = hid_sensor_parse_common_attributes(hsdev, | ||
239 | HID_USAGE_SENSOR_DEVICE_ORIENTATION, | ||
240 | &rot_state->common_attributes); | ||
241 | if (ret) { | ||
242 | dev_err(&pdev->dev, "failed to setup common attributes\n"); | ||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | channels = devm_kmemdup(&pdev->dev, dev_rot_channels, | ||
247 | sizeof(dev_rot_channels), GFP_KERNEL); | ||
248 | if (!channels) { | ||
249 | dev_err(&pdev->dev, "failed to duplicate channels\n"); | ||
250 | return -ENOMEM; | ||
251 | } | ||
252 | |||
253 | ret = dev_rot_parse_report(pdev, hsdev, channels, | ||
254 | HID_USAGE_SENSOR_DEVICE_ORIENTATION, rot_state); | ||
255 | if (ret) { | ||
256 | dev_err(&pdev->dev, "failed to setup attributes\n"); | ||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | indio_dev->channels = channels; | ||
261 | indio_dev->num_channels = ARRAY_SIZE(dev_rot_channels); | ||
262 | indio_dev->dev.parent = &pdev->dev; | ||
263 | indio_dev->info = &dev_rot_info; | ||
264 | indio_dev->name = name; | ||
265 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
266 | |||
267 | ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | ||
268 | NULL, NULL); | ||
269 | if (ret) { | ||
270 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | ||
271 | return ret; | ||
272 | } | ||
273 | atomic_set(&rot_state->common_attributes.data_ready, 0); | ||
274 | ret = hid_sensor_setup_trigger(indio_dev, name, | ||
275 | &rot_state->common_attributes); | ||
276 | if (ret) { | ||
277 | dev_err(&pdev->dev, "trigger setup failed\n"); | ||
278 | goto error_unreg_buffer_funcs; | ||
279 | } | ||
280 | |||
281 | ret = iio_device_register(indio_dev); | ||
282 | if (ret) { | ||
283 | dev_err(&pdev->dev, "device register failed\n"); | ||
284 | goto error_remove_trigger; | ||
285 | } | ||
286 | |||
287 | rot_state->callbacks.send_event = dev_rot_proc_event; | ||
288 | rot_state->callbacks.capture_sample = dev_rot_capture_sample; | ||
289 | rot_state->callbacks.pdev = pdev; | ||
290 | ret = sensor_hub_register_callback(hsdev, | ||
291 | HID_USAGE_SENSOR_DEVICE_ORIENTATION, | ||
292 | &rot_state->callbacks); | ||
293 | if (ret) { | ||
294 | dev_err(&pdev->dev, "callback reg failed\n"); | ||
295 | goto error_iio_unreg; | ||
296 | } | ||
297 | |||
298 | return 0; | ||
299 | |||
300 | error_iio_unreg: | ||
301 | iio_device_unregister(indio_dev); | ||
302 | error_remove_trigger: | ||
303 | hid_sensor_remove_trigger(&rot_state->common_attributes); | ||
304 | error_unreg_buffer_funcs: | ||
305 | iio_triggered_buffer_cleanup(indio_dev); | ||
306 | return ret; | ||
307 | } | ||
308 | |||
309 | /* Function to deinitialize the processing for usage id */ | ||
310 | static int hid_dev_rot_remove(struct platform_device *pdev) | ||
311 | { | ||
312 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | ||
313 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); | ||
314 | struct dev_rot_state *rot_state = iio_priv(indio_dev); | ||
315 | |||
316 | sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_DEVICE_ORIENTATION); | ||
317 | iio_device_unregister(indio_dev); | ||
318 | hid_sensor_remove_trigger(&rot_state->common_attributes); | ||
319 | iio_triggered_buffer_cleanup(indio_dev); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static struct platform_device_id hid_dev_rot_ids[] = { | ||
325 | { | ||
326 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ | ||
327 | .name = "HID-SENSOR-20008a", | ||
328 | }, | ||
329 | { /* sentinel */ } | ||
330 | }; | ||
331 | MODULE_DEVICE_TABLE(platform, hid_dev_rot_ids); | ||
332 | |||
333 | static struct platform_driver hid_dev_rot_platform_driver = { | ||
334 | .id_table = hid_dev_rot_ids, | ||
335 | .driver = { | ||
336 | .name = KBUILD_MODNAME, | ||
337 | .owner = THIS_MODULE, | ||
338 | }, | ||
339 | .probe = hid_dev_rot_probe, | ||
340 | .remove = hid_dev_rot_remove, | ||
341 | }; | ||
342 | module_platform_driver(hid_dev_rot_platform_driver); | ||
343 | |||
344 | MODULE_DESCRIPTION("HID Sensor Device Rotation"); | ||
345 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); | ||
346 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index d88ff17fedb2..ffac8ac1efca 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig | |||
@@ -19,6 +19,16 @@ config HID_SENSOR_PRESS | |||
19 | To compile this driver as a module, choose M here: the module | 19 | To compile this driver as a module, choose M here: the module |
20 | will be called hid-sensor-press. | 20 | will be called hid-sensor-press. |
21 | 21 | ||
22 | config MPL115 | ||
23 | tristate "Freescale MPL115A2 pressure sensor driver" | ||
24 | depends on I2C | ||
25 | help | ||
26 | Say yes here to build support for the Freescale MPL115A2 | ||
27 | pressure sensor connected via I2C. | ||
28 | |||
29 | To compile this driver as a module, choose M here: the module | ||
30 | will be called mpl115. | ||
31 | |||
22 | config MPL3115 | 32 | config MPL3115 |
23 | tristate "Freescale MPL3115A2 pressure sensor driver" | 33 | tristate "Freescale MPL3115A2 pressure sensor driver" |
24 | depends on I2C | 34 | depends on I2C |
diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index 4a57bf65b04b..c53d2500737a 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | # When adding new entries keep the list in alphabetical order | 5 | # When adding new entries keep the list in alphabetical order |
6 | obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o | 6 | obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o |
7 | obj-$(CONFIG_MPL115) += mpl115.o | ||
7 | obj-$(CONFIG_MPL3115) += mpl3115.o | 8 | obj-$(CONFIG_MPL3115) += mpl3115.o |
8 | obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o | 9 | obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o |
9 | st_pressure-y := st_pressure_core.o | 10 | st_pressure-y := st_pressure_core.o |
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c index e0e6409aa94e..1cd190c73788 100644 --- a/drivers/iio/pressure/hid-sensor-press.c +++ b/drivers/iio/pressure/hid-sensor-press.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/delay.h> | ||
24 | #include <linux/hid-sensor-hub.h> | 25 | #include <linux/hid-sensor-hub.h> |
25 | #include <linux/iio/iio.h> | 26 | #include <linux/iio/iio.h> |
26 | #include <linux/iio/sysfs.h> | 27 | #include <linux/iio/sysfs.h> |
@@ -36,6 +37,10 @@ struct press_state { | |||
36 | struct hid_sensor_common common_attributes; | 37 | struct hid_sensor_common common_attributes; |
37 | struct hid_sensor_hub_attribute_info press_attr; | 38 | struct hid_sensor_hub_attribute_info press_attr; |
38 | u32 press_data; | 39 | u32 press_data; |
40 | int scale_pre_decml; | ||
41 | int scale_post_decml; | ||
42 | int scale_precision; | ||
43 | int value_offset; | ||
39 | }; | 44 | }; |
40 | 45 | ||
41 | /* Channel definitions */ | 46 | /* Channel definitions */ |
@@ -75,6 +80,7 @@ static int press_read_raw(struct iio_dev *indio_dev, | |||
75 | u32 address; | 80 | u32 address; |
76 | int ret; | 81 | int ret; |
77 | int ret_type; | 82 | int ret_type; |
83 | s32 poll_value; | ||
78 | 84 | ||
79 | *val = 0; | 85 | *val = 0; |
80 | *val2 = 0; | 86 | *val2 = 0; |
@@ -90,24 +96,35 @@ static int press_read_raw(struct iio_dev *indio_dev, | |||
90 | report_id = -1; | 96 | report_id = -1; |
91 | break; | 97 | break; |
92 | } | 98 | } |
93 | if (report_id >= 0) | 99 | if (report_id >= 0) { |
100 | poll_value = hid_sensor_read_poll_value( | ||
101 | &press_state->common_attributes); | ||
102 | if (poll_value < 0) | ||
103 | return -EINVAL; | ||
104 | hid_sensor_power_state(&press_state->common_attributes, | ||
105 | true); | ||
106 | |||
107 | msleep_interruptible(poll_value * 2); | ||
108 | |||
94 | *val = sensor_hub_input_attr_get_raw_value( | 109 | *val = sensor_hub_input_attr_get_raw_value( |
95 | press_state->common_attributes.hsdev, | 110 | press_state->common_attributes.hsdev, |
96 | HID_USAGE_SENSOR_PRESSURE, address, | 111 | HID_USAGE_SENSOR_PRESSURE, address, |
97 | report_id); | 112 | report_id); |
98 | else { | 113 | hid_sensor_power_state(&press_state->common_attributes, |
114 | false); | ||
115 | } else { | ||
99 | *val = 0; | 116 | *val = 0; |
100 | return -EINVAL; | 117 | return -EINVAL; |
101 | } | 118 | } |
102 | ret_type = IIO_VAL_INT; | 119 | ret_type = IIO_VAL_INT; |
103 | break; | 120 | break; |
104 | case IIO_CHAN_INFO_SCALE: | 121 | case IIO_CHAN_INFO_SCALE: |
105 | *val = press_state->press_attr.units; | 122 | *val = press_state->scale_pre_decml; |
106 | ret_type = IIO_VAL_INT; | 123 | *val2 = press_state->scale_post_decml; |
124 | ret_type = press_state->scale_precision; | ||
107 | break; | 125 | break; |
108 | case IIO_CHAN_INFO_OFFSET: | 126 | case IIO_CHAN_INFO_OFFSET: |
109 | *val = hid_sensor_convert_exponent( | 127 | *val = press_state->value_offset; |
110 | press_state->press_attr.unit_expo); | ||
111 | ret_type = IIO_VAL_INT; | 128 | ret_type = IIO_VAL_INT; |
112 | break; | 129 | break; |
113 | case IIO_CHAN_INFO_SAMP_FREQ: | 130 | case IIO_CHAN_INFO_SAMP_FREQ: |
@@ -176,9 +193,8 @@ static int press_proc_event(struct hid_sensor_hub_device *hsdev, | |||
176 | struct iio_dev *indio_dev = platform_get_drvdata(priv); | 193 | struct iio_dev *indio_dev = platform_get_drvdata(priv); |
177 | struct press_state *press_state = iio_priv(indio_dev); | 194 | struct press_state *press_state = iio_priv(indio_dev); |
178 | 195 | ||
179 | dev_dbg(&indio_dev->dev, "press_proc_event [%d]\n", | 196 | dev_dbg(&indio_dev->dev, "press_proc_event\n"); |
180 | press_state->common_attributes.data_ready); | 197 | if (atomic_read(&press_state->common_attributes.data_ready)) |
181 | if (press_state->common_attributes.data_ready) | ||
182 | hid_sensor_push_data(indio_dev, | 198 | hid_sensor_push_data(indio_dev, |
183 | &press_state->press_data, | 199 | &press_state->press_data, |
184 | sizeof(press_state->press_data)); | 200 | sizeof(press_state->press_data)); |
@@ -229,6 +245,11 @@ static int press_parse_report(struct platform_device *pdev, | |||
229 | dev_dbg(&pdev->dev, "press %x:%x\n", st->press_attr.index, | 245 | dev_dbg(&pdev->dev, "press %x:%x\n", st->press_attr.index, |
230 | st->press_attr.report_id); | 246 | st->press_attr.report_id); |
231 | 247 | ||
248 | st->scale_precision = hid_sensor_format_scale( | ||
249 | HID_USAGE_SENSOR_PRESSURE, | ||
250 | &st->press_attr, | ||
251 | &st->scale_pre_decml, &st->scale_post_decml); | ||
252 | |||
232 | /* Set Sensitivity field ids, when there is no individual modifier */ | 253 | /* Set Sensitivity field ids, when there is no individual modifier */ |
233 | if (st->common_attributes.sensitivity.index < 0) { | 254 | if (st->common_attributes.sensitivity.index < 0) { |
234 | sensor_hub_input_get_attribute_info(hsdev, | 255 | sensor_hub_input_get_attribute_info(hsdev, |
@@ -298,7 +319,7 @@ static int hid_press_probe(struct platform_device *pdev) | |||
298 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | 319 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); |
299 | goto error_free_dev_mem; | 320 | goto error_free_dev_mem; |
300 | } | 321 | } |
301 | press_state->common_attributes.data_ready = false; | 322 | atomic_set(&press_state->common_attributes.data_ready, 0); |
302 | ret = hid_sensor_setup_trigger(indio_dev, name, | 323 | ret = hid_sensor_setup_trigger(indio_dev, name, |
303 | &press_state->common_attributes); | 324 | &press_state->common_attributes); |
304 | if (ret) { | 325 | if (ret) { |
diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c new file mode 100644 index 000000000000..f5ecd6e19f5d --- /dev/null +++ b/drivers/iio/pressure/mpl115.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * mpl115.c - Support for Freescale MPL115A2 pressure/temperature sensor | ||
3 | * | ||
4 | * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net> | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of version 2 of | ||
7 | * the GNU General Public License. See the file COPYING in the main | ||
8 | * directory of this archive for more details. | ||
9 | * | ||
10 | * (7-bit I2C slave address 0x60) | ||
11 | * | ||
12 | * TODO: shutdown pin | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/iio/iio.h> | ||
19 | #include <linux/delay.h> | ||
20 | |||
21 | #define MPL115_PADC 0x00 /* pressure ADC output value, MSB first, 10 bit */ | ||
22 | #define MPL115_TADC 0x02 /* temperature ADC output value, MSB first, 10 bit */ | ||
23 | #define MPL115_A0 0x04 /* 12 bit integer, 3 bit fraction */ | ||
24 | #define MPL115_B1 0x06 /* 2 bit integer, 13 bit fraction */ | ||
25 | #define MPL115_B2 0x08 /* 1 bit integer, 14 bit fraction */ | ||
26 | #define MPL115_C12 0x0a /* 0 bit integer, 13 bit fraction */ | ||
27 | #define MPL115_CONVERT 0x12 /* convert temperature and pressure */ | ||
28 | |||
29 | struct mpl115_data { | ||
30 | struct i2c_client *client; | ||
31 | struct mutex lock; | ||
32 | s16 a0; | ||
33 | s16 b1, b2; | ||
34 | s16 c12; | ||
35 | }; | ||
36 | |||
37 | static int mpl115_request(struct mpl115_data *data) | ||
38 | { | ||
39 | int ret = i2c_smbus_write_byte_data(data->client, MPL115_CONVERT, 0); | ||
40 | if (ret < 0) | ||
41 | return ret; | ||
42 | |||
43 | usleep_range(3000, 4000); | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static int mpl115_comp_pressure(struct mpl115_data *data, int *val, int *val2) | ||
49 | { | ||
50 | int ret; | ||
51 | u16 padc, tadc; | ||
52 | int a1, y1, pcomp; | ||
53 | unsigned kpa; | ||
54 | |||
55 | mutex_lock(&data->lock); | ||
56 | ret = mpl115_request(data); | ||
57 | if (ret < 0) | ||
58 | goto done; | ||
59 | |||
60 | ret = i2c_smbus_read_word_swapped(data->client, MPL115_PADC); | ||
61 | if (ret < 0) | ||
62 | goto done; | ||
63 | padc = ret >> 6; | ||
64 | |||
65 | ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC); | ||
66 | if (ret < 0) | ||
67 | goto done; | ||
68 | tadc = ret >> 6; | ||
69 | |||
70 | /* see Freescale AN3785 */ | ||
71 | a1 = data->b1 + ((data->c12 * tadc) >> 11); | ||
72 | y1 = (data->a0 << 10) + a1 * padc; | ||
73 | |||
74 | /* compensated pressure with 4 fractional bits */ | ||
75 | pcomp = (y1 + ((data->b2 * (int) tadc) >> 1)) >> 9; | ||
76 | |||
77 | kpa = pcomp * (115 - 50) / 1023 + (50 << 4); | ||
78 | *val = kpa >> 4; | ||
79 | *val2 = (kpa & 15) * (1000000 >> 4); | ||
80 | done: | ||
81 | mutex_unlock(&data->lock); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static int mpl115_read_temp(struct mpl115_data *data) | ||
86 | { | ||
87 | int ret; | ||
88 | |||
89 | mutex_lock(&data->lock); | ||
90 | ret = mpl115_request(data); | ||
91 | if (ret < 0) | ||
92 | goto done; | ||
93 | ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC); | ||
94 | done: | ||
95 | mutex_unlock(&data->lock); | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | static int mpl115_read_raw(struct iio_dev *indio_dev, | ||
100 | struct iio_chan_spec const *chan, | ||
101 | int *val, int *val2, long mask) | ||
102 | { | ||
103 | struct mpl115_data *data = iio_priv(indio_dev); | ||
104 | int ret; | ||
105 | |||
106 | switch (mask) { | ||
107 | case IIO_CHAN_INFO_PROCESSED: | ||
108 | ret = mpl115_comp_pressure(data, val, val2); | ||
109 | if (ret < 0) | ||
110 | return ret; | ||
111 | return IIO_VAL_INT_PLUS_MICRO; | ||
112 | case IIO_CHAN_INFO_RAW: | ||
113 | /* temperature -5.35 C / LSB, 472 LSB is 25 C */ | ||
114 | ret = mpl115_read_temp(data); | ||
115 | if (ret < 0) | ||
116 | return ret; | ||
117 | *val = ret >> 6; | ||
118 | return IIO_VAL_INT; | ||
119 | case IIO_CHAN_INFO_OFFSET: | ||
120 | *val = 605; | ||
121 | *val2 = 750000; | ||
122 | return IIO_VAL_INT_PLUS_MICRO; | ||
123 | case IIO_CHAN_INFO_SCALE: | ||
124 | *val = -186; | ||
125 | *val2 = 915888; | ||
126 | return IIO_VAL_INT_PLUS_MICRO; | ||
127 | } | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | |||
131 | static const struct iio_chan_spec mpl115_channels[] = { | ||
132 | { | ||
133 | .type = IIO_PRESSURE, | ||
134 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), | ||
135 | }, | ||
136 | { | ||
137 | .type = IIO_TEMP, | ||
138 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
139 | BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), | ||
140 | }, | ||
141 | }; | ||
142 | |||
143 | static const struct iio_info mpl115_info = { | ||
144 | .read_raw = &mpl115_read_raw, | ||
145 | .driver_module = THIS_MODULE, | ||
146 | }; | ||
147 | |||
148 | static int mpl115_probe(struct i2c_client *client, | ||
149 | const struct i2c_device_id *id) | ||
150 | { | ||
151 | struct mpl115_data *data; | ||
152 | struct iio_dev *indio_dev; | ||
153 | int ret; | ||
154 | |||
155 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) | ||
156 | return -ENODEV; | ||
157 | |||
158 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
159 | if (!indio_dev) | ||
160 | return -ENOMEM; | ||
161 | |||
162 | data = iio_priv(indio_dev); | ||
163 | data->client = client; | ||
164 | mutex_init(&data->lock); | ||
165 | |||
166 | i2c_set_clientdata(client, indio_dev); | ||
167 | indio_dev->info = &mpl115_info; | ||
168 | indio_dev->name = id->name; | ||
169 | indio_dev->dev.parent = &client->dev; | ||
170 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
171 | indio_dev->channels = mpl115_channels; | ||
172 | indio_dev->num_channels = ARRAY_SIZE(mpl115_channels); | ||
173 | |||
174 | ret = i2c_smbus_read_word_swapped(data->client, MPL115_A0); | ||
175 | if (ret < 0) | ||
176 | return ret; | ||
177 | data->a0 = ret; | ||
178 | ret = i2c_smbus_read_word_swapped(data->client, MPL115_B1); | ||
179 | if (ret < 0) | ||
180 | return ret; | ||
181 | data->b1 = ret; | ||
182 | ret = i2c_smbus_read_word_swapped(data->client, MPL115_B2); | ||
183 | if (ret < 0) | ||
184 | return ret; | ||
185 | data->b2 = ret; | ||
186 | ret = i2c_smbus_read_word_swapped(data->client, MPL115_C12); | ||
187 | if (ret < 0) | ||
188 | return ret; | ||
189 | data->c12 = ret; | ||
190 | |||
191 | return devm_iio_device_register(&client->dev, indio_dev); | ||
192 | } | ||
193 | |||
194 | static const struct i2c_device_id mpl115_id[] = { | ||
195 | { "mpl115", 0 }, | ||
196 | { } | ||
197 | }; | ||
198 | MODULE_DEVICE_TABLE(i2c, mpl115_id); | ||
199 | |||
200 | static struct i2c_driver mpl115_driver = { | ||
201 | .driver = { | ||
202 | .name = "mpl115", | ||
203 | }, | ||
204 | .probe = mpl115_probe, | ||
205 | .id_table = mpl115_id, | ||
206 | }; | ||
207 | module_i2c_driver(mpl115_driver); | ||
208 | |||
209 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); | ||
210 | MODULE_DESCRIPTION("Freescale MPL115 pressure/temperature driver"); | ||
211 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index 7418768ed49c..cd7e01f3a93b 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/iio/sysfs.h> | 23 | #include <linux/iio/sysfs.h> |
24 | #include <linux/iio/trigger.h> | 24 | #include <linux/iio/trigger.h> |
25 | #include <linux/iio/buffer.h> | 25 | #include <linux/iio/buffer.h> |
26 | #include <linux/regulator/consumer.h> | ||
27 | #include <asm/unaligned.h> | 26 | #include <asm/unaligned.h> |
28 | 27 | ||
29 | #include <linux/iio/common/st_sensors.h> | 28 | #include <linux/iio/common/st_sensors.h> |
@@ -387,40 +386,6 @@ static const struct iio_trigger_ops st_press_trigger_ops = { | |||
387 | #define ST_PRESS_TRIGGER_OPS NULL | 386 | #define ST_PRESS_TRIGGER_OPS NULL |
388 | #endif | 387 | #endif |
389 | 388 | ||
390 | static void st_press_power_enable(struct iio_dev *indio_dev) | ||
391 | { | ||
392 | struct st_sensor_data *pdata = iio_priv(indio_dev); | ||
393 | int err; | ||
394 | |||
395 | /* Regulators not mandatory, but if requested we should enable them. */ | ||
396 | pdata->vdd = devm_regulator_get_optional(&indio_dev->dev, "vdd"); | ||
397 | if (!IS_ERR(pdata->vdd)) { | ||
398 | err = regulator_enable(pdata->vdd); | ||
399 | if (err != 0) | ||
400 | dev_warn(&indio_dev->dev, | ||
401 | "Failed to enable specified Vdd supply\n"); | ||
402 | } | ||
403 | |||
404 | pdata->vdd_io = devm_regulator_get_optional(&indio_dev->dev, "vddio"); | ||
405 | if (!IS_ERR(pdata->vdd_io)) { | ||
406 | err = regulator_enable(pdata->vdd_io); | ||
407 | if (err != 0) | ||
408 | dev_warn(&indio_dev->dev, | ||
409 | "Failed to enable specified Vdd_IO supply\n"); | ||
410 | } | ||
411 | } | ||
412 | |||
413 | static void st_press_power_disable(struct iio_dev *indio_dev) | ||
414 | { | ||
415 | struct st_sensor_data *pdata = iio_priv(indio_dev); | ||
416 | |||
417 | if (!IS_ERR(pdata->vdd)) | ||
418 | regulator_disable(pdata->vdd); | ||
419 | |||
420 | if (!IS_ERR(pdata->vdd_io)) | ||
421 | regulator_disable(pdata->vdd_io); | ||
422 | } | ||
423 | |||
424 | int st_press_common_probe(struct iio_dev *indio_dev, | 389 | int st_press_common_probe(struct iio_dev *indio_dev, |
425 | struct st_sensors_platform_data *plat_data) | 390 | struct st_sensors_platform_data *plat_data) |
426 | { | 391 | { |
@@ -431,7 +396,7 @@ int st_press_common_probe(struct iio_dev *indio_dev, | |||
431 | indio_dev->modes = INDIO_DIRECT_MODE; | 396 | indio_dev->modes = INDIO_DIRECT_MODE; |
432 | indio_dev->info = &press_info; | 397 | indio_dev->info = &press_info; |
433 | 398 | ||
434 | st_press_power_enable(indio_dev); | 399 | st_sensors_power_enable(indio_dev); |
435 | 400 | ||
436 | err = st_sensors_check_device_support(indio_dev, | 401 | err = st_sensors_check_device_support(indio_dev, |
437 | ARRAY_SIZE(st_press_sensors), | 402 | ARRAY_SIZE(st_press_sensors), |
@@ -474,6 +439,9 @@ int st_press_common_probe(struct iio_dev *indio_dev, | |||
474 | if (err) | 439 | if (err) |
475 | goto st_press_device_register_error; | 440 | goto st_press_device_register_error; |
476 | 441 | ||
442 | dev_info(&indio_dev->dev, "registered pressure sensor %s\n", | ||
443 | indio_dev->name); | ||
444 | |||
477 | return err; | 445 | return err; |
478 | 446 | ||
479 | st_press_device_register_error: | 447 | st_press_device_register_error: |
@@ -490,7 +458,7 @@ void st_press_common_remove(struct iio_dev *indio_dev) | |||
490 | { | 458 | { |
491 | struct st_sensor_data *pdata = iio_priv(indio_dev); | 459 | struct st_sensor_data *pdata = iio_priv(indio_dev); |
492 | 460 | ||
493 | st_press_power_disable(indio_dev); | 461 | st_sensors_power_disable(indio_dev); |
494 | 462 | ||
495 | iio_device_unregister(indio_dev); | 463 | iio_device_unregister(indio_dev); |
496 | if (pdata->get_irq_data_ready(indio_dev) > 0) | 464 | if (pdata->get_irq_data_ready(indio_dev) > 0) |
diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig new file mode 100644 index 000000000000..0c8cdf58f6a1 --- /dev/null +++ b/drivers/iio/proximity/Kconfig | |||
@@ -0,0 +1,19 @@ | |||
1 | # | ||
2 | # Proximity sensors | ||
3 | # | ||
4 | |||
5 | menu "Lightning sensors" | ||
6 | |||
7 | config AS3935 | ||
8 | tristate "AS3935 Franklin lightning sensor" | ||
9 | select IIO_BUFFER | ||
10 | select IIO_TRIGGERED_BUFFER | ||
11 | depends on SPI | ||
12 | help | ||
13 | Say Y here to build SPI interface support for the Austrian | ||
14 | Microsystems AS3935 lightning detection sensor. | ||
15 | |||
16 | To compile this driver as a module, choose M here: the | ||
17 | module will be called as3935 | ||
18 | |||
19 | endmenu | ||
diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile new file mode 100644 index 000000000000..743adee1c8bf --- /dev/null +++ b/drivers/iio/proximity/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for IIO proximity sensors | ||
3 | # | ||
4 | |||
5 | # When adding new entries keep the list in alphabetical order | ||
6 | obj-$(CONFIG_AS3935) += as3935.o | ||
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c new file mode 100644 index 000000000000..bf677bfe8eb2 --- /dev/null +++ b/drivers/iio/proximity/as3935.c | |||
@@ -0,0 +1,456 @@ | |||
1 | /* | ||
2 | * as3935.c - Support for AS3935 Franklin lightning sensor | ||
3 | * | ||
4 | * Copyright (C) 2014 Matt Ranostay <mranostay@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/workqueue.h> | ||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/gpio.h> | ||
27 | #include <linux/spi/spi.h> | ||
28 | #include <linux/iio/iio.h> | ||
29 | #include <linux/iio/sysfs.h> | ||
30 | #include <linux/iio/trigger.h> | ||
31 | #include <linux/iio/trigger_consumer.h> | ||
32 | #include <linux/iio/buffer.h> | ||
33 | #include <linux/iio/triggered_buffer.h> | ||
34 | #include <linux/of_gpio.h> | ||
35 | |||
36 | |||
37 | #define AS3935_AFE_GAIN 0x00 | ||
38 | #define AS3935_AFE_MASK 0x3F | ||
39 | #define AS3935_AFE_GAIN_MAX 0x1F | ||
40 | #define AS3935_AFE_PWR_BIT BIT(0) | ||
41 | |||
42 | #define AS3935_INT 0x03 | ||
43 | #define AS3935_INT_MASK 0x07 | ||
44 | #define AS3935_EVENT_INT BIT(3) | ||
45 | #define AS3935_NOISE_INT BIT(1) | ||
46 | |||
47 | #define AS3935_DATA 0x07 | ||
48 | #define AS3935_DATA_MASK 0x3F | ||
49 | |||
50 | #define AS3935_TUNE_CAP 0x08 | ||
51 | #define AS3935_CALIBRATE 0x3D | ||
52 | |||
53 | #define AS3935_WRITE_DATA BIT(15) | ||
54 | #define AS3935_READ_DATA BIT(14) | ||
55 | #define AS3935_ADDRESS(x) ((x) << 8) | ||
56 | |||
57 | #define MAX_PF_CAP 120 | ||
58 | #define TUNE_CAP_DIV 8 | ||
59 | |||
60 | struct as3935_state { | ||
61 | struct spi_device *spi; | ||
62 | struct iio_trigger *trig; | ||
63 | struct mutex lock; | ||
64 | struct delayed_work work; | ||
65 | |||
66 | u32 tune_cap; | ||
67 | u8 buf[2] ____cacheline_aligned; | ||
68 | }; | ||
69 | |||
70 | static const struct iio_chan_spec as3935_channels[] = { | ||
71 | { | ||
72 | .type = IIO_PROXIMITY, | ||
73 | .info_mask_separate = | ||
74 | BIT(IIO_CHAN_INFO_RAW) | | ||
75 | BIT(IIO_CHAN_INFO_PROCESSED), | ||
76 | .scan_index = 0, | ||
77 | .scan_type = { | ||
78 | .sign = 'u', | ||
79 | .realbits = 6, | ||
80 | .storagebits = 8, | ||
81 | }, | ||
82 | }, | ||
83 | IIO_CHAN_SOFT_TIMESTAMP(1), | ||
84 | }; | ||
85 | |||
86 | static int as3935_read(struct as3935_state *st, unsigned int reg, int *val) | ||
87 | { | ||
88 | u8 cmd; | ||
89 | int ret; | ||
90 | |||
91 | cmd = (AS3935_READ_DATA | AS3935_ADDRESS(reg)) >> 8; | ||
92 | ret = spi_w8r8(st->spi, cmd); | ||
93 | if (ret < 0) | ||
94 | return ret; | ||
95 | *val = ret; | ||
96 | |||
97 | return 0; | ||
98 | }; | ||
99 | |||
100 | static int as3935_write(struct as3935_state *st, | ||
101 | unsigned int reg, | ||
102 | unsigned int val) | ||
103 | { | ||
104 | u8 *buf = st->buf; | ||
105 | |||
106 | buf[0] = (AS3935_WRITE_DATA | AS3935_ADDRESS(reg)) >> 8; | ||
107 | buf[1] = val; | ||
108 | |||
109 | return spi_write(st->spi, buf, 2); | ||
110 | }; | ||
111 | |||
112 | static ssize_t as3935_sensor_sensitivity_show(struct device *dev, | ||
113 | struct device_attribute *attr, | ||
114 | char *buf) | ||
115 | { | ||
116 | struct as3935_state *st = iio_priv(dev_to_iio_dev(dev)); | ||
117 | int val, ret; | ||
118 | |||
119 | ret = as3935_read(st, AS3935_AFE_GAIN, &val); | ||
120 | if (ret) | ||
121 | return ret; | ||
122 | val = (val & AS3935_AFE_MASK) >> 1; | ||
123 | |||
124 | return sprintf(buf, "%d\n", val); | ||
125 | }; | ||
126 | |||
127 | static ssize_t as3935_sensor_sensitivity_store(struct device *dev, | ||
128 | struct device_attribute *attr, | ||
129 | const char *buf, size_t len) | ||
130 | { | ||
131 | struct as3935_state *st = iio_priv(dev_to_iio_dev(dev)); | ||
132 | unsigned long val; | ||
133 | int ret; | ||
134 | |||
135 | ret = kstrtoul((const char *) buf, 10, &val); | ||
136 | if (ret) | ||
137 | return -EINVAL; | ||
138 | |||
139 | if (val > AS3935_AFE_GAIN_MAX) | ||
140 | return -EINVAL; | ||
141 | |||
142 | as3935_write(st, AS3935_AFE_GAIN, val << 1); | ||
143 | |||
144 | return len; | ||
145 | }; | ||
146 | |||
147 | static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR, | ||
148 | as3935_sensor_sensitivity_show, as3935_sensor_sensitivity_store, 0); | ||
149 | |||
150 | |||
151 | static struct attribute *as3935_attributes[] = { | ||
152 | &iio_dev_attr_sensor_sensitivity.dev_attr.attr, | ||
153 | NULL, | ||
154 | }; | ||
155 | |||
156 | static struct attribute_group as3935_attribute_group = { | ||
157 | .attrs = as3935_attributes, | ||
158 | }; | ||
159 | |||
160 | static int as3935_read_raw(struct iio_dev *indio_dev, | ||
161 | struct iio_chan_spec const *chan, | ||
162 | int *val, | ||
163 | int *val2, | ||
164 | long m) | ||
165 | { | ||
166 | struct as3935_state *st = iio_priv(indio_dev); | ||
167 | int ret; | ||
168 | |||
169 | |||
170 | switch (m) { | ||
171 | case IIO_CHAN_INFO_PROCESSED: | ||
172 | case IIO_CHAN_INFO_RAW: | ||
173 | *val2 = 0; | ||
174 | ret = as3935_read(st, AS3935_DATA, val); | ||
175 | if (ret) | ||
176 | return ret; | ||
177 | |||
178 | if (m == IIO_CHAN_INFO_RAW) | ||
179 | return IIO_VAL_INT; | ||
180 | |||
181 | /* storm out of range */ | ||
182 | if (*val == AS3935_DATA_MASK) | ||
183 | return -EINVAL; | ||
184 | *val *= 1000; | ||
185 | break; | ||
186 | default: | ||
187 | return -EINVAL; | ||
188 | } | ||
189 | |||
190 | return IIO_VAL_INT; | ||
191 | } | ||
192 | |||
193 | static const struct iio_info as3935_info = { | ||
194 | .driver_module = THIS_MODULE, | ||
195 | .attrs = &as3935_attribute_group, | ||
196 | .read_raw = &as3935_read_raw, | ||
197 | }; | ||
198 | |||
199 | static irqreturn_t as3935_trigger_handler(int irq, void *private) | ||
200 | { | ||
201 | struct iio_poll_func *pf = private; | ||
202 | struct iio_dev *indio_dev = pf->indio_dev; | ||
203 | struct as3935_state *st = iio_priv(indio_dev); | ||
204 | int val, ret; | ||
205 | |||
206 | ret = as3935_read(st, AS3935_DATA, &val); | ||
207 | if (ret) | ||
208 | goto err_read; | ||
209 | val &= AS3935_DATA_MASK; | ||
210 | val *= 1000; | ||
211 | |||
212 | iio_push_to_buffers_with_timestamp(indio_dev, &val, pf->timestamp); | ||
213 | err_read: | ||
214 | iio_trigger_notify_done(indio_dev->trig); | ||
215 | |||
216 | return IRQ_HANDLED; | ||
217 | }; | ||
218 | |||
219 | static const struct iio_trigger_ops iio_interrupt_trigger_ops = { | ||
220 | .owner = THIS_MODULE, | ||
221 | }; | ||
222 | |||
223 | static void as3935_event_work(struct work_struct *work) | ||
224 | { | ||
225 | struct as3935_state *st; | ||
226 | int val; | ||
227 | |||
228 | st = container_of(work, struct as3935_state, work.work); | ||
229 | |||
230 | as3935_read(st, AS3935_INT, &val); | ||
231 | val &= AS3935_INT_MASK; | ||
232 | |||
233 | switch (val) { | ||
234 | case AS3935_EVENT_INT: | ||
235 | iio_trigger_poll(st->trig, iio_get_time_ns()); | ||
236 | break; | ||
237 | case AS3935_NOISE_INT: | ||
238 | dev_warn(&st->spi->dev, "noise level is too high"); | ||
239 | break; | ||
240 | } | ||
241 | }; | ||
242 | |||
243 | static irqreturn_t as3935_interrupt_handler(int irq, void *private) | ||
244 | { | ||
245 | struct iio_dev *indio_dev = private; | ||
246 | struct as3935_state *st = iio_priv(indio_dev); | ||
247 | |||
248 | /* | ||
249 | * Delay work for >2 milliseconds after an interrupt to allow | ||
250 | * estimated distance to recalculated. | ||
251 | */ | ||
252 | |||
253 | schedule_delayed_work(&st->work, msecs_to_jiffies(3)); | ||
254 | |||
255 | return IRQ_HANDLED; | ||
256 | } | ||
257 | |||
258 | static void calibrate_as3935(struct as3935_state *st) | ||
259 | { | ||
260 | mutex_lock(&st->lock); | ||
261 | |||
262 | /* mask disturber interrupt bit */ | ||
263 | as3935_write(st, AS3935_INT, BIT(5)); | ||
264 | |||
265 | as3935_write(st, AS3935_CALIBRATE, 0x96); | ||
266 | as3935_write(st, AS3935_TUNE_CAP, | ||
267 | BIT(5) | (st->tune_cap / TUNE_CAP_DIV)); | ||
268 | |||
269 | mdelay(2); | ||
270 | as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV)); | ||
271 | |||
272 | mutex_unlock(&st->lock); | ||
273 | } | ||
274 | |||
275 | #ifdef CONFIG_PM_SLEEP | ||
276 | static int as3935_suspend(struct spi_device *spi, pm_message_t msg) | ||
277 | { | ||
278 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
279 | struct as3935_state *st = iio_priv(indio_dev); | ||
280 | int val, ret; | ||
281 | |||
282 | mutex_lock(&st->lock); | ||
283 | ret = as3935_read(st, AS3935_AFE_GAIN, &val); | ||
284 | if (ret) | ||
285 | goto err_suspend; | ||
286 | val |= AS3935_AFE_PWR_BIT; | ||
287 | |||
288 | ret = as3935_write(st, AS3935_AFE_GAIN, val); | ||
289 | |||
290 | err_suspend: | ||
291 | mutex_unlock(&st->lock); | ||
292 | |||
293 | return ret; | ||
294 | } | ||
295 | |||
296 | static int as3935_resume(struct spi_device *spi) | ||
297 | { | ||
298 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
299 | struct as3935_state *st = iio_priv(indio_dev); | ||
300 | int val, ret; | ||
301 | |||
302 | mutex_lock(&st->lock); | ||
303 | ret = as3935_read(st, AS3935_AFE_GAIN, &val); | ||
304 | if (ret) | ||
305 | goto err_resume; | ||
306 | val &= ~AS3935_AFE_PWR_BIT; | ||
307 | ret = as3935_write(st, AS3935_AFE_GAIN, val); | ||
308 | |||
309 | err_resume: | ||
310 | mutex_unlock(&st->lock); | ||
311 | |||
312 | return ret; | ||
313 | } | ||
314 | #else | ||
315 | #define as3935_suspend NULL | ||
316 | #define as3935_resume NULL | ||
317 | #endif | ||
318 | |||
319 | static int as3935_probe(struct spi_device *spi) | ||
320 | { | ||
321 | struct iio_dev *indio_dev; | ||
322 | struct iio_trigger *trig; | ||
323 | struct as3935_state *st; | ||
324 | struct device_node *np = spi->dev.of_node; | ||
325 | int ret; | ||
326 | |||
327 | /* Be sure lightning event interrupt is specified */ | ||
328 | if (!spi->irq) { | ||
329 | dev_err(&spi->dev, "unable to get event interrupt\n"); | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | |||
333 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(st)); | ||
334 | if (!indio_dev) | ||
335 | return -ENOMEM; | ||
336 | |||
337 | st = iio_priv(indio_dev); | ||
338 | st->spi = spi; | ||
339 | st->tune_cap = 0; | ||
340 | |||
341 | spi_set_drvdata(spi, indio_dev); | ||
342 | mutex_init(&st->lock); | ||
343 | INIT_DELAYED_WORK(&st->work, as3935_event_work); | ||
344 | |||
345 | ret = of_property_read_u32(np, | ||
346 | "ams,tuning-capacitor-pf", &st->tune_cap); | ||
347 | if (ret) { | ||
348 | st->tune_cap = 0; | ||
349 | dev_warn(&spi->dev, | ||
350 | "no tuning-capacitor-pf set, defaulting to %d", | ||
351 | st->tune_cap); | ||
352 | } | ||
353 | |||
354 | if (st->tune_cap > MAX_PF_CAP) { | ||
355 | dev_err(&spi->dev, | ||
356 | "wrong tuning-capacitor-pf setting of %d\n", | ||
357 | st->tune_cap); | ||
358 | return -EINVAL; | ||
359 | } | ||
360 | |||
361 | indio_dev->dev.parent = &spi->dev; | ||
362 | indio_dev->name = spi_get_device_id(spi)->name; | ||
363 | indio_dev->channels = as3935_channels; | ||
364 | indio_dev->num_channels = ARRAY_SIZE(as3935_channels); | ||
365 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
366 | indio_dev->info = &as3935_info; | ||
367 | |||
368 | trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", | ||
369 | indio_dev->name, indio_dev->id); | ||
370 | |||
371 | if (!trig) | ||
372 | return -ENOMEM; | ||
373 | |||
374 | st->trig = trig; | ||
375 | trig->dev.parent = indio_dev->dev.parent; | ||
376 | iio_trigger_set_drvdata(trig, indio_dev); | ||
377 | trig->ops = &iio_interrupt_trigger_ops; | ||
378 | |||
379 | ret = iio_trigger_register(trig); | ||
380 | if (ret) { | ||
381 | dev_err(&spi->dev, "failed to register trigger\n"); | ||
382 | return ret; | ||
383 | } | ||
384 | |||
385 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | ||
386 | &as3935_trigger_handler, NULL); | ||
387 | |||
388 | if (ret) { | ||
389 | dev_err(&spi->dev, "cannot setup iio trigger\n"); | ||
390 | goto unregister_trigger; | ||
391 | } | ||
392 | |||
393 | calibrate_as3935(st); | ||
394 | |||
395 | ret = devm_request_irq(&spi->dev, spi->irq, | ||
396 | &as3935_interrupt_handler, | ||
397 | IRQF_TRIGGER_RISING, | ||
398 | dev_name(&spi->dev), | ||
399 | indio_dev); | ||
400 | |||
401 | if (ret) { | ||
402 | dev_err(&spi->dev, "unable to request irq\n"); | ||
403 | goto unregister_buffer; | ||
404 | } | ||
405 | |||
406 | ret = iio_device_register(indio_dev); | ||
407 | if (ret < 0) { | ||
408 | dev_err(&spi->dev, "unable to register device\n"); | ||
409 | goto unregister_buffer; | ||
410 | } | ||
411 | return 0; | ||
412 | |||
413 | unregister_buffer: | ||
414 | iio_triggered_buffer_cleanup(indio_dev); | ||
415 | |||
416 | unregister_trigger: | ||
417 | iio_trigger_unregister(st->trig); | ||
418 | |||
419 | return ret; | ||
420 | }; | ||
421 | |||
422 | static int as3935_remove(struct spi_device *spi) | ||
423 | { | ||
424 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
425 | struct as3935_state *st = iio_priv(indio_dev); | ||
426 | |||
427 | iio_device_unregister(indio_dev); | ||
428 | iio_triggered_buffer_cleanup(indio_dev); | ||
429 | iio_trigger_unregister(st->trig); | ||
430 | |||
431 | return 0; | ||
432 | }; | ||
433 | |||
434 | static const struct spi_device_id as3935_id[] = { | ||
435 | {"as3935", 0}, | ||
436 | {}, | ||
437 | }; | ||
438 | MODULE_DEVICE_TABLE(spi, as3935_id); | ||
439 | |||
440 | static struct spi_driver as3935_driver = { | ||
441 | .driver = { | ||
442 | .name = "as3935", | ||
443 | .owner = THIS_MODULE, | ||
444 | }, | ||
445 | .probe = as3935_probe, | ||
446 | .remove = as3935_remove, | ||
447 | .id_table = as3935_id, | ||
448 | .suspend = as3935_suspend, | ||
449 | .resume = as3935_resume, | ||
450 | }; | ||
451 | module_spi_driver(as3935_driver); | ||
452 | |||
453 | MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); | ||
454 | MODULE_DESCRIPTION("AS3935 lightning sensor"); | ||
455 | MODULE_LICENSE("GPL"); | ||
456 | MODULE_ALIAS("spi:as3935"); | ||
diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig index 372f8fb3085f..21feaa4661b4 100644 --- a/drivers/iio/temperature/Kconfig +++ b/drivers/iio/temperature/Kconfig | |||
@@ -3,6 +3,16 @@ | |||
3 | # | 3 | # |
4 | menu "Temperature sensors" | 4 | menu "Temperature sensors" |
5 | 5 | ||
6 | config MLX90614 | ||
7 | tristate "MLX90614 contact-less infrared sensor" | ||
8 | depends on I2C | ||
9 | help | ||
10 | If you say yes here you get support for the Melexis | ||
11 | MLX90614 contact-less infrared sensor connected with I2C. | ||
12 | |||
13 | This driver can also be built as a module. If so, the module will | ||
14 | be called mlx90614. | ||
15 | |||
6 | config TMP006 | 16 | config TMP006 |
7 | tristate "TMP006 infrared thermopile sensor" | 17 | tristate "TMP006 infrared thermopile sensor" |
8 | depends on I2C | 18 | depends on I2C |
diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile index 24d7b602db3e..40710a81158e 100644 --- a/drivers/iio/temperature/Makefile +++ b/drivers/iio/temperature/Makefile | |||
@@ -2,4 +2,5 @@ | |||
2 | # Makefile for industrial I/O temperature drivers | 2 | # Makefile for industrial I/O temperature drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_MLX90614) += mlx90614.o | ||
5 | obj-$(CONFIG_TMP006) += tmp006.o | 6 | obj-$(CONFIG_TMP006) += tmp006.o |
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c new file mode 100644 index 000000000000..c8b6ac8b2d69 --- /dev/null +++ b/drivers/iio/temperature/mlx90614.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * mlx90614.c - Support for Melexis MLX90614 contactless IR temperature sensor | ||
3 | * | ||
4 | * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net> | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of version 2 of | ||
7 | * the GNU General Public License. See the file COPYING in the main | ||
8 | * directory of this archive for more details. | ||
9 | * | ||
10 | * Driver for the Melexis MLX90614 I2C 16-bit IR thermopile sensor | ||
11 | * | ||
12 | * (7-bit I2C slave address 0x5a, 100KHz bus speed only!) | ||
13 | * | ||
14 | * TODO: sleep mode, configuration EEPROM | ||
15 | */ | ||
16 | |||
17 | #include <linux/err.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include <linux/iio/iio.h> | ||
22 | |||
23 | #define MLX90614_OP_RAM 0x00 | ||
24 | |||
25 | /* RAM offsets with 16-bit data, MSB first */ | ||
26 | #define MLX90614_TA 0x06 /* ambient temperature */ | ||
27 | #define MLX90614_TOBJ1 0x07 /* object temperature */ | ||
28 | |||
29 | struct mlx90614_data { | ||
30 | struct i2c_client *client; | ||
31 | }; | ||
32 | |||
33 | static int mlx90614_read_raw(struct iio_dev *indio_dev, | ||
34 | struct iio_chan_spec const *channel, int *val, | ||
35 | int *val2, long mask) | ||
36 | { | ||
37 | struct mlx90614_data *data = iio_priv(indio_dev); | ||
38 | s32 ret; | ||
39 | |||
40 | switch (mask) { | ||
41 | case IIO_CHAN_INFO_RAW: /* 0.02K / LSB */ | ||
42 | switch (channel->channel2) { | ||
43 | case IIO_MOD_TEMP_AMBIENT: | ||
44 | ret = i2c_smbus_read_word_data(data->client, | ||
45 | MLX90614_OP_RAM | MLX90614_TA); | ||
46 | if (ret < 0) | ||
47 | return ret; | ||
48 | break; | ||
49 | case IIO_MOD_TEMP_OBJECT: | ||
50 | ret = i2c_smbus_read_word_data(data->client, | ||
51 | MLX90614_OP_RAM | MLX90614_TOBJ1); | ||
52 | if (ret < 0) | ||
53 | return ret; | ||
54 | break; | ||
55 | default: | ||
56 | return -EINVAL; | ||
57 | } | ||
58 | *val = ret; | ||
59 | return IIO_VAL_INT; | ||
60 | case IIO_CHAN_INFO_OFFSET: | ||
61 | *val = 13657; | ||
62 | *val2 = 500000; | ||
63 | return IIO_VAL_INT_PLUS_MICRO; | ||
64 | case IIO_CHAN_INFO_SCALE: | ||
65 | *val = 20; | ||
66 | return IIO_VAL_INT; | ||
67 | default: | ||
68 | return -EINVAL; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | static const struct iio_chan_spec mlx90614_channels[] = { | ||
73 | { | ||
74 | .type = IIO_TEMP, | ||
75 | .modified = 1, | ||
76 | .channel2 = IIO_MOD_TEMP_AMBIENT, | ||
77 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
78 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | ||
79 | BIT(IIO_CHAN_INFO_SCALE), | ||
80 | }, | ||
81 | { | ||
82 | .type = IIO_TEMP, | ||
83 | .modified = 1, | ||
84 | .channel2 = IIO_MOD_TEMP_OBJECT, | ||
85 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
86 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | ||
87 | BIT(IIO_CHAN_INFO_SCALE), | ||
88 | }, | ||
89 | }; | ||
90 | |||
91 | static const struct iio_info mlx90614_info = { | ||
92 | .read_raw = mlx90614_read_raw, | ||
93 | .driver_module = THIS_MODULE, | ||
94 | }; | ||
95 | |||
96 | static int mlx90614_probe(struct i2c_client *client, | ||
97 | const struct i2c_device_id *id) | ||
98 | { | ||
99 | struct iio_dev *indio_dev; | ||
100 | struct mlx90614_data *data; | ||
101 | |||
102 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) | ||
103 | return -ENODEV; | ||
104 | |||
105 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
106 | if (!indio_dev) | ||
107 | return -ENOMEM; | ||
108 | |||
109 | data = iio_priv(indio_dev); | ||
110 | i2c_set_clientdata(client, indio_dev); | ||
111 | data->client = client; | ||
112 | |||
113 | indio_dev->dev.parent = &client->dev; | ||
114 | indio_dev->name = id->name; | ||
115 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
116 | indio_dev->info = &mlx90614_info; | ||
117 | |||
118 | indio_dev->channels = mlx90614_channels; | ||
119 | indio_dev->num_channels = ARRAY_SIZE(mlx90614_channels); | ||
120 | |||
121 | return iio_device_register(indio_dev); | ||
122 | } | ||
123 | |||
124 | static int mlx90614_remove(struct i2c_client *client) | ||
125 | { | ||
126 | iio_device_unregister(i2c_get_clientdata(client)); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static const struct i2c_device_id mlx90614_id[] = { | ||
132 | { "mlx90614", 0 }, | ||
133 | { } | ||
134 | }; | ||
135 | MODULE_DEVICE_TABLE(i2c, mlx90614_id); | ||
136 | |||
137 | static struct i2c_driver mlx90614_driver = { | ||
138 | .driver = { | ||
139 | .name = "mlx90614", | ||
140 | .owner = THIS_MODULE, | ||
141 | }, | ||
142 | .probe = mlx90614_probe, | ||
143 | .remove = mlx90614_remove, | ||
144 | .id_table = mlx90614_id, | ||
145 | }; | ||
146 | module_i2c_driver(mlx90614_driver); | ||
147 | |||
148 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); | ||
149 | MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver"); | ||
150 | MODULE_LICENSE("GPL"); | ||