diff options
70 files changed, 2780 insertions, 866 deletions
diff --git a/Documentation/ABI/testing/configfs-iio b/Documentation/ABI/testing/configfs-iio index 2483756fccf5..aebda53ec0f7 100644 --- a/Documentation/ABI/testing/configfs-iio +++ b/Documentation/ABI/testing/configfs-iio | |||
@@ -19,3 +19,16 @@ KernelVersion: 4.4 | |||
19 | Description: | 19 | Description: |
20 | High resolution timers directory. Creating a directory here | 20 | High resolution timers directory. Creating a directory here |
21 | will result in creating a hrtimer trigger in the IIO subsystem. | 21 | will result in creating a hrtimer trigger in the IIO subsystem. |
22 | |||
23 | What: /config/iio/devices | ||
24 | Date: April 2016 | ||
25 | KernelVersion: 4.7 | ||
26 | Description: | ||
27 | Industrial IO software devices directory. | ||
28 | |||
29 | What: /config/iio/devices/dummy | ||
30 | Date: April 2016 | ||
31 | KernelVersion: 4.7 | ||
32 | Description: | ||
33 | Dummy IIO devices directory. Creating a directory here will result | ||
34 | in creating a dummy IIO device in the IIO subystem. | ||
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index df44998e7506..e7f590c6ef8e 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio | |||
@@ -1565,3 +1565,10 @@ Description: | |||
1565 | * X is in the plane of the propellers, perpendicular to Y axis, | 1565 | * X is in the plane of the propellers, perpendicular to Y axis, |
1566 | and positive towards the starboard side of the UAV ; | 1566 | and positive towards the starboard side of the UAV ; |
1567 | * Z is perpendicular to propellers plane and positive upwards. | 1567 | * Z is perpendicular to propellers plane and positive upwards. |
1568 | |||
1569 | What: /sys/bus/iio/devices/iio:deviceX/in_electricalconductivity_raw | ||
1570 | KernelVersion: 4.8 | ||
1571 | Contact: linux-iio@vger.kernel.org | ||
1572 | Description: | ||
1573 | Raw (unscaled no offset etc.) electric conductivity reading that | ||
1574 | can be processed to siemens per meter. | ||
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-health-afe440x b/Documentation/ABI/testing/sysfs-bus-iio-health-afe440x index 3740f253d406..6adba9058b22 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-health-afe440x +++ b/Documentation/ABI/testing/sysfs-bus-iio-health-afe440x | |||
@@ -1,54 +1,41 @@ | |||
1 | What: /sys/bus/iio/devices/iio:deviceX/tia_resistanceY | 1 | What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_raw |
2 | /sys/bus/iio/devices/iio:deviceX/tia_capacitanceY | 2 | Date: May 2016 |
3 | Date: December 2015 | ||
4 | KernelVersion: | ||
5 | Contact: Andrew F. Davis <afd@ti.com> | ||
6 | Description: | ||
7 | Get and set the resistance and the capacitance settings for the | ||
8 | Transimpedance Amplifier. Y is 1 for Rf1 and Cf1, Y is 2 for | ||
9 | Rf2 and Cf2 values. | ||
10 | |||
11 | What: /sys/bus/iio/devices/iio:deviceX/tia_separate_en | ||
12 | Date: December 2015 | ||
13 | KernelVersion: | ||
14 | Contact: Andrew F. Davis <afd@ti.com> | ||
15 | Description: | ||
16 | Enable or disable separate settings for the TransImpedance | ||
17 | Amplifier above, when disabled both values are set by the | ||
18 | first channel. | ||
19 | |||
20 | What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY_raw | ||
21 | /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY_ambient_raw | ||
22 | Date: December 2015 | ||
23 | KernelVersion: | 3 | KernelVersion: |
24 | Contact: Andrew F. Davis <afd@ti.com> | 4 | Contact: Andrew F. Davis <afd@ti.com> |
25 | Description: | 5 | Description: |
26 | Get measured values from the ADC for these stages. Y is the | 6 | Get measured values from the ADC for these stages. Y is the |
27 | specific LED number. The values are expressed in 24-bit twos | 7 | specific stage number corresponding to datasheet stage names |
28 | complement. | 8 | as follows: |
9 | 1 -> LED2 | ||
10 | 2 -> ALED2/LED3 | ||
11 | 3 -> LED1 | ||
12 | 4 -> ALED1/LED4 | ||
13 | Note that channels 5 and 6 represent LED2-ALED2 and LED1-ALED1 | ||
14 | respectively which simply helper channels containing the | ||
15 | calculated difference in the value of stage 1 - 2 and 3 - 4. | ||
16 | The values are expressed in 24-bit twos complement. | ||
29 | 17 | ||
30 | What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY-ledY_ambient_raw | 18 | What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_offset |
31 | Date: December 2015 | 19 | Date: May 2016 |
32 | KernelVersion: | 20 | KernelVersion: |
33 | Contact: Andrew F. Davis <afd@ti.com> | 21 | Contact: Andrew F. Davis <afd@ti.com> |
34 | Description: | 22 | Description: |
35 | Get differential values from the ADC for these stages. Y is the | 23 | Get and set the offset cancellation DAC setting for these |
36 | specific LED number. The values are expressed in 24-bit twos | 24 | stages. The values are expressed in 5-bit sign-magnitude. |
37 | complement for the specified LEDs. | ||
38 | 25 | ||
39 | What: /sys/bus/iio/devices/iio:deviceX/out_current_ledY_offset | 26 | What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_resistance |
40 | /sys/bus/iio/devices/iio:deviceX/out_current_ledY_ambient_offset | 27 | What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_capacitance |
41 | Date: December 2015 | 28 | Date: May 2016 |
42 | KernelVersion: | 29 | KernelVersion: |
43 | Contact: Andrew F. Davis <afd@ti.com> | 30 | Contact: Andrew F. Davis <afd@ti.com> |
44 | Description: | 31 | Description: |
45 | Get and set the offset cancellation DAC setting for these | 32 | Get and set the resistance and the capacitance settings for the |
46 | stages. The values are expressed in 5-bit sign-magnitude. | 33 | Transimpedance Amplifier during the associated stage. |
47 | 34 | ||
48 | What: /sys/bus/iio/devices/iio:deviceX/out_current_ledY_raw | 35 | What: /sys/bus/iio/devices/iio:deviceX/out_currentY_raw |
49 | Date: December 2015 | 36 | Date: May 2016 |
50 | KernelVersion: | 37 | KernelVersion: |
51 | Contact: Andrew F. Davis <afd@ti.com> | 38 | Contact: Andrew F. Davis <afd@ti.com> |
52 | Description: | 39 | Description: |
53 | Get and set the LED current for the specified LED. Y is the | 40 | Get and set the LED current for the specified LED active during |
54 | specific LED number. | 41 | this stage. Y is the specific stage number. |
diff --git a/Documentation/devicetree/bindings/iio/chemical/atlas,ec-sm.txt b/Documentation/devicetree/bindings/iio/chemical/atlas,ec-sm.txt new file mode 100644 index 000000000000..2962bd9a2b3d --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/atlas,ec-sm.txt | |||
@@ -0,0 +1,22 @@ | |||
1 | * Atlas Scientific EC-SM OEM sensor | ||
2 | |||
3 | http://www.atlas-scientific.com/_files/_datasheets/_oem/EC_oem_datasheet.pdf | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible: must be "atlas,ec-sm" | ||
8 | - reg: the I2C address of the sensor | ||
9 | - interrupt-parent: should be the phandle for the interrupt controller | ||
10 | - interrupts: the sole interrupt generated by the device | ||
11 | |||
12 | Refer to interrupt-controller/interrupts.txt for generic interrupt client | ||
13 | node bindings. | ||
14 | |||
15 | Example: | ||
16 | |||
17 | atlas@64 { | ||
18 | compatible = "atlas,ec-sm"; | ||
19 | reg = <0x64>; | ||
20 | interrupt-parent = <&gpio1>; | ||
21 | interrupts = <16 2>; | ||
22 | }; | ||
diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt index 5844cf72862d..e41fe340162b 100644 --- a/Documentation/devicetree/bindings/iio/st-sensors.txt +++ b/Documentation/devicetree/bindings/iio/st-sensors.txt | |||
@@ -64,3 +64,4 @@ Pressure sensors: | |||
64 | - st,lps001wp-press | 64 | - st,lps001wp-press |
65 | - st,lps25h-press | 65 | - st,lps25h-press |
66 | - st,lps331ap-press | 66 | - st,lps331ap-press |
67 | - st,lps22hb-press | ||
diff --git a/MAINTAINERS b/MAINTAINERS index ed42cb65a19b..24ccad7e5494 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5773,6 +5773,7 @@ R: Lars-Peter Clausen <lars@metafoo.de> | |||
5773 | R: Peter Meerwald-Stadler <pmeerw@pmeerw.net> | 5773 | R: Peter Meerwald-Stadler <pmeerw@pmeerw.net> |
5774 | L: linux-iio@vger.kernel.org | 5774 | L: linux-iio@vger.kernel.org |
5775 | S: Maintained | 5775 | S: Maintained |
5776 | F: Documentation/devicetree/bindings/iio/ | ||
5776 | F: drivers/iio/ | 5777 | F: drivers/iio/ |
5777 | F: drivers/staging/iio/ | 5778 | F: drivers/staging/iio/ |
5778 | F: include/linux/iio/ | 5779 | F: include/linux/iio/ |
@@ -10841,6 +10842,7 @@ STAGING - INDUSTRIAL IO | |||
10841 | M: Jonathan Cameron <jic23@kernel.org> | 10842 | M: Jonathan Cameron <jic23@kernel.org> |
10842 | L: linux-iio@vger.kernel.org | 10843 | L: linux-iio@vger.kernel.org |
10843 | S: Odd Fixes | 10844 | S: Odd Fixes |
10845 | F: Documentation/devicetree/bindings/staging/iio/ | ||
10844 | F: drivers/staging/iio/ | 10846 | F: drivers/staging/iio/ |
10845 | 10847 | ||
10846 | STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS | 10848 | STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS |
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 505e921f0b19..6743b18194fb 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig | |||
@@ -46,6 +46,14 @@ config IIO_CONSUMERS_PER_TRIGGER | |||
46 | This value controls the maximum number of consumers that a | 46 | This value controls the maximum number of consumers that a |
47 | given trigger may handle. Default is 2. | 47 | given trigger may handle. Default is 2. |
48 | 48 | ||
49 | config IIO_SW_DEVICE | ||
50 | tristate "Enable software IIO device support" | ||
51 | select IIO_CONFIGFS | ||
52 | help | ||
53 | Provides IIO core support for software devices. A software | ||
54 | device can be created via configfs or directly by a driver | ||
55 | using the API provided. | ||
56 | |||
49 | config IIO_SW_TRIGGER | 57 | config IIO_SW_TRIGGER |
50 | tristate "Enable software triggers support" | 58 | tristate "Enable software triggers support" |
51 | select IIO_CONFIGFS | 59 | select IIO_CONFIGFS |
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 20f649073462..87e4c4369e2f 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile | |||
@@ -8,6 +8,7 @@ industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o | |||
8 | industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o | 8 | industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o |
9 | 9 | ||
10 | obj-$(CONFIG_IIO_CONFIGFS) += industrialio-configfs.o | 10 | obj-$(CONFIG_IIO_CONFIGFS) += industrialio-configfs.o |
11 | obj-$(CONFIG_IIO_SW_DEVICE) += industrialio-sw-device.o | ||
11 | obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o | 12 | obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o |
12 | obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o | 13 | obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o |
13 | 14 | ||
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index e4a758cd7d35..31325870a9ef 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig | |||
@@ -17,6 +17,16 @@ config BMA180 | |||
17 | To compile this driver as a module, choose M here: the | 17 | To compile this driver as a module, choose M here: the |
18 | module will be called bma180. | 18 | module will be called bma180. |
19 | 19 | ||
20 | config BMA220 | ||
21 | tristate "Bosch BMA220 3-Axis Accelerometer Driver" | ||
22 | depends on SPI | ||
23 | help | ||
24 | Say yes here to add support for the Bosch BMA220 triaxial | ||
25 | acceleration sensor. | ||
26 | |||
27 | To compile this driver as a module, choose M here: the | ||
28 | module will be called bma220_spi. | ||
29 | |||
20 | config BMC150_ACCEL | 30 | config BMC150_ACCEL |
21 | tristate "Bosch BMC150 Accelerometer Driver" | 31 | tristate "Bosch BMC150 Accelerometer Driver" |
22 | select IIO_BUFFER | 32 | select IIO_BUFFER |
@@ -136,6 +146,16 @@ config MMA7455_SPI | |||
136 | To compile this driver as a module, choose M here: the module | 146 | To compile this driver as a module, choose M here: the module |
137 | will be called mma7455_spi. | 147 | will be called mma7455_spi. |
138 | 148 | ||
149 | config MMA7660 | ||
150 | tristate "Freescale MMA7660FC 3-Axis Accelerometer Driver" | ||
151 | depends on I2C | ||
152 | help | ||
153 | Say yes here to get support for the Freescale MMA7660FC 3-Axis | ||
154 | accelerometer. | ||
155 | |||
156 | Choosing M will build the driver as a module. If so, the module | ||
157 | will be called mma7660. | ||
158 | |||
139 | config MMA8452 | 159 | config MMA8452 |
140 | tristate "Freescale MMA8452Q and similar Accelerometers Driver" | 160 | tristate "Freescale MMA8452Q and similar Accelerometers Driver" |
141 | depends on I2C | 161 | depends on I2C |
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 71b6794de885..6cedbecca2ee 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/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_BMA180) += bma180.o | 6 | obj-$(CONFIG_BMA180) += bma180.o |
7 | obj-$(CONFIG_BMA220) += bma220_spi.o | ||
7 | obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o | 8 | obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o |
8 | obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o | 9 | obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o |
9 | obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o | 10 | obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o |
@@ -15,6 +16,8 @@ obj-$(CONFIG_MMA7455) += mma7455_core.o | |||
15 | obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o | 16 | obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o |
16 | obj-$(CONFIG_MMA7455_SPI) += mma7455_spi.o | 17 | obj-$(CONFIG_MMA7455_SPI) += mma7455_spi.o |
17 | 18 | ||
19 | obj-$(CONFIG_MMA7660) += mma7660.o | ||
20 | |||
18 | obj-$(CONFIG_MMA8452) += mma8452.o | 21 | obj-$(CONFIG_MMA8452) += mma8452.o |
19 | 22 | ||
20 | obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o | 23 | obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o |
diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c new file mode 100644 index 000000000000..1098d10df8e8 --- /dev/null +++ b/drivers/iio/accel/bma220_spi.c | |||
@@ -0,0 +1,338 @@ | |||
1 | /** | ||
2 | * BMA220 Digital triaxial acceleration sensor driver | ||
3 | * | ||
4 | * Copyright (c) 2016, Intel Corporation. | ||
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 | |||
11 | #include <linux/acpi.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/iio/buffer.h> | ||
15 | #include <linux/iio/iio.h> | ||
16 | #include <linux/iio/sysfs.h> | ||
17 | #include <linux/spi/spi.h> | ||
18 | #include <linux/iio/trigger_consumer.h> | ||
19 | #include <linux/iio/triggered_buffer.h> | ||
20 | |||
21 | #define BMA220_REG_ID 0x00 | ||
22 | #define BMA220_REG_ACCEL_X 0x02 | ||
23 | #define BMA220_REG_ACCEL_Y 0x03 | ||
24 | #define BMA220_REG_ACCEL_Z 0x04 | ||
25 | #define BMA220_REG_RANGE 0x11 | ||
26 | #define BMA220_REG_SUSPEND 0x18 | ||
27 | |||
28 | #define BMA220_CHIP_ID 0xDD | ||
29 | #define BMA220_READ_MASK 0x80 | ||
30 | #define BMA220_RANGE_MASK 0x03 | ||
31 | #define BMA220_DATA_SHIFT 2 | ||
32 | #define BMA220_SUSPEND_SLEEP 0xFF | ||
33 | #define BMA220_SUSPEND_WAKE 0x00 | ||
34 | |||
35 | #define BMA220_DEVICE_NAME "bma220" | ||
36 | #define BMA220_SCALE_AVAILABLE "0.623 1.248 2.491 4.983" | ||
37 | |||
38 | #define BMA220_ACCEL_CHANNEL(index, reg, axis) { \ | ||
39 | .type = IIO_ACCEL, \ | ||
40 | .address = reg, \ | ||
41 | .modified = 1, \ | ||
42 | .channel2 = IIO_MOD_##axis, \ | ||
43 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
44 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | ||
45 | .scan_index = index, \ | ||
46 | .scan_type = { \ | ||
47 | .sign = 's', \ | ||
48 | .realbits = 6, \ | ||
49 | .storagebits = 8, \ | ||
50 | .shift = BMA220_DATA_SHIFT, \ | ||
51 | .endianness = IIO_CPU, \ | ||
52 | }, \ | ||
53 | } | ||
54 | |||
55 | enum bma220_axis { | ||
56 | AXIS_X, | ||
57 | AXIS_Y, | ||
58 | AXIS_Z, | ||
59 | }; | ||
60 | |||
61 | static IIO_CONST_ATTR(in_accel_scale_available, BMA220_SCALE_AVAILABLE); | ||
62 | |||
63 | static struct attribute *bma220_attributes[] = { | ||
64 | &iio_const_attr_in_accel_scale_available.dev_attr.attr, | ||
65 | NULL, | ||
66 | }; | ||
67 | |||
68 | static const struct attribute_group bma220_attribute_group = { | ||
69 | .attrs = bma220_attributes, | ||
70 | }; | ||
71 | |||
72 | static const int bma220_scale_table[][4] = { | ||
73 | {0, 623000}, {1, 248000}, {2, 491000}, {4, 983000} | ||
74 | }; | ||
75 | |||
76 | struct bma220_data { | ||
77 | struct spi_device *spi_device; | ||
78 | struct mutex lock; | ||
79 | s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 8x8 timestamp */ | ||
80 | u8 tx_buf[2] ____cacheline_aligned; | ||
81 | }; | ||
82 | |||
83 | static const struct iio_chan_spec bma220_channels[] = { | ||
84 | BMA220_ACCEL_CHANNEL(0, BMA220_REG_ACCEL_X, X), | ||
85 | BMA220_ACCEL_CHANNEL(1, BMA220_REG_ACCEL_Y, Y), | ||
86 | BMA220_ACCEL_CHANNEL(2, BMA220_REG_ACCEL_Z, Z), | ||
87 | IIO_CHAN_SOFT_TIMESTAMP(3), | ||
88 | }; | ||
89 | |||
90 | static inline int bma220_read_reg(struct spi_device *spi, u8 reg) | ||
91 | { | ||
92 | return spi_w8r8(spi, reg | BMA220_READ_MASK); | ||
93 | } | ||
94 | |||
95 | static const unsigned long bma220_accel_scan_masks[] = { | ||
96 | BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), | ||
97 | 0 | ||
98 | }; | ||
99 | |||
100 | static irqreturn_t bma220_trigger_handler(int irq, void *p) | ||
101 | { | ||
102 | int ret; | ||
103 | struct iio_poll_func *pf = p; | ||
104 | struct iio_dev *indio_dev = pf->indio_dev; | ||
105 | struct bma220_data *data = iio_priv(indio_dev); | ||
106 | struct spi_device *spi = data->spi_device; | ||
107 | |||
108 | mutex_lock(&data->lock); | ||
109 | data->tx_buf[0] = BMA220_REG_ACCEL_X | BMA220_READ_MASK; | ||
110 | ret = spi_write_then_read(spi, data->tx_buf, 1, data->buffer, | ||
111 | ARRAY_SIZE(bma220_channels) - 1); | ||
112 | if (ret < 0) | ||
113 | goto err; | ||
114 | |||
115 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | ||
116 | pf->timestamp); | ||
117 | err: | ||
118 | mutex_unlock(&data->lock); | ||
119 | iio_trigger_notify_done(indio_dev->trig); | ||
120 | |||
121 | return IRQ_HANDLED; | ||
122 | } | ||
123 | |||
124 | static int bma220_read_raw(struct iio_dev *indio_dev, | ||
125 | struct iio_chan_spec const *chan, | ||
126 | int *val, int *val2, long mask) | ||
127 | { | ||
128 | int ret; | ||
129 | u8 range_idx; | ||
130 | struct bma220_data *data = iio_priv(indio_dev); | ||
131 | |||
132 | switch (mask) { | ||
133 | case IIO_CHAN_INFO_RAW: | ||
134 | ret = bma220_read_reg(data->spi_device, chan->address); | ||
135 | if (ret < 0) | ||
136 | return -EINVAL; | ||
137 | *val = sign_extend32(ret >> BMA220_DATA_SHIFT, 5); | ||
138 | return IIO_VAL_INT; | ||
139 | case IIO_CHAN_INFO_SCALE: | ||
140 | ret = bma220_read_reg(data->spi_device, BMA220_REG_RANGE); | ||
141 | if (ret < 0) | ||
142 | return ret; | ||
143 | range_idx = ret & BMA220_RANGE_MASK; | ||
144 | *val = bma220_scale_table[range_idx][0]; | ||
145 | *val2 = bma220_scale_table[range_idx][1]; | ||
146 | return IIO_VAL_INT_PLUS_MICRO; | ||
147 | } | ||
148 | |||
149 | return -EINVAL; | ||
150 | } | ||
151 | |||
152 | static int bma220_write_raw(struct iio_dev *indio_dev, | ||
153 | struct iio_chan_spec const *chan, | ||
154 | int val, int val2, long mask) | ||
155 | { | ||
156 | int i; | ||
157 | int ret; | ||
158 | int index = -1; | ||
159 | struct bma220_data *data = iio_priv(indio_dev); | ||
160 | |||
161 | switch (mask) { | ||
162 | case IIO_CHAN_INFO_SCALE: | ||
163 | for (i = 0; i < ARRAY_SIZE(bma220_scale_table); i++) | ||
164 | if (val == bma220_scale_table[i][0] && | ||
165 | val2 == bma220_scale_table[i][1]) { | ||
166 | index = i; | ||
167 | break; | ||
168 | } | ||
169 | if (index < 0) | ||
170 | return -EINVAL; | ||
171 | |||
172 | mutex_lock(&data->lock); | ||
173 | data->tx_buf[0] = BMA220_REG_RANGE; | ||
174 | data->tx_buf[1] = index; | ||
175 | ret = spi_write(data->spi_device, data->tx_buf, | ||
176 | sizeof(data->tx_buf)); | ||
177 | if (ret < 0) | ||
178 | dev_err(&data->spi_device->dev, | ||
179 | "failed to set measurement range\n"); | ||
180 | mutex_unlock(&data->lock); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | return -EINVAL; | ||
186 | } | ||
187 | |||
188 | static const struct iio_info bma220_info = { | ||
189 | .driver_module = THIS_MODULE, | ||
190 | .read_raw = bma220_read_raw, | ||
191 | .write_raw = bma220_write_raw, | ||
192 | .attrs = &bma220_attribute_group, | ||
193 | }; | ||
194 | |||
195 | static int bma220_init(struct spi_device *spi) | ||
196 | { | ||
197 | int ret; | ||
198 | |||
199 | ret = bma220_read_reg(spi, BMA220_REG_ID); | ||
200 | if (ret != BMA220_CHIP_ID) | ||
201 | return -ENODEV; | ||
202 | |||
203 | /* Make sure the chip is powered on */ | ||
204 | ret = bma220_read_reg(spi, BMA220_REG_SUSPEND); | ||
205 | if (ret < 0) | ||
206 | return ret; | ||
207 | else if (ret == BMA220_SUSPEND_WAKE) | ||
208 | return bma220_read_reg(spi, BMA220_REG_SUSPEND); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static int bma220_deinit(struct spi_device *spi) | ||
214 | { | ||
215 | int ret; | ||
216 | |||
217 | /* Make sure the chip is powered off */ | ||
218 | ret = bma220_read_reg(spi, BMA220_REG_SUSPEND); | ||
219 | if (ret < 0) | ||
220 | return ret; | ||
221 | else if (ret == BMA220_SUSPEND_SLEEP) | ||
222 | return bma220_read_reg(spi, BMA220_REG_SUSPEND); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int bma220_probe(struct spi_device *spi) | ||
228 | { | ||
229 | int ret; | ||
230 | struct iio_dev *indio_dev; | ||
231 | struct bma220_data *data; | ||
232 | |||
233 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data)); | ||
234 | if (!indio_dev) { | ||
235 | dev_err(&spi->dev, "iio allocation failed!\n"); | ||
236 | return -ENOMEM; | ||
237 | } | ||
238 | |||
239 | data = iio_priv(indio_dev); | ||
240 | data->spi_device = spi; | ||
241 | spi_set_drvdata(spi, indio_dev); | ||
242 | mutex_init(&data->lock); | ||
243 | |||
244 | indio_dev->dev.parent = &spi->dev; | ||
245 | indio_dev->info = &bma220_info; | ||
246 | indio_dev->name = BMA220_DEVICE_NAME; | ||
247 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
248 | indio_dev->channels = bma220_channels; | ||
249 | indio_dev->num_channels = ARRAY_SIZE(bma220_channels); | ||
250 | indio_dev->available_scan_masks = bma220_accel_scan_masks; | ||
251 | |||
252 | ret = bma220_init(data->spi_device); | ||
253 | if (ret < 0) | ||
254 | return ret; | ||
255 | |||
256 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | ||
257 | bma220_trigger_handler, NULL); | ||
258 | if (ret < 0) { | ||
259 | dev_err(&spi->dev, "iio triggered buffer setup failed\n"); | ||
260 | goto err_suspend; | ||
261 | } | ||
262 | |||
263 | ret = iio_device_register(indio_dev); | ||
264 | if (ret < 0) { | ||
265 | dev_err(&spi->dev, "iio_device_register failed\n"); | ||
266 | iio_triggered_buffer_cleanup(indio_dev); | ||
267 | goto err_suspend; | ||
268 | } | ||
269 | |||
270 | return 0; | ||
271 | |||
272 | err_suspend: | ||
273 | return bma220_deinit(spi); | ||
274 | } | ||
275 | |||
276 | static int bma220_remove(struct spi_device *spi) | ||
277 | { | ||
278 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
279 | |||
280 | iio_device_unregister(indio_dev); | ||
281 | iio_triggered_buffer_cleanup(indio_dev); | ||
282 | |||
283 | return bma220_deinit(spi); | ||
284 | } | ||
285 | |||
286 | #ifdef CONFIG_PM_SLEEP | ||
287 | static int bma220_suspend(struct device *dev) | ||
288 | { | ||
289 | struct bma220_data *data = | ||
290 | iio_priv(spi_get_drvdata(to_spi_device(dev))); | ||
291 | |||
292 | /* The chip can be suspended/woken up by a simple register read. */ | ||
293 | return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND); | ||
294 | } | ||
295 | |||
296 | static int bma220_resume(struct device *dev) | ||
297 | { | ||
298 | struct bma220_data *data = | ||
299 | iio_priv(spi_get_drvdata(to_spi_device(dev))); | ||
300 | |||
301 | return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND); | ||
302 | } | ||
303 | |||
304 | static SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume); | ||
305 | |||
306 | #define BMA220_PM_OPS (&bma220_pm_ops) | ||
307 | #else | ||
308 | #define BMA220_PM_OPS NULL | ||
309 | #endif | ||
310 | |||
311 | static const struct spi_device_id bma220_spi_id[] = { | ||
312 | {"bma220", 0}, | ||
313 | {} | ||
314 | }; | ||
315 | |||
316 | static const struct acpi_device_id bma220_acpi_id[] = { | ||
317 | {"BMA0220", 0}, | ||
318 | {} | ||
319 | }; | ||
320 | |||
321 | MODULE_DEVICE_TABLE(spi, bma220_spi_id); | ||
322 | |||
323 | static struct spi_driver bma220_driver = { | ||
324 | .driver = { | ||
325 | .name = "bma220_spi", | ||
326 | .pm = BMA220_PM_OPS, | ||
327 | .acpi_match_table = ACPI_PTR(bma220_acpi_id), | ||
328 | }, | ||
329 | .probe = bma220_probe, | ||
330 | .remove = bma220_remove, | ||
331 | .id_table = bma220_spi_id, | ||
332 | }; | ||
333 | |||
334 | module_spi_driver(bma220_driver); | ||
335 | |||
336 | MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>"); | ||
337 | MODULE_DESCRIPTION("BMA220 acceleration sensor driver"); | ||
338 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c new file mode 100644 index 000000000000..0acdee516973 --- /dev/null +++ b/drivers/iio/accel/mma7660.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /** | ||
2 | * Freescale MMA7660FC 3-Axis Accelerometer | ||
3 | * | ||
4 | * Copyright (c) 2016, Intel Corporation. | ||
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 | * IIO driver for Freescale MMA7660FC; 7-bit I2C address: 0x4c. | ||
11 | */ | ||
12 | |||
13 | #include <linux/acpi.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/iio/iio.h> | ||
17 | #include <linux/iio/sysfs.h> | ||
18 | |||
19 | #define MMA7660_DRIVER_NAME "mma7660" | ||
20 | |||
21 | #define MMA7660_REG_XOUT 0x00 | ||
22 | #define MMA7660_REG_YOUT 0x01 | ||
23 | #define MMA7660_REG_ZOUT 0x02 | ||
24 | #define MMA7660_REG_OUT_BIT_ALERT BIT(6) | ||
25 | |||
26 | #define MMA7660_REG_MODE 0x07 | ||
27 | #define MMA7660_REG_MODE_BIT_MODE BIT(0) | ||
28 | #define MMA7660_REG_MODE_BIT_TON BIT(2) | ||
29 | |||
30 | #define MMA7660_I2C_READ_RETRIES 5 | ||
31 | |||
32 | /* | ||
33 | * The accelerometer has one measurement range: | ||
34 | * | ||
35 | * -1.5g - +1.5g (6-bit, signed) | ||
36 | * | ||
37 | * scale = (1.5 + 1.5) * 9.81 / (2^6 - 1) = 0.467142857 | ||
38 | */ | ||
39 | |||
40 | #define MMA7660_SCALE_AVAIL "0.467142857" | ||
41 | |||
42 | const int mma7660_nscale = 467142857; | ||
43 | |||
44 | #define MMA7660_CHANNEL(reg, axis) { \ | ||
45 | .type = IIO_ACCEL, \ | ||
46 | .address = reg, \ | ||
47 | .modified = 1, \ | ||
48 | .channel2 = IIO_MOD_##axis, \ | ||
49 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
50 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | ||
51 | } | ||
52 | |||
53 | static const struct iio_chan_spec mma7660_channels[] = { | ||
54 | MMA7660_CHANNEL(MMA7660_REG_XOUT, X), | ||
55 | MMA7660_CHANNEL(MMA7660_REG_YOUT, Y), | ||
56 | MMA7660_CHANNEL(MMA7660_REG_ZOUT, Z), | ||
57 | }; | ||
58 | |||
59 | enum mma7660_mode { | ||
60 | MMA7660_MODE_STANDBY, | ||
61 | MMA7660_MODE_ACTIVE | ||
62 | }; | ||
63 | |||
64 | struct mma7660_data { | ||
65 | struct i2c_client *client; | ||
66 | struct mutex lock; | ||
67 | enum mma7660_mode mode; | ||
68 | }; | ||
69 | |||
70 | static IIO_CONST_ATTR(in_accel_scale_available, MMA7660_SCALE_AVAIL); | ||
71 | |||
72 | static struct attribute *mma7660_attributes[] = { | ||
73 | &iio_const_attr_in_accel_scale_available.dev_attr.attr, | ||
74 | NULL, | ||
75 | }; | ||
76 | |||
77 | static const struct attribute_group mma7660_attribute_group = { | ||
78 | .attrs = mma7660_attributes | ||
79 | }; | ||
80 | |||
81 | static int mma7660_set_mode(struct mma7660_data *data, | ||
82 | enum mma7660_mode mode) | ||
83 | { | ||
84 | int ret; | ||
85 | struct i2c_client *client = data->client; | ||
86 | |||
87 | if (mode == data->mode) | ||
88 | return 0; | ||
89 | |||
90 | ret = i2c_smbus_read_byte_data(client, MMA7660_REG_MODE); | ||
91 | if (ret < 0) { | ||
92 | dev_err(&client->dev, "failed to read sensor mode\n"); | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | if (mode == MMA7660_MODE_ACTIVE) { | ||
97 | ret &= ~MMA7660_REG_MODE_BIT_TON; | ||
98 | ret |= MMA7660_REG_MODE_BIT_MODE; | ||
99 | } else { | ||
100 | ret &= ~MMA7660_REG_MODE_BIT_TON; | ||
101 | ret &= ~MMA7660_REG_MODE_BIT_MODE; | ||
102 | } | ||
103 | |||
104 | ret = i2c_smbus_write_byte_data(client, MMA7660_REG_MODE, ret); | ||
105 | if (ret < 0) { | ||
106 | dev_err(&client->dev, "failed to change sensor mode\n"); | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | data->mode = mode; | ||
111 | |||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | static int mma7660_read_accel(struct mma7660_data *data, u8 address) | ||
116 | { | ||
117 | int ret, retries = MMA7660_I2C_READ_RETRIES; | ||
118 | struct i2c_client *client = data->client; | ||
119 | |||
120 | /* | ||
121 | * Read data. If the Alert bit is set, the register was read at | ||
122 | * the same time as the device was attempting to update the content. | ||
123 | * The solution is to read the register again. Do this only | ||
124 | * MMA7660_I2C_READ_RETRIES times to avoid spending too much time | ||
125 | * in the kernel. | ||
126 | */ | ||
127 | do { | ||
128 | ret = i2c_smbus_read_byte_data(client, address); | ||
129 | if (ret < 0) { | ||
130 | dev_err(&client->dev, "register read failed\n"); | ||
131 | return ret; | ||
132 | } | ||
133 | } while (retries-- > 0 && ret & MMA7660_REG_OUT_BIT_ALERT); | ||
134 | |||
135 | if (ret & MMA7660_REG_OUT_BIT_ALERT) { | ||
136 | dev_err(&client->dev, "all register read retries failed\n"); | ||
137 | return -ETIMEDOUT; | ||
138 | } | ||
139 | |||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | static int mma7660_read_raw(struct iio_dev *indio_dev, | ||
144 | struct iio_chan_spec const *chan, | ||
145 | int *val, int *val2, long mask) | ||
146 | { | ||
147 | struct mma7660_data *data = iio_priv(indio_dev); | ||
148 | int ret; | ||
149 | |||
150 | switch (mask) { | ||
151 | case IIO_CHAN_INFO_RAW: | ||
152 | mutex_lock(&data->lock); | ||
153 | ret = mma7660_read_accel(data, chan->address); | ||
154 | mutex_unlock(&data->lock); | ||
155 | if (ret < 0) | ||
156 | return ret; | ||
157 | *val = sign_extend32(ret, 5); | ||
158 | return IIO_VAL_INT; | ||
159 | case IIO_CHAN_INFO_SCALE: | ||
160 | *val = 0; | ||
161 | *val2 = mma7660_nscale; | ||
162 | return IIO_VAL_INT_PLUS_NANO; | ||
163 | default: | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
167 | return -EINVAL; | ||
168 | } | ||
169 | |||
170 | static const struct iio_info mma7660_info = { | ||
171 | .driver_module = THIS_MODULE, | ||
172 | .read_raw = mma7660_read_raw, | ||
173 | .attrs = &mma7660_attribute_group, | ||
174 | }; | ||
175 | |||
176 | static int mma7660_probe(struct i2c_client *client, | ||
177 | const struct i2c_device_id *id) | ||
178 | { | ||
179 | int ret; | ||
180 | struct iio_dev *indio_dev; | ||
181 | struct mma7660_data *data; | ||
182 | |||
183 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
184 | if (!indio_dev) { | ||
185 | dev_err(&client->dev, "iio allocation failed!\n"); | ||
186 | return -ENOMEM; | ||
187 | } | ||
188 | |||
189 | data = iio_priv(indio_dev); | ||
190 | data->client = client; | ||
191 | i2c_set_clientdata(client, indio_dev); | ||
192 | mutex_init(&data->lock); | ||
193 | data->mode = MMA7660_MODE_STANDBY; | ||
194 | |||
195 | indio_dev->dev.parent = &client->dev; | ||
196 | indio_dev->info = &mma7660_info; | ||
197 | indio_dev->name = MMA7660_DRIVER_NAME; | ||
198 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
199 | indio_dev->channels = mma7660_channels; | ||
200 | indio_dev->num_channels = ARRAY_SIZE(mma7660_channels); | ||
201 | |||
202 | ret = mma7660_set_mode(data, MMA7660_MODE_ACTIVE); | ||
203 | if (ret < 0) | ||
204 | return ret; | ||
205 | |||
206 | ret = iio_device_register(indio_dev); | ||
207 | if (ret < 0) { | ||
208 | dev_err(&client->dev, "device_register failed\n"); | ||
209 | mma7660_set_mode(data, MMA7660_MODE_STANDBY); | ||
210 | } | ||
211 | |||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | static int mma7660_remove(struct i2c_client *client) | ||
216 | { | ||
217 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
218 | |||
219 | iio_device_unregister(indio_dev); | ||
220 | |||
221 | return mma7660_set_mode(iio_priv(indio_dev), MMA7660_MODE_STANDBY); | ||
222 | } | ||
223 | |||
224 | #ifdef CONFIG_PM_SLEEP | ||
225 | static int mma7660_suspend(struct device *dev) | ||
226 | { | ||
227 | struct mma7660_data *data; | ||
228 | |||
229 | data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | ||
230 | |||
231 | return mma7660_set_mode(data, MMA7660_MODE_STANDBY); | ||
232 | } | ||
233 | |||
234 | static int mma7660_resume(struct device *dev) | ||
235 | { | ||
236 | struct mma7660_data *data; | ||
237 | |||
238 | data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | ||
239 | |||
240 | return mma7660_set_mode(data, MMA7660_MODE_ACTIVE); | ||
241 | } | ||
242 | |||
243 | static SIMPLE_DEV_PM_OPS(mma7660_pm_ops, mma7660_suspend, mma7660_resume); | ||
244 | |||
245 | #define MMA7660_PM_OPS (&mma7660_pm_ops) | ||
246 | #else | ||
247 | #define MMA7660_PM_OPS NULL | ||
248 | #endif | ||
249 | |||
250 | static const struct i2c_device_id mma7660_i2c_id[] = { | ||
251 | {"mma7660", 0}, | ||
252 | {} | ||
253 | }; | ||
254 | |||
255 | static const struct acpi_device_id mma7660_acpi_id[] = { | ||
256 | {"MMA7660", 0}, | ||
257 | {} | ||
258 | }; | ||
259 | |||
260 | MODULE_DEVICE_TABLE(acpi, mma7660_acpi_id); | ||
261 | |||
262 | static struct i2c_driver mma7660_driver = { | ||
263 | .driver = { | ||
264 | .name = "mma7660", | ||
265 | .pm = MMA7660_PM_OPS, | ||
266 | .acpi_match_table = ACPI_PTR(mma7660_acpi_id), | ||
267 | }, | ||
268 | .probe = mma7660_probe, | ||
269 | .remove = mma7660_remove, | ||
270 | .id_table = mma7660_i2c_id, | ||
271 | }; | ||
272 | |||
273 | module_i2c_driver(mma7660_driver); | ||
274 | |||
275 | MODULE_AUTHOR("Constantin Musca <constantin.musca@intel.com>"); | ||
276 | MODULE_DESCRIPTION("Freescale MMA7660FC 3-Axis Accelerometer driver"); | ||
277 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index e225d3c53bd5..458c82715427 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c | |||
@@ -76,6 +76,8 @@ | |||
76 | #define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */ | 76 | #define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */ |
77 | #define MMA8452_CTRL_REG2 0x2b | 77 | #define MMA8452_CTRL_REG2 0x2b |
78 | #define MMA8452_CTRL_REG2_RST BIT(6) | 78 | #define MMA8452_CTRL_REG2_RST BIT(6) |
79 | #define MMA8452_CTRL_REG2_MODS_SHIFT 3 | ||
80 | #define MMA8452_CTRL_REG2_MODS_MASK 0x1b | ||
79 | #define MMA8452_CTRL_REG4 0x2d | 81 | #define MMA8452_CTRL_REG4 0x2d |
80 | #define MMA8452_CTRL_REG5 0x2e | 82 | #define MMA8452_CTRL_REG5 0x2e |
81 | #define MMA8452_OFF_X 0x2f | 83 | #define MMA8452_OFF_X 0x2f |
@@ -257,20 +259,17 @@ static const int mma8452_samp_freq[8][2] = { | |||
257 | {6, 250000}, {1, 560000} | 259 | {6, 250000}, {1, 560000} |
258 | }; | 260 | }; |
259 | 261 | ||
260 | /* Datasheet table 35 (step time vs sample frequency) */ | 262 | /* Datasheet table: step time "Relationship with the ODR" (sample frequency) */ |
261 | static const int mma8452_transient_time_step_us[8] = { | 263 | static const int mma8452_transient_time_step_us[4][8] = { |
262 | 1250, | 264 | { 1250, 2500, 5000, 10000, 20000, 20000, 20000, 20000 }, /* normal */ |
263 | 2500, | 265 | { 1250, 2500, 5000, 10000, 20000, 80000, 80000, 80000 }, /* l p l n */ |
264 | 5000, | 266 | { 1250, 2500, 2500, 2500, 2500, 2500, 2500, 2500 }, /* high res*/ |
265 | 10000, | 267 | { 1250, 2500, 5000, 10000, 20000, 80000, 160000, 160000 } /* l p */ |
266 | 20000, | ||
267 | 20000, | ||
268 | 20000, | ||
269 | 20000 | ||
270 | }; | 268 | }; |
271 | 269 | ||
272 | /* Datasheet table 18 (normal mode) */ | 270 | /* Datasheet table "High-Pass Filter Cutoff Options" */ |
273 | static const int mma8452_hp_filter_cutoff[8][4][2] = { | 271 | static const int mma8452_hp_filter_cutoff[4][8][4][2] = { |
272 | { /* normal */ | ||
274 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, /* 800 Hz sample */ | 273 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, /* 800 Hz sample */ |
275 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, /* 400 Hz sample */ | 274 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, /* 400 Hz sample */ |
276 | { {8, 0}, {4, 0}, {2, 0}, {1, 0} }, /* 200 Hz sample */ | 275 | { {8, 0}, {4, 0}, {2, 0}, {1, 0} }, /* 200 Hz sample */ |
@@ -279,8 +278,61 @@ static const int mma8452_hp_filter_cutoff[8][4][2] = { | |||
279 | { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, /* 12.5 Hz sample */ | 278 | { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, /* 12.5 Hz sample */ |
280 | { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, /* 6.25 Hz sample */ | 279 | { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, /* 6.25 Hz sample */ |
281 | { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} } /* 1.56 Hz sample */ | 280 | { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} } /* 1.56 Hz sample */ |
281 | }, | ||
282 | { /* low noise low power */ | ||
283 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, | ||
284 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, | ||
285 | { {8, 0}, {4, 0}, {2, 0}, {1, 0} }, | ||
286 | { {4, 0}, {2, 0}, {1, 0}, {0, 500000} }, | ||
287 | { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, | ||
288 | { {0, 500000}, {0, 250000}, {0, 125000}, {0, 063000} }, | ||
289 | { {0, 500000}, {0, 250000}, {0, 125000}, {0, 063000} }, | ||
290 | { {0, 500000}, {0, 250000}, {0, 125000}, {0, 063000} } | ||
291 | }, | ||
292 | { /* high resolution */ | ||
293 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, | ||
294 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, | ||
295 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, | ||
296 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, | ||
297 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, | ||
298 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, | ||
299 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, | ||
300 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} } | ||
301 | }, | ||
302 | { /* low power */ | ||
303 | { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, | ||
304 | { {8, 0}, {4, 0}, {2, 0}, {1, 0} }, | ||
305 | { {4, 0}, {2, 0}, {1, 0}, {0, 500000} }, | ||
306 | { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, | ||
307 | { {1, 0}, {0, 500000}, {0, 250000}, {0, 125000} }, | ||
308 | { {0, 250000}, {0, 125000}, {0, 063000}, {0, 031000} }, | ||
309 | { {0, 250000}, {0, 125000}, {0, 063000}, {0, 031000} }, | ||
310 | { {0, 250000}, {0, 125000}, {0, 063000}, {0, 031000} } | ||
311 | } | ||
282 | }; | 312 | }; |
283 | 313 | ||
314 | /* Datasheet table "MODS Oversampling modes averaging values at each ODR" */ | ||
315 | static const u16 mma8452_os_ratio[4][8] = { | ||
316 | /* 800 Hz, 400 Hz, ... , 1.56 Hz */ | ||
317 | { 2, 4, 4, 4, 4, 16, 32, 128 }, /* normal */ | ||
318 | { 2, 4, 4, 4, 4, 4, 8, 32 }, /* low power low noise */ | ||
319 | { 2, 4, 8, 16, 32, 128, 256, 1024 }, /* high resolution */ | ||
320 | { 2, 2, 2, 2, 2, 2, 4, 16 } /* low power */ | ||
321 | }; | ||
322 | |||
323 | static int mma8452_get_power_mode(struct mma8452_data *data) | ||
324 | { | ||
325 | int reg; | ||
326 | |||
327 | reg = i2c_smbus_read_byte_data(data->client, | ||
328 | MMA8452_CTRL_REG2); | ||
329 | if (reg < 0) | ||
330 | return reg; | ||
331 | |||
332 | return ((reg & MMA8452_CTRL_REG2_MODS_MASK) >> | ||
333 | MMA8452_CTRL_REG2_MODS_SHIFT); | ||
334 | } | ||
335 | |||
284 | static ssize_t mma8452_show_samp_freq_avail(struct device *dev, | 336 | static ssize_t mma8452_show_samp_freq_avail(struct device *dev, |
285 | struct device_attribute *attr, | 337 | struct device_attribute *attr, |
286 | char *buf) | 338 | char *buf) |
@@ -306,10 +358,39 @@ static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev, | |||
306 | { | 358 | { |
307 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 359 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
308 | struct mma8452_data *data = iio_priv(indio_dev); | 360 | struct mma8452_data *data = iio_priv(indio_dev); |
361 | int i, j; | ||
362 | |||
363 | i = mma8452_get_odr_index(data); | ||
364 | j = mma8452_get_power_mode(data); | ||
365 | if (j < 0) | ||
366 | return j; | ||
367 | |||
368 | return mma8452_show_int_plus_micros(buf, mma8452_hp_filter_cutoff[j][i], | ||
369 | ARRAY_SIZE(mma8452_hp_filter_cutoff[0][0])); | ||
370 | } | ||
371 | |||
372 | static ssize_t mma8452_show_os_ratio_avail(struct device *dev, | ||
373 | struct device_attribute *attr, | ||
374 | char *buf) | ||
375 | { | ||
376 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
377 | struct mma8452_data *data = iio_priv(indio_dev); | ||
309 | int i = mma8452_get_odr_index(data); | 378 | int i = mma8452_get_odr_index(data); |
379 | int j; | ||
380 | u16 val = 0; | ||
381 | size_t len = 0; | ||
382 | |||
383 | for (j = 0; j < ARRAY_SIZE(mma8452_os_ratio); j++) { | ||
384 | if (val == mma8452_os_ratio[j][i]) | ||
385 | continue; | ||
386 | |||
387 | val = mma8452_os_ratio[j][i]; | ||
388 | |||
389 | len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", val); | ||
390 | } | ||
391 | buf[len - 1] = '\n'; | ||
310 | 392 | ||
311 | return mma8452_show_int_plus_micros(buf, mma8452_hp_filter_cutoff[i], | 393 | return len; |
312 | ARRAY_SIZE(mma8452_hp_filter_cutoff[0])); | ||
313 | } | 394 | } |
314 | 395 | ||
315 | static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail); | 396 | static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail); |
@@ -317,6 +398,8 @@ static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO, | |||
317 | mma8452_show_scale_avail, NULL, 0); | 398 | mma8452_show_scale_avail, NULL, 0); |
318 | static IIO_DEVICE_ATTR(in_accel_filter_high_pass_3db_frequency_available, | 399 | static IIO_DEVICE_ATTR(in_accel_filter_high_pass_3db_frequency_available, |
319 | S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0); | 400 | S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0); |
401 | static IIO_DEVICE_ATTR(in_accel_oversampling_ratio_available, S_IRUGO, | ||
402 | mma8452_show_os_ratio_avail, NULL, 0); | ||
320 | 403 | ||
321 | static int mma8452_get_samp_freq_index(struct mma8452_data *data, | 404 | static int mma8452_get_samp_freq_index(struct mma8452_data *data, |
322 | int val, int val2) | 405 | int val, int val2) |
@@ -335,24 +418,33 @@ static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2) | |||
335 | static int mma8452_get_hp_filter_index(struct mma8452_data *data, | 418 | static int mma8452_get_hp_filter_index(struct mma8452_data *data, |
336 | int val, int val2) | 419 | int val, int val2) |
337 | { | 420 | { |
338 | int i = mma8452_get_odr_index(data); | 421 | int i, j; |
422 | |||
423 | i = mma8452_get_odr_index(data); | ||
424 | j = mma8452_get_power_mode(data); | ||
425 | if (j < 0) | ||
426 | return j; | ||
339 | 427 | ||
340 | return mma8452_get_int_plus_micros_index(mma8452_hp_filter_cutoff[i], | 428 | return mma8452_get_int_plus_micros_index(mma8452_hp_filter_cutoff[j][i], |
341 | ARRAY_SIZE(mma8452_hp_filter_cutoff[0]), val, val2); | 429 | ARRAY_SIZE(mma8452_hp_filter_cutoff[0][0]), val, val2); |
342 | } | 430 | } |
343 | 431 | ||
344 | static int mma8452_read_hp_filter(struct mma8452_data *data, int *hz, int *uHz) | 432 | static int mma8452_read_hp_filter(struct mma8452_data *data, int *hz, int *uHz) |
345 | { | 433 | { |
346 | int i, ret; | 434 | int j, i, ret; |
347 | 435 | ||
348 | ret = i2c_smbus_read_byte_data(data->client, MMA8452_HP_FILTER_CUTOFF); | 436 | ret = i2c_smbus_read_byte_data(data->client, MMA8452_HP_FILTER_CUTOFF); |
349 | if (ret < 0) | 437 | if (ret < 0) |
350 | return ret; | 438 | return ret; |
351 | 439 | ||
352 | i = mma8452_get_odr_index(data); | 440 | i = mma8452_get_odr_index(data); |
441 | j = mma8452_get_power_mode(data); | ||
442 | if (j < 0) | ||
443 | return j; | ||
444 | |||
353 | ret &= MMA8452_HP_FILTER_CUTOFF_SEL_MASK; | 445 | ret &= MMA8452_HP_FILTER_CUTOFF_SEL_MASK; |
354 | *hz = mma8452_hp_filter_cutoff[i][ret][0]; | 446 | *hz = mma8452_hp_filter_cutoff[j][i][ret][0]; |
355 | *uHz = mma8452_hp_filter_cutoff[i][ret][1]; | 447 | *uHz = mma8452_hp_filter_cutoff[j][i][ret][1]; |
356 | 448 | ||
357 | return 0; | 449 | return 0; |
358 | } | 450 | } |
@@ -414,6 +506,15 @@ static int mma8452_read_raw(struct iio_dev *indio_dev, | |||
414 | } | 506 | } |
415 | 507 | ||
416 | return IIO_VAL_INT_PLUS_MICRO; | 508 | return IIO_VAL_INT_PLUS_MICRO; |
509 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | ||
510 | ret = mma8452_get_power_mode(data); | ||
511 | if (ret < 0) | ||
512 | return ret; | ||
513 | |||
514 | i = mma8452_get_odr_index(data); | ||
515 | |||
516 | *val = mma8452_os_ratio[ret][i]; | ||
517 | return IIO_VAL_INT; | ||
417 | } | 518 | } |
418 | 519 | ||
419 | return -EINVAL; | 520 | return -EINVAL; |
@@ -480,6 +581,21 @@ fail: | |||
480 | return ret; | 581 | return ret; |
481 | } | 582 | } |
482 | 583 | ||
584 | static int mma8452_set_power_mode(struct mma8452_data *data, u8 mode) | ||
585 | { | ||
586 | int reg; | ||
587 | |||
588 | reg = i2c_smbus_read_byte_data(data->client, | ||
589 | MMA8452_CTRL_REG2); | ||
590 | if (reg < 0) | ||
591 | return reg; | ||
592 | |||
593 | reg &= ~MMA8452_CTRL_REG2_MODS_MASK; | ||
594 | reg |= mode << MMA8452_CTRL_REG2_MODS_SHIFT; | ||
595 | |||
596 | return mma8452_change_config(data, MMA8452_CTRL_REG2, reg); | ||
597 | } | ||
598 | |||
483 | /* returns >0 if in freefall mode, 0 if not or <0 if an error occurred */ | 599 | /* returns >0 if in freefall mode, 0 if not or <0 if an error occurred */ |
484 | static int mma8452_freefall_mode_enabled(struct mma8452_data *data) | 600 | static int mma8452_freefall_mode_enabled(struct mma8452_data *data) |
485 | { | 601 | { |
@@ -597,6 +713,14 @@ static int mma8452_write_raw(struct iio_dev *indio_dev, | |||
597 | return mma8452_change_config(data, MMA8452_DATA_CFG, | 713 | return mma8452_change_config(data, MMA8452_DATA_CFG, |
598 | data->data_cfg); | 714 | data->data_cfg); |
599 | 715 | ||
716 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | ||
717 | ret = mma8452_get_odr_index(data); | ||
718 | |||
719 | for (i = 0; i < ARRAY_SIZE(mma8452_os_ratio); i++) { | ||
720 | if (mma8452_os_ratio[i][ret] == val) | ||
721 | return mma8452_set_power_mode(data, i); | ||
722 | } | ||
723 | |||
600 | default: | 724 | default: |
601 | return -EINVAL; | 725 | return -EINVAL; |
602 | } | 726 | } |
@@ -610,7 +734,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev, | |||
610 | int *val, int *val2) | 734 | int *val, int *val2) |
611 | { | 735 | { |
612 | struct mma8452_data *data = iio_priv(indio_dev); | 736 | struct mma8452_data *data = iio_priv(indio_dev); |
613 | int ret, us; | 737 | int ret, us, power_mode; |
614 | 738 | ||
615 | switch (info) { | 739 | switch (info) { |
616 | case IIO_EV_INFO_VALUE: | 740 | case IIO_EV_INFO_VALUE: |
@@ -629,7 +753,11 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev, | |||
629 | if (ret < 0) | 753 | if (ret < 0) |
630 | return ret; | 754 | return ret; |
631 | 755 | ||
632 | us = ret * mma8452_transient_time_step_us[ | 756 | power_mode = mma8452_get_power_mode(data); |
757 | if (power_mode < 0) | ||
758 | return power_mode; | ||
759 | |||
760 | us = ret * mma8452_transient_time_step_us[power_mode][ | ||
633 | mma8452_get_odr_index(data)]; | 761 | mma8452_get_odr_index(data)]; |
634 | *val = us / USEC_PER_SEC; | 762 | *val = us / USEC_PER_SEC; |
635 | *val2 = us % USEC_PER_SEC; | 763 | *val2 = us % USEC_PER_SEC; |
@@ -677,8 +805,12 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev, | |||
677 | val); | 805 | val); |
678 | 806 | ||
679 | case IIO_EV_INFO_PERIOD: | 807 | case IIO_EV_INFO_PERIOD: |
808 | ret = mma8452_get_power_mode(data); | ||
809 | if (ret < 0) | ||
810 | return ret; | ||
811 | |||
680 | steps = (val * USEC_PER_SEC + val2) / | 812 | steps = (val * USEC_PER_SEC + val2) / |
681 | mma8452_transient_time_step_us[ | 813 | mma8452_transient_time_step_us[ret][ |
682 | mma8452_get_odr_index(data)]; | 814 | mma8452_get_odr_index(data)]; |
683 | 815 | ||
684 | if (steps < 0 || steps > 0xff) | 816 | if (steps < 0 || steps > 0xff) |
@@ -978,7 +1110,8 @@ static struct attribute_group mma8452_event_attribute_group = { | |||
978 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ | 1110 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ |
979 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | 1111 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ |
980 | BIT(IIO_CHAN_INFO_SCALE) | \ | 1112 | BIT(IIO_CHAN_INFO_SCALE) | \ |
981 | BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \ | 1113 | BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY) | \ |
1114 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ | ||
982 | .scan_index = idx, \ | 1115 | .scan_index = idx, \ |
983 | .scan_type = { \ | 1116 | .scan_type = { \ |
984 | .sign = 's', \ | 1117 | .sign = 's', \ |
@@ -998,7 +1131,8 @@ static struct attribute_group mma8452_event_attribute_group = { | |||
998 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | 1131 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
999 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ | 1132 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ |
1000 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | 1133 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ |
1001 | BIT(IIO_CHAN_INFO_SCALE), \ | 1134 | BIT(IIO_CHAN_INFO_SCALE) | \ |
1135 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ | ||
1002 | .scan_index = idx, \ | 1136 | .scan_index = idx, \ |
1003 | .scan_type = { \ | 1137 | .scan_type = { \ |
1004 | .sign = 's', \ | 1138 | .sign = 's', \ |
@@ -1171,6 +1305,7 @@ static struct attribute *mma8452_attributes[] = { | |||
1171 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, | 1305 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, |
1172 | &iio_dev_attr_in_accel_scale_available.dev_attr.attr, | 1306 | &iio_dev_attr_in_accel_scale_available.dev_attr.attr, |
1173 | &iio_dev_attr_in_accel_filter_high_pass_3db_frequency_available.dev_attr.attr, | 1307 | &iio_dev_attr_in_accel_filter_high_pass_3db_frequency_available.dev_attr.attr, |
1308 | &iio_dev_attr_in_accel_oversampling_ratio_available.dev_attr.attr, | ||
1174 | NULL | 1309 | NULL |
1175 | }; | 1310 | }; |
1176 | 1311 | ||
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index dc73f2d85e6d..b8d3c3c91b4d 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c | |||
@@ -757,13 +757,15 @@ int st_accel_common_probe(struct iio_dev *indio_dev) | |||
757 | indio_dev->info = &accel_info; | 757 | indio_dev->info = &accel_info; |
758 | mutex_init(&adata->tb.buf_lock); | 758 | mutex_init(&adata->tb.buf_lock); |
759 | 759 | ||
760 | st_sensors_power_enable(indio_dev); | 760 | err = st_sensors_power_enable(indio_dev); |
761 | if (err) | ||
762 | return err; | ||
761 | 763 | ||
762 | err = st_sensors_check_device_support(indio_dev, | 764 | err = st_sensors_check_device_support(indio_dev, |
763 | ARRAY_SIZE(st_accel_sensors_settings), | 765 | ARRAY_SIZE(st_accel_sensors_settings), |
764 | st_accel_sensors_settings); | 766 | st_accel_sensors_settings); |
765 | if (err < 0) | 767 | if (err < 0) |
766 | return err; | 768 | goto st_accel_power_off; |
767 | 769 | ||
768 | adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; | 770 | adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; |
769 | adata->multiread_bit = adata->sensor_settings->multi_read_bit; | 771 | adata->multiread_bit = adata->sensor_settings->multi_read_bit; |
@@ -780,11 +782,11 @@ int st_accel_common_probe(struct iio_dev *indio_dev) | |||
780 | 782 | ||
781 | err = st_sensors_init_sensor(indio_dev, adata->dev->platform_data); | 783 | err = st_sensors_init_sensor(indio_dev, adata->dev->platform_data); |
782 | if (err < 0) | 784 | if (err < 0) |
783 | return err; | 785 | goto st_accel_power_off; |
784 | 786 | ||
785 | err = st_accel_allocate_ring(indio_dev); | 787 | err = st_accel_allocate_ring(indio_dev); |
786 | if (err < 0) | 788 | if (err < 0) |
787 | return err; | 789 | goto st_accel_power_off; |
788 | 790 | ||
789 | if (irq > 0) { | 791 | if (irq > 0) { |
790 | err = st_sensors_allocate_trigger(indio_dev, | 792 | err = st_sensors_allocate_trigger(indio_dev, |
@@ -807,6 +809,8 @@ st_accel_device_register_error: | |||
807 | st_sensors_deallocate_trigger(indio_dev); | 809 | st_sensors_deallocate_trigger(indio_dev); |
808 | st_accel_probe_trigger_error: | 810 | st_accel_probe_trigger_error: |
809 | st_accel_deallocate_ring(indio_dev); | 811 | st_accel_deallocate_ring(indio_dev); |
812 | st_accel_power_off: | ||
813 | st_sensors_power_disable(indio_dev); | ||
810 | 814 | ||
811 | return err; | 815 | return err; |
812 | } | 816 | } |
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 21e19b60e2b9..01240aeeeab0 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c | |||
@@ -154,12 +154,11 @@ static int ad7266_read_raw(struct iio_dev *indio_dev, | |||
154 | 154 | ||
155 | switch (m) { | 155 | switch (m) { |
156 | case IIO_CHAN_INFO_RAW: | 156 | case IIO_CHAN_INFO_RAW: |
157 | if (iio_buffer_enabled(indio_dev)) | 157 | ret = iio_device_claim_direct_mode(indio_dev); |
158 | return -EBUSY; | ||
159 | |||
160 | ret = ad7266_read_single(st, val, chan->address); | ||
161 | if (ret) | 158 | if (ret) |
162 | return ret; | 159 | return ret; |
160 | ret = ad7266_read_single(st, val, chan->address); | ||
161 | iio_device_release_direct_mode(indio_dev); | ||
163 | 162 | ||
164 | *val = (*val >> 2) & 0xfff; | 163 | *val = (*val >> 2) & 0xfff; |
165 | if (chan->scan_type.sign == 's') | 164 | if (chan->scan_type.sign == 's') |
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c index be85c2a0ad97..810c9a9fa62f 100644 --- a/drivers/iio/adc/ad7476.c +++ b/drivers/iio/adc/ad7476.c | |||
@@ -106,12 +106,11 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, | |||
106 | 106 | ||
107 | switch (m) { | 107 | switch (m) { |
108 | case IIO_CHAN_INFO_RAW: | 108 | case IIO_CHAN_INFO_RAW: |
109 | mutex_lock(&indio_dev->mlock); | 109 | ret = iio_device_claim_direct_mode(indio_dev); |
110 | if (iio_buffer_enabled(indio_dev)) | 110 | if (ret) |
111 | ret = -EBUSY; | 111 | return ret; |
112 | else | 112 | ret = ad7476_scan_direct(st); |
113 | ret = ad7476_scan_direct(st); | 113 | iio_device_release_direct_mode(indio_dev); |
114 | mutex_unlock(&indio_dev->mlock); | ||
115 | 114 | ||
116 | if (ret < 0) | 115 | if (ret < 0) |
117 | return ret; | 116 | return ret; |
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index cf172d58cd44..1dfe6410c64c 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c | |||
@@ -272,30 +272,22 @@ static ssize_t ad7791_write_frequency(struct device *dev, | |||
272 | struct ad7791_state *st = iio_priv(indio_dev); | 272 | struct ad7791_state *st = iio_priv(indio_dev); |
273 | int i, ret; | 273 | int i, ret; |
274 | 274 | ||
275 | mutex_lock(&indio_dev->mlock); | 275 | for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) |
276 | if (iio_buffer_enabled(indio_dev)) { | 276 | if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) |
277 | mutex_unlock(&indio_dev->mlock); | ||
278 | return -EBUSY; | ||
279 | } | ||
280 | mutex_unlock(&indio_dev->mlock); | ||
281 | |||
282 | ret = -EINVAL; | ||
283 | |||
284 | for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) { | ||
285 | if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) { | ||
286 | |||
287 | mutex_lock(&indio_dev->mlock); | ||
288 | st->filter &= ~AD7791_FILTER_RATE_MASK; | ||
289 | st->filter |= i; | ||
290 | ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, | ||
291 | sizeof(st->filter), st->filter); | ||
292 | mutex_unlock(&indio_dev->mlock); | ||
293 | ret = 0; | ||
294 | break; | 277 | break; |
295 | } | 278 | if (i == ARRAY_SIZE(ad7791_sample_freq_avail)) |
296 | } | 279 | return -EINVAL; |
280 | |||
281 | ret = iio_device_claim_direct_mode(indio_dev); | ||
282 | if (ret) | ||
283 | return ret; | ||
284 | st->filter &= ~AD7791_FILTER_RATE_MASK; | ||
285 | st->filter |= i; | ||
286 | ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, sizeof(st->filter), | ||
287 | st->filter); | ||
288 | iio_device_release_direct_mode(indio_dev); | ||
297 | 289 | ||
298 | return ret ? ret : len; | 290 | return len; |
299 | } | 291 | } |
300 | 292 | ||
301 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, | 293 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, |
diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 7b07bb651671..a43722fbf03a 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c | |||
@@ -369,13 +369,6 @@ static ssize_t ad7793_write_frequency(struct device *dev, | |||
369 | long lval; | 369 | long lval; |
370 | int i, ret; | 370 | int i, ret; |
371 | 371 | ||
372 | mutex_lock(&indio_dev->mlock); | ||
373 | if (iio_buffer_enabled(indio_dev)) { | ||
374 | mutex_unlock(&indio_dev->mlock); | ||
375 | return -EBUSY; | ||
376 | } | ||
377 | mutex_unlock(&indio_dev->mlock); | ||
378 | |||
379 | ret = kstrtol(buf, 10, &lval); | 372 | ret = kstrtol(buf, 10, &lval); |
380 | if (ret) | 373 | if (ret) |
381 | return ret; | 374 | return ret; |
@@ -383,20 +376,21 @@ static ssize_t ad7793_write_frequency(struct device *dev, | |||
383 | if (lval == 0) | 376 | if (lval == 0) |
384 | return -EINVAL; | 377 | return -EINVAL; |
385 | 378 | ||
386 | ret = -EINVAL; | ||
387 | |||
388 | for (i = 0; i < 16; i++) | 379 | for (i = 0; i < 16; i++) |
389 | if (lval == st->chip_info->sample_freq_avail[i]) { | 380 | if (lval == st->chip_info->sample_freq_avail[i]) |
390 | mutex_lock(&indio_dev->mlock); | 381 | break; |
391 | st->mode &= ~AD7793_MODE_RATE(-1); | 382 | if (i == 16) |
392 | st->mode |= AD7793_MODE_RATE(i); | 383 | return -EINVAL; |
393 | ad_sd_write_reg(&st->sd, AD7793_REG_MODE, | ||
394 | sizeof(st->mode), st->mode); | ||
395 | mutex_unlock(&indio_dev->mlock); | ||
396 | ret = 0; | ||
397 | } | ||
398 | 384 | ||
399 | return ret ? ret : len; | 385 | ret = iio_device_claim_direct_mode(indio_dev); |
386 | if (ret) | ||
387 | return ret; | ||
388 | st->mode &= ~AD7793_MODE_RATE(-1); | ||
389 | st->mode |= AD7793_MODE_RATE(i); | ||
390 | ad_sd_write_reg(&st->sd, AD7793_REG_MODE, sizeof(st->mode), st->mode); | ||
391 | iio_device_release_direct_mode(indio_dev); | ||
392 | |||
393 | return len; | ||
400 | } | 394 | } |
401 | 395 | ||
402 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, | 396 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, |
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c index 2d3c397e66ad..ee2ccc19fab6 100644 --- a/drivers/iio/adc/ad7887.c +++ b/drivers/iio/adc/ad7887.c | |||
@@ -156,12 +156,11 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, | |||
156 | 156 | ||
157 | switch (m) { | 157 | switch (m) { |
158 | case IIO_CHAN_INFO_RAW: | 158 | case IIO_CHAN_INFO_RAW: |
159 | mutex_lock(&indio_dev->mlock); | 159 | ret = iio_device_claim_direct_mode(indio_dev); |
160 | if (iio_buffer_enabled(indio_dev)) | 160 | if (ret) |
161 | ret = -EBUSY; | 161 | return ret; |
162 | else | 162 | ret = ad7887_scan_direct(st, chan->address); |
163 | ret = ad7887_scan_direct(st, chan->address); | 163 | iio_device_release_direct_mode(indio_dev); |
164 | mutex_unlock(&indio_dev->mlock); | ||
165 | 164 | ||
166 | if (ret < 0) | 165 | if (ret < 0) |
167 | return ret; | 166 | return ret; |
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c index 45e29ccd824f..ff444c19d749 100644 --- a/drivers/iio/adc/ad7923.c +++ b/drivers/iio/adc/ad7923.c | |||
@@ -233,12 +233,11 @@ static int ad7923_read_raw(struct iio_dev *indio_dev, | |||
233 | 233 | ||
234 | switch (m) { | 234 | switch (m) { |
235 | case IIO_CHAN_INFO_RAW: | 235 | case IIO_CHAN_INFO_RAW: |
236 | mutex_lock(&indio_dev->mlock); | 236 | ret = iio_device_claim_direct_mode(indio_dev); |
237 | if (iio_buffer_enabled(indio_dev)) | 237 | if (ret) |
238 | ret = -EBUSY; | 238 | return ret; |
239 | else | 239 | ret = ad7923_scan_direct(st, chan->address); |
240 | ret = ad7923_scan_direct(st, chan->address); | 240 | iio_device_release_direct_mode(indio_dev); |
241 | mutex_unlock(&indio_dev->mlock); | ||
242 | 241 | ||
243 | if (ret < 0) | 242 | if (ret < 0) |
244 | return ret; | 243 | return ret; |
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index a3f5254f4e51..ec0200dd52cb 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c | |||
@@ -282,12 +282,11 @@ static int ad799x_read_raw(struct iio_dev *indio_dev, | |||
282 | 282 | ||
283 | switch (m) { | 283 | switch (m) { |
284 | case IIO_CHAN_INFO_RAW: | 284 | case IIO_CHAN_INFO_RAW: |
285 | mutex_lock(&indio_dev->mlock); | 285 | ret = iio_device_claim_direct_mode(indio_dev); |
286 | if (iio_buffer_enabled(indio_dev)) | 286 | if (ret) |
287 | ret = -EBUSY; | 287 | return ret; |
288 | else | 288 | ret = ad799x_scan_direct(st, chan->scan_index); |
289 | ret = ad799x_scan_direct(st, chan->scan_index); | 289 | iio_device_release_direct_mode(indio_dev); |
290 | mutex_unlock(&indio_dev->mlock); | ||
291 | 290 | ||
292 | if (ret < 0) | 291 | if (ret < 0) |
293 | return ret; | 292 | return ret; |
@@ -395,11 +394,9 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev, | |||
395 | struct ad799x_state *st = iio_priv(indio_dev); | 394 | struct ad799x_state *st = iio_priv(indio_dev); |
396 | int ret; | 395 | int ret; |
397 | 396 | ||
398 | mutex_lock(&indio_dev->mlock); | 397 | ret = iio_device_claim_direct_mode(indio_dev); |
399 | if (iio_buffer_enabled(indio_dev)) { | 398 | if (ret) |
400 | ret = -EBUSY; | 399 | return ret; |
401 | goto done; | ||
402 | } | ||
403 | 400 | ||
404 | if (state) | 401 | if (state) |
405 | st->config |= BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT; | 402 | st->config |= BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT; |
@@ -412,10 +409,7 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev, | |||
412 | st->config &= ~AD7998_ALERT_EN; | 409 | st->config &= ~AD7998_ALERT_EN; |
413 | 410 | ||
414 | ret = ad799x_write_config(st, st->config); | 411 | ret = ad799x_write_config(st, st->config); |
415 | 412 | iio_device_release_direct_mode(indio_dev); | |
416 | done: | ||
417 | mutex_unlock(&indio_dev->mlock); | ||
418 | |||
419 | return ret; | 413 | return ret; |
420 | } | 414 | } |
421 | 415 | ||
diff --git a/drivers/iio/adc/mxs-lradc.c b/drivers/iio/adc/mxs-lradc.c index ad26da1edbee..b84d37c80a94 100644 --- a/drivers/iio/adc/mxs-lradc.c +++ b/drivers/iio/adc/mxs-lradc.c | |||
@@ -373,13 +373,6 @@ static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc) | |||
373 | return LRADC_CTRL0_MX28_PLATE_MASK; | 373 | return LRADC_CTRL0_MX28_PLATE_MASK; |
374 | } | 374 | } |
375 | 375 | ||
376 | static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc) | ||
377 | { | ||
378 | if (lradc->soc == IMX23_LRADC) | ||
379 | return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK; | ||
380 | return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK; | ||
381 | } | ||
382 | |||
383 | static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc) | 376 | static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc) |
384 | { | 377 | { |
385 | if (lradc->soc == IMX23_LRADC) | 378 | if (lradc->soc == IMX23_LRADC) |
@@ -1120,18 +1113,16 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc) | |||
1120 | { | 1113 | { |
1121 | struct input_dev *input; | 1114 | struct input_dev *input; |
1122 | struct device *dev = lradc->dev; | 1115 | struct device *dev = lradc->dev; |
1123 | int ret; | ||
1124 | 1116 | ||
1125 | if (!lradc->use_touchscreen) | 1117 | if (!lradc->use_touchscreen) |
1126 | return 0; | 1118 | return 0; |
1127 | 1119 | ||
1128 | input = input_allocate_device(); | 1120 | input = devm_input_allocate_device(dev); |
1129 | if (!input) | 1121 | if (!input) |
1130 | return -ENOMEM; | 1122 | return -ENOMEM; |
1131 | 1123 | ||
1132 | input->name = DRIVER_NAME; | 1124 | input->name = DRIVER_NAME; |
1133 | input->id.bustype = BUS_HOST; | 1125 | input->id.bustype = BUS_HOST; |
1134 | input->dev.parent = dev; | ||
1135 | input->open = mxs_lradc_ts_open; | 1126 | input->open = mxs_lradc_ts_open; |
1136 | input->close = mxs_lradc_ts_close; | 1127 | input->close = mxs_lradc_ts_close; |
1137 | 1128 | ||
@@ -1146,20 +1137,8 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc) | |||
1146 | 1137 | ||
1147 | lradc->ts_input = input; | 1138 | lradc->ts_input = input; |
1148 | input_set_drvdata(input, lradc); | 1139 | input_set_drvdata(input, lradc); |
1149 | ret = input_register_device(input); | ||
1150 | if (ret) | ||
1151 | input_free_device(lradc->ts_input); | ||
1152 | |||
1153 | return ret; | ||
1154 | } | ||
1155 | |||
1156 | static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc) | ||
1157 | { | ||
1158 | if (!lradc->use_touchscreen) | ||
1159 | return; | ||
1160 | 1140 | ||
1161 | mxs_lradc_disable_ts(lradc); | 1141 | return input_register_device(input); |
1162 | input_unregister_device(lradc->ts_input); | ||
1163 | } | 1142 | } |
1164 | 1143 | ||
1165 | /* | 1144 | /* |
@@ -1510,7 +1489,9 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) | |||
1510 | { | 1489 | { |
1511 | int i; | 1490 | int i; |
1512 | 1491 | ||
1513 | mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1); | 1492 | mxs_lradc_reg_clear(lradc, |
1493 | lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, | ||
1494 | LRADC_CTRL1); | ||
1514 | 1495 | ||
1515 | for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) | 1496 | for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) |
1516 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i)); | 1497 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i)); |
@@ -1721,13 +1702,11 @@ static int mxs_lradc_probe(struct platform_device *pdev) | |||
1721 | ret = iio_device_register(iio); | 1702 | ret = iio_device_register(iio); |
1722 | if (ret) { | 1703 | if (ret) { |
1723 | dev_err(dev, "Failed to register IIO device\n"); | 1704 | dev_err(dev, "Failed to register IIO device\n"); |
1724 | goto err_ts; | 1705 | return ret; |
1725 | } | 1706 | } |
1726 | 1707 | ||
1727 | return 0; | 1708 | return 0; |
1728 | 1709 | ||
1729 | err_ts: | ||
1730 | mxs_lradc_ts_unregister(lradc); | ||
1731 | err_ts_register: | 1710 | err_ts_register: |
1732 | mxs_lradc_hw_stop(lradc); | 1711 | mxs_lradc_hw_stop(lradc); |
1733 | err_dev: | 1712 | err_dev: |
@@ -1745,7 +1724,6 @@ static int mxs_lradc_remove(struct platform_device *pdev) | |||
1745 | struct mxs_lradc *lradc = iio_priv(iio); | 1724 | struct mxs_lradc *lradc = iio_priv(iio); |
1746 | 1725 | ||
1747 | iio_device_unregister(iio); | 1726 | iio_device_unregister(iio); |
1748 | mxs_lradc_ts_unregister(lradc); | ||
1749 | mxs_lradc_hw_stop(lradc); | 1727 | mxs_lradc_hw_stop(lradc); |
1750 | mxs_lradc_trigger_remove(iio); | 1728 | mxs_lradc_trigger_remove(iio); |
1751 | iio_triggered_buffer_cleanup(iio); | 1729 | iio_triggered_buffer_cleanup(iio); |
diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c index e525aa6475c4..57365c504093 100644 --- a/drivers/iio/adc/nau7802.c +++ b/drivers/iio/adc/nau7802.c | |||
@@ -79,10 +79,29 @@ static const struct iio_chan_spec nau7802_chan_array[] = { | |||
79 | static const u16 nau7802_sample_freq_avail[] = {10, 20, 40, 80, | 79 | static const u16 nau7802_sample_freq_avail[] = {10, 20, 40, 80, |
80 | 10, 10, 10, 320}; | 80 | 10, 10, 10, 320}; |
81 | 81 | ||
82 | static ssize_t nau7802_show_scales(struct device *dev, | ||
83 | struct device_attribute *attr, char *buf) | ||
84 | { | ||
85 | struct nau7802_state *st = iio_priv(dev_to_iio_dev(dev)); | ||
86 | int i, len = 0; | ||
87 | |||
88 | for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) | ||
89 | len += scnprintf(buf + len, PAGE_SIZE - len, "0.%09d ", | ||
90 | st->scale_avail[i]); | ||
91 | |||
92 | buf[len-1] = '\n'; | ||
93 | |||
94 | return len; | ||
95 | } | ||
96 | |||
82 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 40 80 320"); | 97 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 40 80 320"); |
83 | 98 | ||
99 | static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, nau7802_show_scales, | ||
100 | NULL, 0); | ||
101 | |||
84 | static struct attribute *nau7802_attributes[] = { | 102 | static struct attribute *nau7802_attributes[] = { |
85 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | 103 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, |
104 | &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, | ||
86 | NULL | 105 | NULL |
87 | }; | 106 | }; |
88 | 107 | ||
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index 73cbf0b54e54..8be192a84893 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c | |||
@@ -55,6 +55,11 @@ | |||
55 | #define ADS1015_DEFAULT_DATA_RATE 4 | 55 | #define ADS1015_DEFAULT_DATA_RATE 4 |
56 | #define ADS1015_DEFAULT_CHAN 0 | 56 | #define ADS1015_DEFAULT_CHAN 0 |
57 | 57 | ||
58 | enum { | ||
59 | ADS1015, | ||
60 | ADS1115, | ||
61 | }; | ||
62 | |||
58 | enum ads1015_channels { | 63 | enum ads1015_channels { |
59 | ADS1015_AIN0_AIN1 = 0, | 64 | ADS1015_AIN0_AIN1 = 0, |
60 | ADS1015_AIN0_AIN3, | 65 | ADS1015_AIN0_AIN3, |
@@ -71,6 +76,10 @@ static const unsigned int ads1015_data_rate[] = { | |||
71 | 128, 250, 490, 920, 1600, 2400, 3300, 3300 | 76 | 128, 250, 490, 920, 1600, 2400, 3300, 3300 |
72 | }; | 77 | }; |
73 | 78 | ||
79 | static const unsigned int ads1115_data_rate[] = { | ||
80 | 8, 16, 32, 64, 128, 250, 475, 860 | ||
81 | }; | ||
82 | |||
74 | static const struct { | 83 | static const struct { |
75 | int scale; | 84 | int scale; |
76 | int uscale; | 85 | int uscale; |
@@ -101,6 +110,7 @@ static const struct { | |||
101 | .shift = 4, \ | 110 | .shift = 4, \ |
102 | .endianness = IIO_CPU, \ | 111 | .endianness = IIO_CPU, \ |
103 | }, \ | 112 | }, \ |
113 | .datasheet_name = "AIN"#_chan, \ | ||
104 | } | 114 | } |
105 | 115 | ||
106 | #define ADS1015_V_DIFF_CHAN(_chan, _chan2, _addr) { \ | 116 | #define ADS1015_V_DIFF_CHAN(_chan, _chan2, _addr) { \ |
@@ -121,6 +131,45 @@ static const struct { | |||
121 | .shift = 4, \ | 131 | .shift = 4, \ |
122 | .endianness = IIO_CPU, \ | 132 | .endianness = IIO_CPU, \ |
123 | }, \ | 133 | }, \ |
134 | .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \ | ||
135 | } | ||
136 | |||
137 | #define ADS1115_V_CHAN(_chan, _addr) { \ | ||
138 | .type = IIO_VOLTAGE, \ | ||
139 | .indexed = 1, \ | ||
140 | .address = _addr, \ | ||
141 | .channel = _chan, \ | ||
142 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | ||
143 | BIT(IIO_CHAN_INFO_SCALE) | \ | ||
144 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | ||
145 | .scan_index = _addr, \ | ||
146 | .scan_type = { \ | ||
147 | .sign = 's', \ | ||
148 | .realbits = 16, \ | ||
149 | .storagebits = 16, \ | ||
150 | .endianness = IIO_CPU, \ | ||
151 | }, \ | ||
152 | .datasheet_name = "AIN"#_chan, \ | ||
153 | } | ||
154 | |||
155 | #define ADS1115_V_DIFF_CHAN(_chan, _chan2, _addr) { \ | ||
156 | .type = IIO_VOLTAGE, \ | ||
157 | .differential = 1, \ | ||
158 | .indexed = 1, \ | ||
159 | .address = _addr, \ | ||
160 | .channel = _chan, \ | ||
161 | .channel2 = _chan2, \ | ||
162 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | ||
163 | BIT(IIO_CHAN_INFO_SCALE) | \ | ||
164 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | ||
165 | .scan_index = _addr, \ | ||
166 | .scan_type = { \ | ||
167 | .sign = 's', \ | ||
168 | .realbits = 16, \ | ||
169 | .storagebits = 16, \ | ||
170 | .endianness = IIO_CPU, \ | ||
171 | }, \ | ||
172 | .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \ | ||
124 | } | 173 | } |
125 | 174 | ||
126 | struct ads1015_data { | 175 | struct ads1015_data { |
@@ -131,6 +180,8 @@ struct ads1015_data { | |||
131 | */ | 180 | */ |
132 | struct mutex lock; | 181 | struct mutex lock; |
133 | struct ads1015_channel_data channel_data[ADS1015_CHANNELS]; | 182 | struct ads1015_channel_data channel_data[ADS1015_CHANNELS]; |
183 | |||
184 | unsigned int *data_rate; | ||
134 | }; | 185 | }; |
135 | 186 | ||
136 | static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg) | 187 | static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg) |
@@ -157,6 +208,18 @@ static const struct iio_chan_spec ads1015_channels[] = { | |||
157 | IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP), | 208 | IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP), |
158 | }; | 209 | }; |
159 | 210 | ||
211 | static const struct iio_chan_spec ads1115_channels[] = { | ||
212 | ADS1115_V_DIFF_CHAN(0, 1, ADS1015_AIN0_AIN1), | ||
213 | ADS1115_V_DIFF_CHAN(0, 3, ADS1015_AIN0_AIN3), | ||
214 | ADS1115_V_DIFF_CHAN(1, 3, ADS1015_AIN1_AIN3), | ||
215 | ADS1115_V_DIFF_CHAN(2, 3, ADS1015_AIN2_AIN3), | ||
216 | ADS1115_V_CHAN(0, ADS1015_AIN0), | ||
217 | ADS1115_V_CHAN(1, ADS1015_AIN1), | ||
218 | ADS1115_V_CHAN(2, ADS1015_AIN2), | ||
219 | ADS1115_V_CHAN(3, ADS1015_AIN3), | ||
220 | IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP), | ||
221 | }; | ||
222 | |||
160 | static int ads1015_set_power_state(struct ads1015_data *data, bool on) | 223 | static int ads1015_set_power_state(struct ads1015_data *data, bool on) |
161 | { | 224 | { |
162 | int ret; | 225 | int ret; |
@@ -196,7 +259,7 @@ int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val) | |||
196 | return ret; | 259 | return ret; |
197 | 260 | ||
198 | if (change) { | 261 | if (change) { |
199 | conv_time = DIV_ROUND_UP(USEC_PER_SEC, ads1015_data_rate[dr]); | 262 | conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]); |
200 | usleep_range(conv_time, conv_time + 1); | 263 | usleep_range(conv_time, conv_time + 1); |
201 | } | 264 | } |
202 | 265 | ||
@@ -263,7 +326,7 @@ static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate) | |||
263 | int i, ret, rindex = -1; | 326 | int i, ret, rindex = -1; |
264 | 327 | ||
265 | for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++) | 328 | for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++) |
266 | if (ads1015_data_rate[i] == rate) { | 329 | if (data->data_rate[i] == rate) { |
267 | rindex = i; | 330 | rindex = i; |
268 | break; | 331 | break; |
269 | } | 332 | } |
@@ -291,7 +354,9 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, | |||
291 | mutex_lock(&indio_dev->mlock); | 354 | mutex_lock(&indio_dev->mlock); |
292 | mutex_lock(&data->lock); | 355 | mutex_lock(&data->lock); |
293 | switch (mask) { | 356 | switch (mask) { |
294 | case IIO_CHAN_INFO_RAW: | 357 | case IIO_CHAN_INFO_RAW: { |
358 | int shift = chan->scan_type.shift; | ||
359 | |||
295 | if (iio_buffer_enabled(indio_dev)) { | 360 | if (iio_buffer_enabled(indio_dev)) { |
296 | ret = -EBUSY; | 361 | ret = -EBUSY; |
297 | break; | 362 | break; |
@@ -307,8 +372,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, | |||
307 | break; | 372 | break; |
308 | } | 373 | } |
309 | 374 | ||
310 | /* 12 bit res, D0 is bit 4 in conversion register */ | 375 | *val = sign_extend32(*val >> shift, 15 - shift); |
311 | *val = sign_extend32(*val >> 4, 11); | ||
312 | 376 | ||
313 | ret = ads1015_set_power_state(data, false); | 377 | ret = ads1015_set_power_state(data, false); |
314 | if (ret < 0) | 378 | if (ret < 0) |
@@ -316,6 +380,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, | |||
316 | 380 | ||
317 | ret = IIO_VAL_INT; | 381 | ret = IIO_VAL_INT; |
318 | break; | 382 | break; |
383 | } | ||
319 | case IIO_CHAN_INFO_SCALE: | 384 | case IIO_CHAN_INFO_SCALE: |
320 | idx = data->channel_data[chan->address].pga; | 385 | idx = data->channel_data[chan->address].pga; |
321 | *val = ads1015_scale[idx].scale; | 386 | *val = ads1015_scale[idx].scale; |
@@ -324,7 +389,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, | |||
324 | break; | 389 | break; |
325 | case IIO_CHAN_INFO_SAMP_FREQ: | 390 | case IIO_CHAN_INFO_SAMP_FREQ: |
326 | idx = data->channel_data[chan->address].data_rate; | 391 | idx = data->channel_data[chan->address].data_rate; |
327 | *val = ads1015_data_rate[idx]; | 392 | *val = data->data_rate[idx]; |
328 | ret = IIO_VAL_INT; | 393 | ret = IIO_VAL_INT; |
329 | break; | 394 | break; |
330 | default: | 395 | default: |
@@ -380,12 +445,15 @@ static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = { | |||
380 | }; | 445 | }; |
381 | 446 | ||
382 | static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125"); | 447 | static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125"); |
383 | static IIO_CONST_ATTR(sampling_frequency_available, | 448 | |
384 | "128 250 490 920 1600 2400 3300"); | 449 | static IIO_CONST_ATTR_NAMED(ads1015_sampling_frequency_available, |
450 | sampling_frequency_available, "128 250 490 920 1600 2400 3300"); | ||
451 | static IIO_CONST_ATTR_NAMED(ads1115_sampling_frequency_available, | ||
452 | sampling_frequency_available, "8 16 32 64 128 250 475 860"); | ||
385 | 453 | ||
386 | static struct attribute *ads1015_attributes[] = { | 454 | static struct attribute *ads1015_attributes[] = { |
387 | &iio_const_attr_scale_available.dev_attr.attr, | 455 | &iio_const_attr_scale_available.dev_attr.attr, |
388 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | 456 | &iio_const_attr_ads1015_sampling_frequency_available.dev_attr.attr, |
389 | NULL, | 457 | NULL, |
390 | }; | 458 | }; |
391 | 459 | ||
@@ -393,11 +461,28 @@ static const struct attribute_group ads1015_attribute_group = { | |||
393 | .attrs = ads1015_attributes, | 461 | .attrs = ads1015_attributes, |
394 | }; | 462 | }; |
395 | 463 | ||
396 | static const struct iio_info ads1015_info = { | 464 | static struct attribute *ads1115_attributes[] = { |
465 | &iio_const_attr_scale_available.dev_attr.attr, | ||
466 | &iio_const_attr_ads1115_sampling_frequency_available.dev_attr.attr, | ||
467 | NULL, | ||
468 | }; | ||
469 | |||
470 | static const struct attribute_group ads1115_attribute_group = { | ||
471 | .attrs = ads1115_attributes, | ||
472 | }; | ||
473 | |||
474 | static struct iio_info ads1015_info = { | ||
475 | .driver_module = THIS_MODULE, | ||
476 | .read_raw = ads1015_read_raw, | ||
477 | .write_raw = ads1015_write_raw, | ||
478 | .attrs = &ads1015_attribute_group, | ||
479 | }; | ||
480 | |||
481 | static struct iio_info ads1115_info = { | ||
397 | .driver_module = THIS_MODULE, | 482 | .driver_module = THIS_MODULE, |
398 | .read_raw = ads1015_read_raw, | 483 | .read_raw = ads1015_read_raw, |
399 | .write_raw = ads1015_write_raw, | 484 | .write_raw = ads1015_write_raw, |
400 | .attrs = &ads1015_attribute_group, | 485 | .attrs = &ads1115_attribute_group, |
401 | }; | 486 | }; |
402 | 487 | ||
403 | #ifdef CONFIG_OF | 488 | #ifdef CONFIG_OF |
@@ -500,12 +585,24 @@ static int ads1015_probe(struct i2c_client *client, | |||
500 | mutex_init(&data->lock); | 585 | mutex_init(&data->lock); |
501 | 586 | ||
502 | indio_dev->dev.parent = &client->dev; | 587 | indio_dev->dev.parent = &client->dev; |
503 | indio_dev->info = &ads1015_info; | ||
504 | indio_dev->name = ADS1015_DRV_NAME; | 588 | indio_dev->name = ADS1015_DRV_NAME; |
505 | indio_dev->channels = ads1015_channels; | ||
506 | indio_dev->num_channels = ARRAY_SIZE(ads1015_channels); | ||
507 | indio_dev->modes = INDIO_DIRECT_MODE; | 589 | indio_dev->modes = INDIO_DIRECT_MODE; |
508 | 590 | ||
591 | switch (id->driver_data) { | ||
592 | case ADS1015: | ||
593 | indio_dev->channels = ads1015_channels; | ||
594 | indio_dev->num_channels = ARRAY_SIZE(ads1015_channels); | ||
595 | indio_dev->info = &ads1015_info; | ||
596 | data->data_rate = (unsigned int *) &ads1015_data_rate; | ||
597 | break; | ||
598 | case ADS1115: | ||
599 | indio_dev->channels = ads1115_channels; | ||
600 | indio_dev->num_channels = ARRAY_SIZE(ads1115_channels); | ||
601 | indio_dev->info = &ads1115_info; | ||
602 | data->data_rate = (unsigned int *) &ads1115_data_rate; | ||
603 | break; | ||
604 | } | ||
605 | |||
509 | /* we need to keep this ABI the same as used by hwmon ADS1015 driver */ | 606 | /* we need to keep this ABI the same as used by hwmon ADS1015 driver */ |
510 | ads1015_get_channels_config(client); | 607 | ads1015_get_channels_config(client); |
511 | 608 | ||
@@ -590,7 +687,8 @@ static const struct dev_pm_ops ads1015_pm_ops = { | |||
590 | }; | 687 | }; |
591 | 688 | ||
592 | static const struct i2c_device_id ads1015_id[] = { | 689 | static const struct i2c_device_id ads1015_id[] = { |
593 | {"ads1015", 0}, | 690 | {"ads1015", ADS1015}, |
691 | {"ads1115", ADS1115}, | ||
594 | {} | 692 | {} |
595 | }; | 693 | }; |
596 | MODULE_DEVICE_TABLE(i2c, ads1015_id); | 694 | MODULE_DEVICE_TABLE(i2c, ads1015_id); |
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index c1e05532d437..8a368756881b 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c | |||
@@ -326,8 +326,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) | |||
326 | int i; | 326 | int i; |
327 | 327 | ||
328 | indio_dev->num_channels = channels; | 328 | indio_dev->num_channels = channels; |
329 | chan_array = kcalloc(channels, | 329 | chan_array = kcalloc(channels, sizeof(*chan_array), GFP_KERNEL); |
330 | sizeof(struct iio_chan_spec), GFP_KERNEL); | ||
331 | if (chan_array == NULL) | 330 | if (chan_array == NULL) |
332 | return -ENOMEM; | 331 | return -ENOMEM; |
333 | 332 | ||
@@ -467,8 +466,7 @@ static int tiadc_probe(struct platform_device *pdev) | |||
467 | return -EINVAL; | 466 | return -EINVAL; |
468 | } | 467 | } |
469 | 468 | ||
470 | indio_dev = devm_iio_device_alloc(&pdev->dev, | 469 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*indio_dev)); |
471 | sizeof(struct tiadc_device)); | ||
472 | if (indio_dev == NULL) { | 470 | if (indio_dev == NULL) { |
473 | dev_err(&pdev->dev, "failed to allocate iio device\n"); | 471 | dev_err(&pdev->dev, "failed to allocate iio device\n"); |
474 | return -ENOMEM; | 472 | return -ENOMEM; |
@@ -531,8 +529,7 @@ static int tiadc_remove(struct platform_device *pdev) | |||
531 | return 0; | 529 | return 0; |
532 | } | 530 | } |
533 | 531 | ||
534 | #ifdef CONFIG_PM | 532 | static int __maybe_unused tiadc_suspend(struct device *dev) |
535 | static int tiadc_suspend(struct device *dev) | ||
536 | { | 533 | { |
537 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | 534 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
538 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | 535 | struct tiadc_device *adc_dev = iio_priv(indio_dev); |
@@ -550,7 +547,7 @@ static int tiadc_suspend(struct device *dev) | |||
550 | return 0; | 547 | return 0; |
551 | } | 548 | } |
552 | 549 | ||
553 | static int tiadc_resume(struct device *dev) | 550 | static int __maybe_unused tiadc_resume(struct device *dev) |
554 | { | 551 | { |
555 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | 552 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
556 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | 553 | struct tiadc_device *adc_dev = iio_priv(indio_dev); |
@@ -567,14 +564,7 @@ static int tiadc_resume(struct device *dev) | |||
567 | return 0; | 564 | return 0; |
568 | } | 565 | } |
569 | 566 | ||
570 | static const struct dev_pm_ops tiadc_pm_ops = { | 567 | static SIMPLE_DEV_PM_OPS(tiadc_pm_ops, tiadc_suspend, tiadc_resume); |
571 | .suspend = tiadc_suspend, | ||
572 | .resume = tiadc_resume, | ||
573 | }; | ||
574 | #define TIADC_PM_OPS (&tiadc_pm_ops) | ||
575 | #else | ||
576 | #define TIADC_PM_OPS NULL | ||
577 | #endif | ||
578 | 568 | ||
579 | static const struct of_device_id ti_adc_dt_ids[] = { | 569 | static const struct of_device_id ti_adc_dt_ids[] = { |
580 | { .compatible = "ti,am3359-adc", }, | 570 | { .compatible = "ti,am3359-adc", }, |
@@ -585,7 +575,7 @@ MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); | |||
585 | static struct platform_driver tiadc_driver = { | 575 | static struct platform_driver tiadc_driver = { |
586 | .driver = { | 576 | .driver = { |
587 | .name = "TI-am335x-adc", | 577 | .name = "TI-am335x-adc", |
588 | .pm = TIADC_PM_OPS, | 578 | .pm = &tiadc_pm_ops, |
589 | .of_match_table = ti_adc_dt_ids, | 579 | .of_match_table = ti_adc_dt_ids, |
590 | }, | 580 | }, |
591 | .probe = tiadc_probe, | 581 | .probe = tiadc_probe, |
diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index f73290f84c90..4bcc025e8c8a 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig | |||
@@ -5,15 +5,17 @@ | |||
5 | menu "Chemical Sensors" | 5 | menu "Chemical Sensors" |
6 | 6 | ||
7 | config ATLAS_PH_SENSOR | 7 | config ATLAS_PH_SENSOR |
8 | tristate "Atlas Scientific OEM pH-SM sensor" | 8 | tristate "Atlas Scientific OEM SM sensors" |
9 | depends on I2C | 9 | depends on I2C |
10 | select REGMAP_I2C | 10 | select REGMAP_I2C |
11 | select IIO_BUFFER | 11 | select IIO_BUFFER |
12 | select IIO_TRIGGERED_BUFFER | 12 | select IIO_TRIGGERED_BUFFER |
13 | select IRQ_WORK | 13 | select IRQ_WORK |
14 | help | 14 | help |
15 | Say Y here to build I2C interface support for the Atlas | 15 | Say Y here to build I2C interface support for the following |
16 | Scientific OEM pH-SM sensor. | 16 | Atlas Scientific OEM SM sensors: |
17 | * pH SM sensor | ||
18 | * EC SM sensor | ||
17 | 19 | ||
18 | To compile this driver as module, choose M here: the | 20 | To compile this driver as module, choose M here: the |
19 | module will be called atlas-ph-sensor. | 21 | module will be called atlas-ph-sensor. |
diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c index 62b37cd8fb56..02e85db5d31f 100644 --- a/drivers/iio/chemical/atlas-ph-sensor.c +++ b/drivers/iio/chemical/atlas-ph-sensor.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/irq_work.h> | 24 | #include <linux/irq_work.h> |
25 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include <linux/of_device.h> | ||
27 | #include <linux/regmap.h> | 28 | #include <linux/regmap.h> |
28 | #include <linux/iio/iio.h> | 29 | #include <linux/iio/iio.h> |
29 | #include <linux/iio/buffer.h> | 30 | #include <linux/iio/buffer.h> |
@@ -43,29 +44,50 @@ | |||
43 | 44 | ||
44 | #define ATLAS_REG_PWR_CONTROL 0x06 | 45 | #define ATLAS_REG_PWR_CONTROL 0x06 |
45 | 46 | ||
46 | #define ATLAS_REG_CALIB_STATUS 0x0d | 47 | #define ATLAS_REG_PH_CALIB_STATUS 0x0d |
47 | #define ATLAS_REG_CALIB_STATUS_MASK 0x07 | 48 | #define ATLAS_REG_PH_CALIB_STATUS_MASK 0x07 |
48 | #define ATLAS_REG_CALIB_STATUS_LOW BIT(0) | 49 | #define ATLAS_REG_PH_CALIB_STATUS_LOW BIT(0) |
49 | #define ATLAS_REG_CALIB_STATUS_MID BIT(1) | 50 | #define ATLAS_REG_PH_CALIB_STATUS_MID BIT(1) |
50 | #define ATLAS_REG_CALIB_STATUS_HIGH BIT(2) | 51 | #define ATLAS_REG_PH_CALIB_STATUS_HIGH BIT(2) |
51 | 52 | ||
52 | #define ATLAS_REG_TEMP_DATA 0x0e | 53 | #define ATLAS_REG_EC_CALIB_STATUS 0x0f |
54 | #define ATLAS_REG_EC_CALIB_STATUS_MASK 0x0f | ||
55 | #define ATLAS_REG_EC_CALIB_STATUS_DRY BIT(0) | ||
56 | #define ATLAS_REG_EC_CALIB_STATUS_SINGLE BIT(1) | ||
57 | #define ATLAS_REG_EC_CALIB_STATUS_LOW BIT(2) | ||
58 | #define ATLAS_REG_EC_CALIB_STATUS_HIGH BIT(3) | ||
59 | |||
60 | #define ATLAS_REG_PH_TEMP_DATA 0x0e | ||
53 | #define ATLAS_REG_PH_DATA 0x16 | 61 | #define ATLAS_REG_PH_DATA 0x16 |
54 | 62 | ||
63 | #define ATLAS_REG_EC_PROBE 0x08 | ||
64 | #define ATLAS_REG_EC_TEMP_DATA 0x10 | ||
65 | #define ATLAS_REG_EC_DATA 0x18 | ||
66 | #define ATLAS_REG_TDS_DATA 0x1c | ||
67 | #define ATLAS_REG_PSS_DATA 0x20 | ||
68 | |||
55 | #define ATLAS_PH_INT_TIME_IN_US 450000 | 69 | #define ATLAS_PH_INT_TIME_IN_US 450000 |
70 | #define ATLAS_EC_INT_TIME_IN_US 650000 | ||
71 | |||
72 | enum { | ||
73 | ATLAS_PH_SM, | ||
74 | ATLAS_EC_SM, | ||
75 | }; | ||
56 | 76 | ||
57 | struct atlas_data { | 77 | struct atlas_data { |
58 | struct i2c_client *client; | 78 | struct i2c_client *client; |
59 | struct iio_trigger *trig; | 79 | struct iio_trigger *trig; |
80 | struct atlas_device *chip; | ||
60 | struct regmap *regmap; | 81 | struct regmap *regmap; |
61 | struct irq_work work; | 82 | struct irq_work work; |
62 | 83 | ||
63 | __be32 buffer[4]; /* 32-bit pH data + 32-bit pad + 64-bit timestamp */ | 84 | __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */ |
64 | }; | 85 | }; |
65 | 86 | ||
66 | static const struct regmap_range atlas_volatile_ranges[] = { | 87 | static const struct regmap_range atlas_volatile_ranges[] = { |
67 | regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL), | 88 | regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL), |
68 | regmap_reg_range(ATLAS_REG_PH_DATA, ATLAS_REG_PH_DATA + 4), | 89 | regmap_reg_range(ATLAS_REG_PH_DATA, ATLAS_REG_PH_DATA + 4), |
90 | regmap_reg_range(ATLAS_REG_EC_DATA, ATLAS_REG_PSS_DATA + 4), | ||
69 | }; | 91 | }; |
70 | 92 | ||
71 | static const struct regmap_access_table atlas_volatile_table = { | 93 | static const struct regmap_access_table atlas_volatile_table = { |
@@ -80,13 +102,14 @@ static const struct regmap_config atlas_regmap_config = { | |||
80 | .val_bits = 8, | 102 | .val_bits = 8, |
81 | 103 | ||
82 | .volatile_table = &atlas_volatile_table, | 104 | .volatile_table = &atlas_volatile_table, |
83 | .max_register = ATLAS_REG_PH_DATA + 4, | 105 | .max_register = ATLAS_REG_PSS_DATA + 4, |
84 | .cache_type = REGCACHE_RBTREE, | 106 | .cache_type = REGCACHE_RBTREE, |
85 | }; | 107 | }; |
86 | 108 | ||
87 | static const struct iio_chan_spec atlas_channels[] = { | 109 | static const struct iio_chan_spec atlas_ph_channels[] = { |
88 | { | 110 | { |
89 | .type = IIO_PH, | 111 | .type = IIO_PH, |
112 | .address = ATLAS_REG_PH_DATA, | ||
90 | .info_mask_separate = | 113 | .info_mask_separate = |
91 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 114 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
92 | .scan_index = 0, | 115 | .scan_index = 0, |
@@ -100,7 +123,7 @@ static const struct iio_chan_spec atlas_channels[] = { | |||
100 | IIO_CHAN_SOFT_TIMESTAMP(1), | 123 | IIO_CHAN_SOFT_TIMESTAMP(1), |
101 | { | 124 | { |
102 | .type = IIO_TEMP, | 125 | .type = IIO_TEMP, |
103 | .address = ATLAS_REG_TEMP_DATA, | 126 | .address = ATLAS_REG_PH_TEMP_DATA, |
104 | .info_mask_separate = | 127 | .info_mask_separate = |
105 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 128 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
106 | .output = 1, | 129 | .output = 1, |
@@ -108,6 +131,142 @@ static const struct iio_chan_spec atlas_channels[] = { | |||
108 | }, | 131 | }, |
109 | }; | 132 | }; |
110 | 133 | ||
134 | #define ATLAS_EC_CHANNEL(_idx, _addr) \ | ||
135 | {\ | ||
136 | .type = IIO_CONCENTRATION, \ | ||
137 | .indexed = 1, \ | ||
138 | .channel = _idx, \ | ||
139 | .address = _addr, \ | ||
140 | .info_mask_separate = \ | ||
141 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \ | ||
142 | .scan_index = _idx + 1, \ | ||
143 | .scan_type = { \ | ||
144 | .sign = 'u', \ | ||
145 | .realbits = 32, \ | ||
146 | .storagebits = 32, \ | ||
147 | .endianness = IIO_BE, \ | ||
148 | }, \ | ||
149 | } | ||
150 | |||
151 | static const struct iio_chan_spec atlas_ec_channels[] = { | ||
152 | { | ||
153 | .type = IIO_ELECTRICALCONDUCTIVITY, | ||
154 | .address = ATLAS_REG_EC_DATA, | ||
155 | .info_mask_separate = | ||
156 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | ||
157 | .scan_index = 0, | ||
158 | .scan_type = { | ||
159 | .sign = 'u', | ||
160 | .realbits = 32, | ||
161 | .storagebits = 32, | ||
162 | .endianness = IIO_BE, | ||
163 | }, | ||
164 | }, | ||
165 | ATLAS_EC_CHANNEL(0, ATLAS_REG_TDS_DATA), | ||
166 | ATLAS_EC_CHANNEL(1, ATLAS_REG_PSS_DATA), | ||
167 | IIO_CHAN_SOFT_TIMESTAMP(3), | ||
168 | { | ||
169 | .type = IIO_TEMP, | ||
170 | .address = ATLAS_REG_EC_TEMP_DATA, | ||
171 | .info_mask_separate = | ||
172 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | ||
173 | .output = 1, | ||
174 | .scan_index = -1 | ||
175 | }, | ||
176 | }; | ||
177 | |||
178 | static int atlas_check_ph_calibration(struct atlas_data *data) | ||
179 | { | ||
180 | struct device *dev = &data->client->dev; | ||
181 | int ret; | ||
182 | unsigned int val; | ||
183 | |||
184 | ret = regmap_read(data->regmap, ATLAS_REG_PH_CALIB_STATUS, &val); | ||
185 | if (ret) | ||
186 | return ret; | ||
187 | |||
188 | if (!(val & ATLAS_REG_PH_CALIB_STATUS_MASK)) { | ||
189 | dev_warn(dev, "device has not been calibrated\n"); | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | if (!(val & ATLAS_REG_PH_CALIB_STATUS_LOW)) | ||
194 | dev_warn(dev, "device missing low point calibration\n"); | ||
195 | |||
196 | if (!(val & ATLAS_REG_PH_CALIB_STATUS_MID)) | ||
197 | dev_warn(dev, "device missing mid point calibration\n"); | ||
198 | |||
199 | if (!(val & ATLAS_REG_PH_CALIB_STATUS_HIGH)) | ||
200 | dev_warn(dev, "device missing high point calibration\n"); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static int atlas_check_ec_calibration(struct atlas_data *data) | ||
206 | { | ||
207 | struct device *dev = &data->client->dev; | ||
208 | int ret; | ||
209 | unsigned int val; | ||
210 | |||
211 | ret = regmap_bulk_read(data->regmap, ATLAS_REG_EC_PROBE, &val, 2); | ||
212 | if (ret) | ||
213 | return ret; | ||
214 | |||
215 | dev_info(dev, "probe set to K = %d.%.2d", be16_to_cpu(val) / 100, | ||
216 | be16_to_cpu(val) % 100); | ||
217 | |||
218 | ret = regmap_read(data->regmap, ATLAS_REG_EC_CALIB_STATUS, &val); | ||
219 | if (ret) | ||
220 | return ret; | ||
221 | |||
222 | if (!(val & ATLAS_REG_EC_CALIB_STATUS_MASK)) { | ||
223 | dev_warn(dev, "device has not been calibrated\n"); | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | if (!(val & ATLAS_REG_EC_CALIB_STATUS_DRY)) | ||
228 | dev_warn(dev, "device missing dry point calibration\n"); | ||
229 | |||
230 | if (val & ATLAS_REG_EC_CALIB_STATUS_SINGLE) { | ||
231 | dev_warn(dev, "device using single point calibration\n"); | ||
232 | } else { | ||
233 | if (!(val & ATLAS_REG_EC_CALIB_STATUS_LOW)) | ||
234 | dev_warn(dev, "device missing low point calibration\n"); | ||
235 | |||
236 | if (!(val & ATLAS_REG_EC_CALIB_STATUS_HIGH)) | ||
237 | dev_warn(dev, "device missing high point calibration\n"); | ||
238 | } | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | struct atlas_device { | ||
244 | const struct iio_chan_spec *channels; | ||
245 | int num_channels; | ||
246 | int data_reg; | ||
247 | |||
248 | int (*calibration)(struct atlas_data *data); | ||
249 | int delay; | ||
250 | }; | ||
251 | |||
252 | static struct atlas_device atlas_devices[] = { | ||
253 | [ATLAS_PH_SM] = { | ||
254 | .channels = atlas_ph_channels, | ||
255 | .num_channels = 3, | ||
256 | .data_reg = ATLAS_REG_PH_DATA, | ||
257 | .calibration = &atlas_check_ph_calibration, | ||
258 | .delay = ATLAS_PH_INT_TIME_IN_US, | ||
259 | }, | ||
260 | [ATLAS_EC_SM] = { | ||
261 | .channels = atlas_ec_channels, | ||
262 | .num_channels = 5, | ||
263 | .data_reg = ATLAS_REG_EC_DATA, | ||
264 | .calibration = &atlas_check_ec_calibration, | ||
265 | .delay = ATLAS_EC_INT_TIME_IN_US, | ||
266 | }, | ||
267 | |||
268 | }; | ||
269 | |||
111 | static int atlas_set_powermode(struct atlas_data *data, int on) | 270 | static int atlas_set_powermode(struct atlas_data *data, int on) |
112 | { | 271 | { |
113 | return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on); | 272 | return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on); |
@@ -178,8 +337,9 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private) | |||
178 | struct atlas_data *data = iio_priv(indio_dev); | 337 | struct atlas_data *data = iio_priv(indio_dev); |
179 | int ret; | 338 | int ret; |
180 | 339 | ||
181 | ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA, | 340 | ret = regmap_bulk_read(data->regmap, data->chip->data_reg, |
182 | (u8 *) &data->buffer, sizeof(data->buffer[0])); | 341 | (u8 *) &data->buffer, |
342 | sizeof(__be32) * (data->chip->num_channels - 2)); | ||
183 | 343 | ||
184 | if (!ret) | 344 | if (!ret) |
185 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 345 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, |
@@ -200,7 +360,7 @@ static irqreturn_t atlas_interrupt_handler(int irq, void *private) | |||
200 | return IRQ_HANDLED; | 360 | return IRQ_HANDLED; |
201 | } | 361 | } |
202 | 362 | ||
203 | static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val) | 363 | static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val) |
204 | { | 364 | { |
205 | struct device *dev = &data->client->dev; | 365 | struct device *dev = &data->client->dev; |
206 | int suspended = pm_runtime_suspended(dev); | 366 | int suspended = pm_runtime_suspended(dev); |
@@ -213,11 +373,9 @@ static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val) | |||
213 | } | 373 | } |
214 | 374 | ||
215 | if (suspended) | 375 | if (suspended) |
216 | usleep_range(ATLAS_PH_INT_TIME_IN_US, | 376 | usleep_range(data->chip->delay, data->chip->delay + 100000); |
217 | ATLAS_PH_INT_TIME_IN_US + 100000); | ||
218 | 377 | ||
219 | ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA, | 378 | ret = regmap_bulk_read(data->regmap, reg, (u8 *) val, sizeof(*val)); |
220 | (u8 *) val, sizeof(*val)); | ||
221 | 379 | ||
222 | pm_runtime_mark_last_busy(dev); | 380 | pm_runtime_mark_last_busy(dev); |
223 | pm_runtime_put_autosuspend(dev); | 381 | pm_runtime_put_autosuspend(dev); |
@@ -242,12 +400,15 @@ static int atlas_read_raw(struct iio_dev *indio_dev, | |||
242 | (u8 *) ®, sizeof(reg)); | 400 | (u8 *) ®, sizeof(reg)); |
243 | break; | 401 | break; |
244 | case IIO_PH: | 402 | case IIO_PH: |
403 | case IIO_CONCENTRATION: | ||
404 | case IIO_ELECTRICALCONDUCTIVITY: | ||
245 | mutex_lock(&indio_dev->mlock); | 405 | mutex_lock(&indio_dev->mlock); |
246 | 406 | ||
247 | if (iio_buffer_enabled(indio_dev)) | 407 | if (iio_buffer_enabled(indio_dev)) |
248 | ret = -EBUSY; | 408 | ret = -EBUSY; |
249 | else | 409 | else |
250 | ret = atlas_read_ph_measurement(data, ®); | 410 | ret = atlas_read_measurement(data, |
411 | chan->address, ®); | ||
251 | 412 | ||
252 | mutex_unlock(&indio_dev->mlock); | 413 | mutex_unlock(&indio_dev->mlock); |
253 | break; | 414 | break; |
@@ -271,6 +432,14 @@ static int atlas_read_raw(struct iio_dev *indio_dev, | |||
271 | *val = 1; /* 0.001 */ | 432 | *val = 1; /* 0.001 */ |
272 | *val2 = 1000; | 433 | *val2 = 1000; |
273 | break; | 434 | break; |
435 | case IIO_ELECTRICALCONDUCTIVITY: | ||
436 | *val = 1; /* 0.00001 */ | ||
437 | *val = 100000; | ||
438 | break; | ||
439 | case IIO_CONCENTRATION: | ||
440 | *val = 0; /* 0.000000001 */ | ||
441 | *val2 = 1000; | ||
442 | return IIO_VAL_INT_PLUS_NANO; | ||
274 | default: | 443 | default: |
275 | return -EINVAL; | 444 | return -EINVAL; |
276 | } | 445 | } |
@@ -303,37 +472,26 @@ static const struct iio_info atlas_info = { | |||
303 | .write_raw = atlas_write_raw, | 472 | .write_raw = atlas_write_raw, |
304 | }; | 473 | }; |
305 | 474 | ||
306 | static int atlas_check_calibration(struct atlas_data *data) | 475 | static const struct i2c_device_id atlas_id[] = { |
307 | { | 476 | { "atlas-ph-sm", ATLAS_PH_SM}, |
308 | struct device *dev = &data->client->dev; | 477 | { "atlas-ec-sm", ATLAS_EC_SM}, |
309 | int ret; | 478 | {} |
310 | unsigned int val; | 479 | }; |
311 | 480 | MODULE_DEVICE_TABLE(i2c, atlas_id); | |
312 | ret = regmap_read(data->regmap, ATLAS_REG_CALIB_STATUS, &val); | ||
313 | if (ret) | ||
314 | return ret; | ||
315 | |||
316 | if (!(val & ATLAS_REG_CALIB_STATUS_MASK)) { | ||
317 | dev_warn(dev, "device has not been calibrated\n"); | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | if (!(val & ATLAS_REG_CALIB_STATUS_LOW)) | ||
322 | dev_warn(dev, "device missing low point calibration\n"); | ||
323 | |||
324 | if (!(val & ATLAS_REG_CALIB_STATUS_MID)) | ||
325 | dev_warn(dev, "device missing mid point calibration\n"); | ||
326 | |||
327 | if (!(val & ATLAS_REG_CALIB_STATUS_HIGH)) | ||
328 | dev_warn(dev, "device missing high point calibration\n"); | ||
329 | 481 | ||
330 | return 0; | 482 | static const struct of_device_id atlas_dt_ids[] = { |
483 | { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, }, | ||
484 | { .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, }, | ||
485 | { } | ||
331 | }; | 486 | }; |
487 | MODULE_DEVICE_TABLE(of, atlas_dt_ids); | ||
332 | 488 | ||
333 | static int atlas_probe(struct i2c_client *client, | 489 | static int atlas_probe(struct i2c_client *client, |
334 | const struct i2c_device_id *id) | 490 | const struct i2c_device_id *id) |
335 | { | 491 | { |
336 | struct atlas_data *data; | 492 | struct atlas_data *data; |
493 | struct atlas_device *chip; | ||
494 | const struct of_device_id *of_id; | ||
337 | struct iio_trigger *trig; | 495 | struct iio_trigger *trig; |
338 | struct iio_dev *indio_dev; | 496 | struct iio_dev *indio_dev; |
339 | int ret; | 497 | int ret; |
@@ -342,10 +500,16 @@ static int atlas_probe(struct i2c_client *client, | |||
342 | if (!indio_dev) | 500 | if (!indio_dev) |
343 | return -ENOMEM; | 501 | return -ENOMEM; |
344 | 502 | ||
503 | of_id = of_match_device(atlas_dt_ids, &client->dev); | ||
504 | if (!of_id) | ||
505 | chip = &atlas_devices[id->driver_data]; | ||
506 | else | ||
507 | chip = &atlas_devices[(unsigned long)of_id->data]; | ||
508 | |||
345 | indio_dev->info = &atlas_info; | 509 | indio_dev->info = &atlas_info; |
346 | indio_dev->name = ATLAS_DRV_NAME; | 510 | indio_dev->name = ATLAS_DRV_NAME; |
347 | indio_dev->channels = atlas_channels; | 511 | indio_dev->channels = chip->channels; |
348 | indio_dev->num_channels = ARRAY_SIZE(atlas_channels); | 512 | indio_dev->num_channels = chip->num_channels; |
349 | indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; | 513 | indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; |
350 | indio_dev->dev.parent = &client->dev; | 514 | indio_dev->dev.parent = &client->dev; |
351 | 515 | ||
@@ -358,6 +522,7 @@ static int atlas_probe(struct i2c_client *client, | |||
358 | data = iio_priv(indio_dev); | 522 | data = iio_priv(indio_dev); |
359 | data->client = client; | 523 | data->client = client; |
360 | data->trig = trig; | 524 | data->trig = trig; |
525 | data->chip = chip; | ||
361 | trig->dev.parent = indio_dev->dev.parent; | 526 | trig->dev.parent = indio_dev->dev.parent; |
362 | trig->ops = &atlas_interrupt_trigger_ops; | 527 | trig->ops = &atlas_interrupt_trigger_ops; |
363 | iio_trigger_set_drvdata(trig, indio_dev); | 528 | iio_trigger_set_drvdata(trig, indio_dev); |
@@ -379,7 +544,7 @@ static int atlas_probe(struct i2c_client *client, | |||
379 | return -EINVAL; | 544 | return -EINVAL; |
380 | } | 545 | } |
381 | 546 | ||
382 | ret = atlas_check_calibration(data); | 547 | ret = chip->calibration(data); |
383 | if (ret) | 548 | if (ret) |
384 | return ret; | 549 | return ret; |
385 | 550 | ||
@@ -480,18 +645,6 @@ static const struct dev_pm_ops atlas_pm_ops = { | |||
480 | atlas_runtime_resume, NULL) | 645 | atlas_runtime_resume, NULL) |
481 | }; | 646 | }; |
482 | 647 | ||
483 | static const struct i2c_device_id atlas_id[] = { | ||
484 | { "atlas-ph-sm", 0 }, | ||
485 | {} | ||
486 | }; | ||
487 | MODULE_DEVICE_TABLE(i2c, atlas_id); | ||
488 | |||
489 | static const struct of_device_id atlas_dt_ids[] = { | ||
490 | { .compatible = "atlas,ph-sm" }, | ||
491 | { } | ||
492 | }; | ||
493 | MODULE_DEVICE_TABLE(of, atlas_dt_ids); | ||
494 | |||
495 | static struct i2c_driver atlas_driver = { | 648 | static struct i2c_driver atlas_driver = { |
496 | .driver = { | 649 | .driver = { |
497 | .name = ATLAS_DRV_NAME, | 650 | .name = ATLAS_DRV_NAME, |
diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c index c55898543a47..4ccc438afb5f 100644 --- a/drivers/iio/common/st_sensors/st_sensors_buffer.c +++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/iio/common/st_sensors.h> | 22 | #include <linux/iio/common/st_sensors.h> |
23 | 23 | ||
24 | 24 | ||
25 | int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) | 25 | static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) |
26 | { | 26 | { |
27 | int i, len; | 27 | int i, len; |
28 | int total = 0; | 28 | int total = 0; |
@@ -49,7 +49,6 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) | |||
49 | 49 | ||
50 | return total; | 50 | return total; |
51 | } | 51 | } |
52 | EXPORT_SYMBOL(st_sensors_get_buffer_element); | ||
53 | 52 | ||
54 | irqreturn_t st_sensors_trigger_handler(int irq, void *p) | 53 | irqreturn_t st_sensors_trigger_handler(int irq, void *p) |
55 | { | 54 | { |
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index dffe00692169..00078b5fe33c 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c | |||
@@ -228,7 +228,7 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable) | |||
228 | } | 228 | } |
229 | EXPORT_SYMBOL(st_sensors_set_axis_enable); | 229 | EXPORT_SYMBOL(st_sensors_set_axis_enable); |
230 | 230 | ||
231 | void st_sensors_power_enable(struct iio_dev *indio_dev) | 231 | int st_sensors_power_enable(struct iio_dev *indio_dev) |
232 | { | 232 | { |
233 | struct st_sensor_data *pdata = iio_priv(indio_dev); | 233 | struct st_sensor_data *pdata = iio_priv(indio_dev); |
234 | int err; | 234 | int err; |
@@ -237,18 +237,37 @@ void st_sensors_power_enable(struct iio_dev *indio_dev) | |||
237 | pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd"); | 237 | pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd"); |
238 | if (!IS_ERR(pdata->vdd)) { | 238 | if (!IS_ERR(pdata->vdd)) { |
239 | err = regulator_enable(pdata->vdd); | 239 | err = regulator_enable(pdata->vdd); |
240 | if (err != 0) | 240 | if (err != 0) { |
241 | dev_warn(&indio_dev->dev, | 241 | dev_warn(&indio_dev->dev, |
242 | "Failed to enable specified Vdd supply\n"); | 242 | "Failed to enable specified Vdd supply\n"); |
243 | return err; | ||
244 | } | ||
245 | } else { | ||
246 | err = PTR_ERR(pdata->vdd); | ||
247 | if (err != -ENODEV) | ||
248 | return err; | ||
243 | } | 249 | } |
244 | 250 | ||
245 | pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio"); | 251 | pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio"); |
246 | if (!IS_ERR(pdata->vdd_io)) { | 252 | if (!IS_ERR(pdata->vdd_io)) { |
247 | err = regulator_enable(pdata->vdd_io); | 253 | err = regulator_enable(pdata->vdd_io); |
248 | if (err != 0) | 254 | if (err != 0) { |
249 | dev_warn(&indio_dev->dev, | 255 | dev_warn(&indio_dev->dev, |
250 | "Failed to enable specified Vdd_IO supply\n"); | 256 | "Failed to enable specified Vdd_IO supply\n"); |
257 | goto st_sensors_disable_vdd; | ||
258 | } | ||
259 | } else { | ||
260 | err = PTR_ERR(pdata->vdd_io); | ||
261 | if (err != -ENODEV) | ||
262 | goto st_sensors_disable_vdd; | ||
251 | } | 263 | } |
264 | |||
265 | return 0; | ||
266 | |||
267 | st_sensors_disable_vdd: | ||
268 | if (!IS_ERR_OR_NULL(pdata->vdd)) | ||
269 | regulator_disable(pdata->vdd); | ||
270 | return err; | ||
252 | } | 271 | } |
253 | EXPORT_SYMBOL(st_sensors_power_enable); | 272 | EXPORT_SYMBOL(st_sensors_power_enable); |
254 | 273 | ||
@@ -256,10 +275,10 @@ void st_sensors_power_disable(struct iio_dev *indio_dev) | |||
256 | { | 275 | { |
257 | struct st_sensor_data *pdata = iio_priv(indio_dev); | 276 | struct st_sensor_data *pdata = iio_priv(indio_dev); |
258 | 277 | ||
259 | if (!IS_ERR(pdata->vdd)) | 278 | if (!IS_ERR_OR_NULL(pdata->vdd)) |
260 | regulator_disable(pdata->vdd); | 279 | regulator_disable(pdata->vdd); |
261 | 280 | ||
262 | if (!IS_ERR(pdata->vdd_io)) | 281 | if (!IS_ERR_OR_NULL(pdata->vdd_io)) |
263 | regulator_disable(pdata->vdd_io); | 282 | regulator_disable(pdata->vdd_io); |
264 | } | 283 | } |
265 | EXPORT_SYMBOL(st_sensors_power_disable); | 284 | EXPORT_SYMBOL(st_sensors_power_disable); |
diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c index 98cfee296d46..b43aa36031f8 100644 --- a/drivers/iio/common/st_sensors/st_sensors_i2c.c +++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c | |||
@@ -48,8 +48,8 @@ static int st_sensors_i2c_read_multiple_byte( | |||
48 | if (multiread_bit) | 48 | if (multiread_bit) |
49 | reg_addr |= ST_SENSORS_I2C_MULTIREAD; | 49 | reg_addr |= ST_SENSORS_I2C_MULTIREAD; |
50 | 50 | ||
51 | return i2c_smbus_read_i2c_block_data(to_i2c_client(dev), | 51 | return i2c_smbus_read_i2c_block_data_or_emulated(to_i2c_client(dev), |
52 | reg_addr, len, data); | 52 | reg_addr, len, data); |
53 | } | 53 | } |
54 | 54 | ||
55 | static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb, | 55 | static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb, |
diff --git a/drivers/iio/dummy/Kconfig b/drivers/iio/dummy/Kconfig index 71805ced1aae..aa5824d96a43 100644 --- a/drivers/iio/dummy/Kconfig +++ b/drivers/iio/dummy/Kconfig | |||
@@ -10,6 +10,7 @@ config IIO_DUMMY_EVGEN | |||
10 | 10 | ||
11 | config IIO_SIMPLE_DUMMY | 11 | config IIO_SIMPLE_DUMMY |
12 | tristate "An example driver with no hardware requirements" | 12 | tristate "An example driver with no hardware requirements" |
13 | depends on IIO_SW_DEVICE | ||
13 | help | 14 | help |
14 | Driver intended mainly as documentation for how to write | 15 | Driver intended mainly as documentation for how to write |
15 | a driver. May also be useful for testing userspace code | 16 | a driver. May also be useful for testing userspace code |
diff --git a/drivers/iio/dummy/iio_simple_dummy.c b/drivers/iio/dummy/iio_simple_dummy.c index 43fe4ba7d0dc..ad3410e528b6 100644 --- a/drivers/iio/dummy/iio_simple_dummy.c +++ b/drivers/iio/dummy/iio_simple_dummy.c | |||
@@ -17,26 +17,18 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/string.h> | ||
20 | 21 | ||
21 | #include <linux/iio/iio.h> | 22 | #include <linux/iio/iio.h> |
22 | #include <linux/iio/sysfs.h> | 23 | #include <linux/iio/sysfs.h> |
23 | #include <linux/iio/events.h> | 24 | #include <linux/iio/events.h> |
24 | #include <linux/iio/buffer.h> | 25 | #include <linux/iio/buffer.h> |
26 | #include <linux/iio/sw_device.h> | ||
25 | #include "iio_simple_dummy.h" | 27 | #include "iio_simple_dummy.h" |
26 | 28 | ||
27 | /* | 29 | static struct config_item_type iio_dummy_type = { |
28 | * A few elements needed to fake a bus for this driver | 30 | .ct_owner = THIS_MODULE, |
29 | * Note instances parameter controls how many of these | 31 | }; |
30 | * dummy devices are registered. | ||
31 | */ | ||
32 | static unsigned instances = 1; | ||
33 | module_param(instances, uint, 0); | ||
34 | |||
35 | /* Pointer array used to fake bus elements */ | ||
36 | static struct iio_dev **iio_dummy_devs; | ||
37 | |||
38 | /* Fake a name for the part number, usually obtained from the id table */ | ||
39 | static const char *iio_dummy_part_number = "iio_dummy_part_no"; | ||
40 | 32 | ||
41 | /** | 33 | /** |
42 | * struct iio_dummy_accel_calibscale - realworld to register mapping | 34 | * struct iio_dummy_accel_calibscale - realworld to register mapping |
@@ -572,12 +564,18 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev) | |||
572 | * const struct i2c_device_id *id) | 564 | * const struct i2c_device_id *id) |
573 | * SPI: iio_dummy_probe(struct spi_device *spi) | 565 | * SPI: iio_dummy_probe(struct spi_device *spi) |
574 | */ | 566 | */ |
575 | static int iio_dummy_probe(int index) | 567 | static struct iio_sw_device *iio_dummy_probe(const char *name) |
576 | { | 568 | { |
577 | int ret; | 569 | int ret; |
578 | struct iio_dev *indio_dev; | 570 | struct iio_dev *indio_dev; |
579 | struct iio_dummy_state *st; | 571 | struct iio_dummy_state *st; |
572 | struct iio_sw_device *swd; | ||
580 | 573 | ||
574 | swd = kzalloc(sizeof(*swd), GFP_KERNEL); | ||
575 | if (!swd) { | ||
576 | ret = -ENOMEM; | ||
577 | goto error_kzalloc; | ||
578 | } | ||
581 | /* | 579 | /* |
582 | * Allocate an IIO device. | 580 | * Allocate an IIO device. |
583 | * | 581 | * |
@@ -608,7 +606,7 @@ static int iio_dummy_probe(int index) | |||
608 | * i2c_set_clientdata(client, indio_dev); | 606 | * i2c_set_clientdata(client, indio_dev); |
609 | * spi_set_drvdata(spi, indio_dev); | 607 | * spi_set_drvdata(spi, indio_dev); |
610 | */ | 608 | */ |
611 | iio_dummy_devs[index] = indio_dev; | 609 | swd->device = indio_dev; |
612 | 610 | ||
613 | /* | 611 | /* |
614 | * Set the device name. | 612 | * Set the device name. |
@@ -619,7 +617,7 @@ static int iio_dummy_probe(int index) | |||
619 | * indio_dev->name = id->name; | 617 | * indio_dev->name = id->name; |
620 | * indio_dev->name = spi_get_device_id(spi)->name; | 618 | * indio_dev->name = spi_get_device_id(spi)->name; |
621 | */ | 619 | */ |
622 | indio_dev->name = iio_dummy_part_number; | 620 | indio_dev->name = kstrdup(name, GFP_KERNEL); |
623 | 621 | ||
624 | /* Provide description of available channels */ | 622 | /* Provide description of available channels */ |
625 | indio_dev->channels = iio_dummy_channels; | 623 | indio_dev->channels = iio_dummy_channels; |
@@ -646,7 +644,9 @@ static int iio_dummy_probe(int index) | |||
646 | if (ret < 0) | 644 | if (ret < 0) |
647 | goto error_unconfigure_buffer; | 645 | goto error_unconfigure_buffer; |
648 | 646 | ||
649 | return 0; | 647 | iio_swd_group_init_type_name(swd, name, &iio_dummy_type); |
648 | |||
649 | return swd; | ||
650 | error_unconfigure_buffer: | 650 | error_unconfigure_buffer: |
651 | iio_simple_dummy_unconfigure_buffer(indio_dev); | 651 | iio_simple_dummy_unconfigure_buffer(indio_dev); |
652 | error_unregister_events: | 652 | error_unregister_events: |
@@ -654,16 +654,18 @@ error_unregister_events: | |||
654 | error_free_device: | 654 | error_free_device: |
655 | iio_device_free(indio_dev); | 655 | iio_device_free(indio_dev); |
656 | error_ret: | 656 | error_ret: |
657 | return ret; | 657 | kfree(swd); |
658 | error_kzalloc: | ||
659 | return ERR_PTR(ret); | ||
658 | } | 660 | } |
659 | 661 | ||
660 | /** | 662 | /** |
661 | * iio_dummy_remove() - device instance removal function | 663 | * iio_dummy_remove() - device instance removal function |
662 | * @index: device index. | 664 | * @swd: pointer to software IIO device abstraction |
663 | * | 665 | * |
664 | * Parameters follow those of iio_dummy_probe for buses. | 666 | * Parameters follow those of iio_dummy_probe for buses. |
665 | */ | 667 | */ |
666 | static void iio_dummy_remove(int index) | 668 | static int iio_dummy_remove(struct iio_sw_device *swd) |
667 | { | 669 | { |
668 | /* | 670 | /* |
669 | * Get a pointer to the device instance iio_dev structure | 671 | * Get a pointer to the device instance iio_dev structure |
@@ -671,7 +673,7 @@ static void iio_dummy_remove(int index) | |||
671 | * struct iio_dev *indio_dev = i2c_get_clientdata(client); | 673 | * struct iio_dev *indio_dev = i2c_get_clientdata(client); |
672 | * struct iio_dev *indio_dev = spi_get_drvdata(spi); | 674 | * struct iio_dev *indio_dev = spi_get_drvdata(spi); |
673 | */ | 675 | */ |
674 | struct iio_dev *indio_dev = iio_dummy_devs[index]; | 676 | struct iio_dev *indio_dev = swd->device; |
675 | 677 | ||
676 | /* Unregister the device */ | 678 | /* Unregister the device */ |
677 | iio_device_unregister(indio_dev); | 679 | iio_device_unregister(indio_dev); |
@@ -684,11 +686,13 @@ static void iio_dummy_remove(int index) | |||
684 | iio_simple_dummy_events_unregister(indio_dev); | 686 | iio_simple_dummy_events_unregister(indio_dev); |
685 | 687 | ||
686 | /* Free all structures */ | 688 | /* Free all structures */ |
689 | kfree(indio_dev->name); | ||
687 | iio_device_free(indio_dev); | 690 | iio_device_free(indio_dev); |
688 | } | ||
689 | 691 | ||
692 | return 0; | ||
693 | } | ||
690 | /** | 694 | /** |
691 | * iio_dummy_init() - device driver registration | 695 | * module_iio_sw_device_driver() - device driver registration |
692 | * | 696 | * |
693 | * Varies depending on bus type of the device. As there is no device | 697 | * Varies depending on bus type of the device. As there is no device |
694 | * here, call probe directly. For information on device registration | 698 | * here, call probe directly. For information on device registration |
@@ -697,50 +701,18 @@ static void iio_dummy_remove(int index) | |||
697 | * spi: | 701 | * spi: |
698 | * Documentation/spi/spi-summary | 702 | * Documentation/spi/spi-summary |
699 | */ | 703 | */ |
700 | static __init int iio_dummy_init(void) | 704 | static const struct iio_sw_device_ops iio_dummy_device_ops = { |
701 | { | 705 | .probe = iio_dummy_probe, |
702 | int i, ret; | 706 | .remove = iio_dummy_remove, |
703 | 707 | }; | |
704 | if (instances > 10) { | ||
705 | instances = 1; | ||
706 | return -EINVAL; | ||
707 | } | ||
708 | |||
709 | /* Fake a bus */ | ||
710 | iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs), | ||
711 | GFP_KERNEL); | ||
712 | /* Here we have no actual device so call probe */ | ||
713 | for (i = 0; i < instances; i++) { | ||
714 | ret = iio_dummy_probe(i); | ||
715 | if (ret < 0) | ||
716 | goto error_remove_devs; | ||
717 | } | ||
718 | return 0; | ||
719 | |||
720 | error_remove_devs: | ||
721 | while (i--) | ||
722 | iio_dummy_remove(i); | ||
723 | |||
724 | kfree(iio_dummy_devs); | ||
725 | return ret; | ||
726 | } | ||
727 | module_init(iio_dummy_init); | ||
728 | 708 | ||
729 | /** | 709 | static struct iio_sw_device_type iio_dummy_device = { |
730 | * iio_dummy_exit() - device driver removal | 710 | .name = "dummy", |
731 | * | 711 | .owner = THIS_MODULE, |
732 | * Varies depending on bus type of the device. | 712 | .ops = &iio_dummy_device_ops, |
733 | * As there is no device here, call remove directly. | 713 | }; |
734 | */ | ||
735 | static __exit void iio_dummy_exit(void) | ||
736 | { | ||
737 | int i; | ||
738 | 714 | ||
739 | for (i = 0; i < instances; i++) | 715 | module_iio_sw_device_driver(iio_dummy_device); |
740 | iio_dummy_remove(i); | ||
741 | kfree(iio_dummy_devs); | ||
742 | } | ||
743 | module_exit(iio_dummy_exit); | ||
744 | 716 | ||
745 | MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); | 717 | MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); |
746 | MODULE_DESCRIPTION("IIO dummy driver"); | 718 | MODULE_DESCRIPTION("IIO dummy driver"); |
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 52a3c87c375c..ae1377da9a0b 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c | |||
@@ -425,13 +425,15 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) | |||
425 | indio_dev->info = &gyro_info; | 425 | indio_dev->info = &gyro_info; |
426 | mutex_init(&gdata->tb.buf_lock); | 426 | mutex_init(&gdata->tb.buf_lock); |
427 | 427 | ||
428 | st_sensors_power_enable(indio_dev); | 428 | err = st_sensors_power_enable(indio_dev); |
429 | if (err) | ||
430 | return err; | ||
429 | 431 | ||
430 | err = st_sensors_check_device_support(indio_dev, | 432 | err = st_sensors_check_device_support(indio_dev, |
431 | ARRAY_SIZE(st_gyro_sensors_settings), | 433 | ARRAY_SIZE(st_gyro_sensors_settings), |
432 | st_gyro_sensors_settings); | 434 | st_gyro_sensors_settings); |
433 | if (err < 0) | 435 | if (err < 0) |
434 | return err; | 436 | goto st_gyro_power_off; |
435 | 437 | ||
436 | gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS; | 438 | gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS; |
437 | gdata->multiread_bit = gdata->sensor_settings->multi_read_bit; | 439 | gdata->multiread_bit = gdata->sensor_settings->multi_read_bit; |
@@ -445,11 +447,11 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) | |||
445 | err = st_sensors_init_sensor(indio_dev, | 447 | err = st_sensors_init_sensor(indio_dev, |
446 | (struct st_sensors_platform_data *)&gyro_pdata); | 448 | (struct st_sensors_platform_data *)&gyro_pdata); |
447 | if (err < 0) | 449 | if (err < 0) |
448 | return err; | 450 | goto st_gyro_power_off; |
449 | 451 | ||
450 | err = st_gyro_allocate_ring(indio_dev); | 452 | err = st_gyro_allocate_ring(indio_dev); |
451 | if (err < 0) | 453 | if (err < 0) |
452 | return err; | 454 | goto st_gyro_power_off; |
453 | 455 | ||
454 | if (irq > 0) { | 456 | if (irq > 0) { |
455 | err = st_sensors_allocate_trigger(indio_dev, | 457 | err = st_sensors_allocate_trigger(indio_dev, |
@@ -472,6 +474,8 @@ st_gyro_device_register_error: | |||
472 | st_sensors_deallocate_trigger(indio_dev); | 474 | st_sensors_deallocate_trigger(indio_dev); |
473 | st_gyro_probe_trigger_error: | 475 | st_gyro_probe_trigger_error: |
474 | st_gyro_deallocate_ring(indio_dev); | 476 | st_gyro_deallocate_ring(indio_dev); |
477 | st_gyro_power_off: | ||
478 | st_sensors_power_disable(indio_dev); | ||
475 | 479 | ||
476 | return err; | 480 | return err; |
477 | } | 481 | } |
diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c index 88e43f87b926..9a081465c42f 100644 --- a/drivers/iio/health/afe4403.c +++ b/drivers/iio/health/afe4403.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * AFE4403 Heart Rate Monitors and Low-Cost Pulse Oximeters | 2 | * AFE4403 Heart Rate Monitors and Low-Cost Pulse Oximeters |
3 | * | 3 | * |
4 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ | 4 | * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ |
5 | * Andrew F. Davis <afd@ti.com> | 5 | * Andrew F. Davis <afd@ti.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -39,127 +39,90 @@ | |||
39 | #define AFE4403_TIAGAIN 0x20 | 39 | #define AFE4403_TIAGAIN 0x20 |
40 | #define AFE4403_TIA_AMB_GAIN 0x21 | 40 | #define AFE4403_TIA_AMB_GAIN 0x21 |
41 | 41 | ||
42 | /* AFE4403 GAIN register fields */ | 42 | enum afe4403_fields { |
43 | #define AFE4403_TIAGAIN_RES_MASK GENMASK(2, 0) | 43 | /* Gains */ |
44 | #define AFE4403_TIAGAIN_RES_SHIFT 0 | 44 | F_RF_LED1, F_CF_LED1, |
45 | #define AFE4403_TIAGAIN_CAP_MASK GENMASK(7, 3) | 45 | F_RF_LED, F_CF_LED, |
46 | #define AFE4403_TIAGAIN_CAP_SHIFT 3 | 46 | |
47 | 47 | /* LED Current */ | |
48 | /* AFE4403 LEDCNTRL register fields */ | 48 | F_ILED1, F_ILED2, |
49 | #define AFE440X_LEDCNTRL_LED1_MASK GENMASK(15, 8) | 49 | |
50 | #define AFE440X_LEDCNTRL_LED1_SHIFT 8 | 50 | /* sentinel */ |
51 | #define AFE440X_LEDCNTRL_LED2_MASK GENMASK(7, 0) | 51 | F_MAX_FIELDS |
52 | #define AFE440X_LEDCNTRL_LED2_SHIFT 0 | 52 | }; |
53 | #define AFE440X_LEDCNTRL_LED_RANGE_MASK GENMASK(17, 16) | 53 | |
54 | #define AFE440X_LEDCNTRL_LED_RANGE_SHIFT 16 | 54 | static const struct reg_field afe4403_reg_fields[] = { |
55 | 55 | /* Gains */ | |
56 | /* AFE4403 CONTROL2 register fields */ | 56 | [F_RF_LED1] = REG_FIELD(AFE4403_TIAGAIN, 0, 2), |
57 | #define AFE440X_CONTROL2_PWR_DWN_TX BIT(2) | 57 | [F_CF_LED1] = REG_FIELD(AFE4403_TIAGAIN, 3, 7), |
58 | #define AFE440X_CONTROL2_EN_SLOW_DIAG BIT(8) | 58 | [F_RF_LED] = REG_FIELD(AFE4403_TIA_AMB_GAIN, 0, 2), |
59 | #define AFE440X_CONTROL2_DIAG_OUT_TRI BIT(10) | 59 | [F_CF_LED] = REG_FIELD(AFE4403_TIA_AMB_GAIN, 3, 7), |
60 | #define AFE440X_CONTROL2_TX_BRDG_MOD BIT(11) | 60 | /* LED Current */ |
61 | #define AFE440X_CONTROL2_TX_REF_MASK GENMASK(18, 17) | 61 | [F_ILED1] = REG_FIELD(AFE440X_LEDCNTRL, 0, 7), |
62 | #define AFE440X_CONTROL2_TX_REF_SHIFT 17 | 62 | [F_ILED2] = REG_FIELD(AFE440X_LEDCNTRL, 8, 15), |
63 | 63 | }; | |
64 | /* AFE4404 NULL fields */ | ||
65 | #define NULL_MASK 0 | ||
66 | #define NULL_SHIFT 0 | ||
67 | |||
68 | /* AFE4403 LEDCNTRL values */ | ||
69 | #define AFE440X_LEDCNTRL_RANGE_TX_HALF 0x1 | ||
70 | #define AFE440X_LEDCNTRL_RANGE_TX_FULL 0x2 | ||
71 | #define AFE440X_LEDCNTRL_RANGE_TX_OFF 0x3 | ||
72 | |||
73 | /* AFE4403 CONTROL2 values */ | ||
74 | #define AFE440X_CONTROL2_TX_REF_025 0x0 | ||
75 | #define AFE440X_CONTROL2_TX_REF_050 0x1 | ||
76 | #define AFE440X_CONTROL2_TX_REF_100 0x2 | ||
77 | #define AFE440X_CONTROL2_TX_REF_075 0x3 | ||
78 | |||
79 | /* AFE4403 CONTROL3 values */ | ||
80 | #define AFE440X_CONTROL3_CLK_DIV_2 0x0 | ||
81 | #define AFE440X_CONTROL3_CLK_DIV_4 0x2 | ||
82 | #define AFE440X_CONTROL3_CLK_DIV_6 0x3 | ||
83 | #define AFE440X_CONTROL3_CLK_DIV_8 0x4 | ||
84 | #define AFE440X_CONTROL3_CLK_DIV_12 0x5 | ||
85 | #define AFE440X_CONTROL3_CLK_DIV_1 0x7 | ||
86 | |||
87 | /* AFE4403 TIAGAIN_CAP values */ | ||
88 | #define AFE4403_TIAGAIN_CAP_5_P 0x0 | ||
89 | #define AFE4403_TIAGAIN_CAP_10_P 0x1 | ||
90 | #define AFE4403_TIAGAIN_CAP_20_P 0x2 | ||
91 | #define AFE4403_TIAGAIN_CAP_30_P 0x3 | ||
92 | #define AFE4403_TIAGAIN_CAP_55_P 0x8 | ||
93 | #define AFE4403_TIAGAIN_CAP_155_P 0x10 | ||
94 | |||
95 | /* AFE4403 TIAGAIN_RES values */ | ||
96 | #define AFE4403_TIAGAIN_RES_500_K 0x0 | ||
97 | #define AFE4403_TIAGAIN_RES_250_K 0x1 | ||
98 | #define AFE4403_TIAGAIN_RES_100_K 0x2 | ||
99 | #define AFE4403_TIAGAIN_RES_50_K 0x3 | ||
100 | #define AFE4403_TIAGAIN_RES_25_K 0x4 | ||
101 | #define AFE4403_TIAGAIN_RES_10_K 0x5 | ||
102 | #define AFE4403_TIAGAIN_RES_1_M 0x6 | ||
103 | #define AFE4403_TIAGAIN_RES_NONE 0x7 | ||
104 | 64 | ||
105 | /** | 65 | /** |
106 | * struct afe4403_data | 66 | * struct afe4403_data - AFE4403 device instance data |
107 | * @dev - Device structure | 67 | * @dev: Device structure |
108 | * @spi - SPI device handle | 68 | * @spi: SPI device handle |
109 | * @regmap - Register map of the device | 69 | * @regmap: Register map of the device |
110 | * @regulator - Pointer to the regulator for the IC | 70 | * @fields: Register fields of the device |
111 | * @trig - IIO trigger for this device | 71 | * @regulator: Pointer to the regulator for the IC |
112 | * @irq - ADC_RDY line interrupt number | 72 | * @trig: IIO trigger for this device |
73 | * @irq: ADC_RDY line interrupt number | ||
113 | */ | 74 | */ |
114 | struct afe4403_data { | 75 | struct afe4403_data { |
115 | struct device *dev; | 76 | struct device *dev; |
116 | struct spi_device *spi; | 77 | struct spi_device *spi; |
117 | struct regmap *regmap; | 78 | struct regmap *regmap; |
79 | struct regmap_field *fields[F_MAX_FIELDS]; | ||
118 | struct regulator *regulator; | 80 | struct regulator *regulator; |
119 | struct iio_trigger *trig; | 81 | struct iio_trigger *trig; |
120 | int irq; | 82 | int irq; |
121 | }; | 83 | }; |
122 | 84 | ||
123 | enum afe4403_chan_id { | 85 | enum afe4403_chan_id { |
86 | LED2 = 1, | ||
87 | ALED2, | ||
124 | LED1, | 88 | LED1, |
125 | ALED1, | 89 | ALED1, |
126 | LED2, | ||
127 | ALED2, | ||
128 | LED1_ALED1, | ||
129 | LED2_ALED2, | 90 | LED2_ALED2, |
130 | ILED1, | 91 | LED1_ALED1, |
131 | ILED2, | ||
132 | }; | 92 | }; |
133 | 93 | ||
134 | static const struct afe440x_reg_info afe4403_reg_info[] = { | 94 | static const unsigned int afe4403_channel_values[] = { |
135 | [LED1] = AFE440X_REG_INFO(AFE440X_LED1VAL, 0, NULL), | 95 | [LED2] = AFE440X_LED2VAL, |
136 | [ALED1] = AFE440X_REG_INFO(AFE440X_ALED1VAL, 0, NULL), | 96 | [ALED2] = AFE440X_ALED2VAL, |
137 | [LED2] = AFE440X_REG_INFO(AFE440X_LED2VAL, 0, NULL), | 97 | [LED1] = AFE440X_LED1VAL, |
138 | [ALED2] = AFE440X_REG_INFO(AFE440X_ALED2VAL, 0, NULL), | 98 | [ALED1] = AFE440X_ALED1VAL, |
139 | [LED1_ALED1] = AFE440X_REG_INFO(AFE440X_LED1_ALED1VAL, 0, NULL), | 99 | [LED2_ALED2] = AFE440X_LED2_ALED2VAL, |
140 | [LED2_ALED2] = AFE440X_REG_INFO(AFE440X_LED2_ALED2VAL, 0, NULL), | 100 | [LED1_ALED1] = AFE440X_LED1_ALED1VAL, |
141 | [ILED1] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE440X_LEDCNTRL_LED1), | 101 | }; |
142 | [ILED2] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE440X_LEDCNTRL_LED2), | 102 | |
103 | static const unsigned int afe4403_channel_leds[] = { | ||
104 | [LED2] = F_ILED2, | ||
105 | [LED1] = F_ILED1, | ||
143 | }; | 106 | }; |
144 | 107 | ||
145 | static const struct iio_chan_spec afe4403_channels[] = { | 108 | static const struct iio_chan_spec afe4403_channels[] = { |
146 | /* ADC values */ | 109 | /* ADC values */ |
147 | AFE440X_INTENSITY_CHAN(LED1, "led1", 0), | 110 | AFE440X_INTENSITY_CHAN(LED2, 0), |
148 | AFE440X_INTENSITY_CHAN(ALED1, "led1_ambient", 0), | 111 | AFE440X_INTENSITY_CHAN(ALED2, 0), |
149 | AFE440X_INTENSITY_CHAN(LED2, "led2", 0), | 112 | AFE440X_INTENSITY_CHAN(LED1, 0), |
150 | AFE440X_INTENSITY_CHAN(ALED2, "led2_ambient", 0), | 113 | AFE440X_INTENSITY_CHAN(ALED1, 0), |
151 | AFE440X_INTENSITY_CHAN(LED1_ALED1, "led1-led1_ambient", 0), | 114 | AFE440X_INTENSITY_CHAN(LED2_ALED2, 0), |
152 | AFE440X_INTENSITY_CHAN(LED2_ALED2, "led2-led2_ambient", 0), | 115 | AFE440X_INTENSITY_CHAN(LED1_ALED1, 0), |
153 | /* LED current */ | 116 | /* LED current */ |
154 | AFE440X_CURRENT_CHAN(ILED1, "led1"), | 117 | AFE440X_CURRENT_CHAN(LED2), |
155 | AFE440X_CURRENT_CHAN(ILED2, "led2"), | 118 | AFE440X_CURRENT_CHAN(LED1), |
156 | }; | 119 | }; |
157 | 120 | ||
158 | static const struct afe440x_val_table afe4403_res_table[] = { | 121 | static const struct afe440x_val_table afe4403_res_table[] = { |
159 | { 500000 }, { 250000 }, { 100000 }, { 50000 }, | 122 | { 500000 }, { 250000 }, { 100000 }, { 50000 }, |
160 | { 25000 }, { 10000 }, { 1000000 }, { 0 }, | 123 | { 25000 }, { 10000 }, { 1000000 }, { 0 }, |
161 | }; | 124 | }; |
162 | AFE440X_TABLE_ATTR(tia_resistance_available, afe4403_res_table); | 125 | AFE440X_TABLE_ATTR(in_intensity_resistance_available, afe4403_res_table); |
163 | 126 | ||
164 | static const struct afe440x_val_table afe4403_cap_table[] = { | 127 | static const struct afe440x_val_table afe4403_cap_table[] = { |
165 | { 0, 5000 }, { 0, 10000 }, { 0, 20000 }, { 0, 25000 }, | 128 | { 0, 5000 }, { 0, 10000 }, { 0, 20000 }, { 0, 25000 }, |
@@ -171,7 +134,7 @@ static const struct afe440x_val_table afe4403_cap_table[] = { | |||
171 | { 0, 205000 }, { 0, 210000 }, { 0, 220000 }, { 0, 225000 }, | 134 | { 0, 205000 }, { 0, 210000 }, { 0, 220000 }, { 0, 225000 }, |
172 | { 0, 230000 }, { 0, 235000 }, { 0, 245000 }, { 0, 250000 }, | 135 | { 0, 230000 }, { 0, 235000 }, { 0, 245000 }, { 0, 250000 }, |
173 | }; | 136 | }; |
174 | AFE440X_TABLE_ATTR(tia_capacitance_available, afe4403_cap_table); | 137 | AFE440X_TABLE_ATTR(in_intensity_capacitance_available, afe4403_cap_table); |
175 | 138 | ||
176 | static ssize_t afe440x_show_register(struct device *dev, | 139 | static ssize_t afe440x_show_register(struct device *dev, |
177 | struct device_attribute *attr, | 140 | struct device_attribute *attr, |
@@ -180,38 +143,21 @@ static ssize_t afe440x_show_register(struct device *dev, | |||
180 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 143 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
181 | struct afe4403_data *afe = iio_priv(indio_dev); | 144 | struct afe4403_data *afe = iio_priv(indio_dev); |
182 | struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); | 145 | struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); |
183 | unsigned int reg_val, type; | 146 | unsigned int reg_val; |
184 | int vals[2]; | 147 | int vals[2]; |
185 | int ret, val_len; | 148 | int ret; |
186 | 149 | ||
187 | ret = regmap_read(afe->regmap, afe440x_attr->reg, ®_val); | 150 | ret = regmap_field_read(afe->fields[afe440x_attr->field], ®_val); |
188 | if (ret) | 151 | if (ret) |
189 | return ret; | 152 | return ret; |
190 | 153 | ||
191 | reg_val &= afe440x_attr->mask; | 154 | if (reg_val >= afe440x_attr->table_size) |
192 | reg_val >>= afe440x_attr->shift; | ||
193 | |||
194 | switch (afe440x_attr->type) { | ||
195 | case SIMPLE: | ||
196 | type = IIO_VAL_INT; | ||
197 | val_len = 1; | ||
198 | vals[0] = reg_val; | ||
199 | break; | ||
200 | case RESISTANCE: | ||
201 | case CAPACITANCE: | ||
202 | type = IIO_VAL_INT_PLUS_MICRO; | ||
203 | val_len = 2; | ||
204 | if (reg_val < afe440x_attr->table_size) { | ||
205 | vals[0] = afe440x_attr->val_table[reg_val].integer; | ||
206 | vals[1] = afe440x_attr->val_table[reg_val].fract; | ||
207 | break; | ||
208 | } | ||
209 | return -EINVAL; | ||
210 | default: | ||
211 | return -EINVAL; | 155 | return -EINVAL; |
212 | } | ||
213 | 156 | ||
214 | return iio_format_value(buf, type, val_len, vals); | 157 | vals[0] = afe440x_attr->val_table[reg_val].integer; |
158 | vals[1] = afe440x_attr->val_table[reg_val].fract; | ||
159 | |||
160 | return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, 2, vals); | ||
215 | } | 161 | } |
216 | 162 | ||
217 | static ssize_t afe440x_store_register(struct device *dev, | 163 | static ssize_t afe440x_store_register(struct device *dev, |
@@ -227,48 +173,43 @@ static ssize_t afe440x_store_register(struct device *dev, | |||
227 | if (ret) | 173 | if (ret) |
228 | return ret; | 174 | return ret; |
229 | 175 | ||
230 | switch (afe440x_attr->type) { | 176 | for (val = 0; val < afe440x_attr->table_size; val++) |
231 | case SIMPLE: | 177 | if (afe440x_attr->val_table[val].integer == integer && |
232 | val = integer; | 178 | afe440x_attr->val_table[val].fract == fract) |
233 | break; | 179 | break; |
234 | case RESISTANCE: | 180 | if (val == afe440x_attr->table_size) |
235 | case CAPACITANCE: | ||
236 | for (val = 0; val < afe440x_attr->table_size; val++) | ||
237 | if (afe440x_attr->val_table[val].integer == integer && | ||
238 | afe440x_attr->val_table[val].fract == fract) | ||
239 | break; | ||
240 | if (val == afe440x_attr->table_size) | ||
241 | return -EINVAL; | ||
242 | break; | ||
243 | default: | ||
244 | return -EINVAL; | 181 | return -EINVAL; |
245 | } | ||
246 | 182 | ||
247 | ret = regmap_update_bits(afe->regmap, afe440x_attr->reg, | 183 | ret = regmap_field_write(afe->fields[afe440x_attr->field], val); |
248 | afe440x_attr->mask, | ||
249 | (val << afe440x_attr->shift)); | ||
250 | if (ret) | 184 | if (ret) |
251 | return ret; | 185 | return ret; |
252 | 186 | ||
253 | return count; | 187 | return count; |
254 | } | 188 | } |
255 | 189 | ||
256 | static AFE440X_ATTR(tia_separate_en, AFE4403_TIAGAIN, AFE440X_TIAGAIN_ENSEPGAIN, SIMPLE, NULL, 0); | 190 | static AFE440X_ATTR(in_intensity1_resistance, F_RF_LED, afe4403_res_table); |
191 | static AFE440X_ATTR(in_intensity1_capacitance, F_CF_LED, afe4403_cap_table); | ||
192 | |||
193 | static AFE440X_ATTR(in_intensity2_resistance, F_RF_LED, afe4403_res_table); | ||
194 | static AFE440X_ATTR(in_intensity2_capacitance, F_CF_LED, afe4403_cap_table); | ||
257 | 195 | ||
258 | static AFE440X_ATTR(tia_resistance1, AFE4403_TIAGAIN, AFE4403_TIAGAIN_RES, RESISTANCE, afe4403_res_table, ARRAY_SIZE(afe4403_res_table)); | 196 | static AFE440X_ATTR(in_intensity3_resistance, F_RF_LED1, afe4403_res_table); |
259 | static AFE440X_ATTR(tia_capacitance1, AFE4403_TIAGAIN, AFE4403_TIAGAIN_CAP, CAPACITANCE, afe4403_cap_table, ARRAY_SIZE(afe4403_cap_table)); | 197 | static AFE440X_ATTR(in_intensity3_capacitance, F_CF_LED1, afe4403_cap_table); |
260 | 198 | ||
261 | static AFE440X_ATTR(tia_resistance2, AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES, RESISTANCE, afe4403_res_table, ARRAY_SIZE(afe4403_res_table)); | 199 | static AFE440X_ATTR(in_intensity4_resistance, F_RF_LED1, afe4403_res_table); |
262 | static AFE440X_ATTR(tia_capacitance2, AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES, CAPACITANCE, afe4403_cap_table, ARRAY_SIZE(afe4403_cap_table)); | 200 | static AFE440X_ATTR(in_intensity4_capacitance, F_CF_LED1, afe4403_cap_table); |
263 | 201 | ||
264 | static struct attribute *afe440x_attributes[] = { | 202 | static struct attribute *afe440x_attributes[] = { |
265 | &afe440x_attr_tia_separate_en.dev_attr.attr, | 203 | &dev_attr_in_intensity_resistance_available.attr, |
266 | &afe440x_attr_tia_resistance1.dev_attr.attr, | 204 | &dev_attr_in_intensity_capacitance_available.attr, |
267 | &afe440x_attr_tia_capacitance1.dev_attr.attr, | 205 | &afe440x_attr_in_intensity1_resistance.dev_attr.attr, |
268 | &afe440x_attr_tia_resistance2.dev_attr.attr, | 206 | &afe440x_attr_in_intensity1_capacitance.dev_attr.attr, |
269 | &afe440x_attr_tia_capacitance2.dev_attr.attr, | 207 | &afe440x_attr_in_intensity2_resistance.dev_attr.attr, |
270 | &dev_attr_tia_resistance_available.attr, | 208 | &afe440x_attr_in_intensity2_capacitance.dev_attr.attr, |
271 | &dev_attr_tia_capacitance_available.attr, | 209 | &afe440x_attr_in_intensity3_resistance.dev_attr.attr, |
210 | &afe440x_attr_in_intensity3_capacitance.dev_attr.attr, | ||
211 | &afe440x_attr_in_intensity4_resistance.dev_attr.attr, | ||
212 | &afe440x_attr_in_intensity4_capacitance.dev_attr.attr, | ||
272 | NULL | 213 | NULL |
273 | }; | 214 | }; |
274 | 215 | ||
@@ -309,35 +250,26 @@ static int afe4403_read_raw(struct iio_dev *indio_dev, | |||
309 | int *val, int *val2, long mask) | 250 | int *val, int *val2, long mask) |
310 | { | 251 | { |
311 | struct afe4403_data *afe = iio_priv(indio_dev); | 252 | struct afe4403_data *afe = iio_priv(indio_dev); |
312 | const struct afe440x_reg_info reg_info = afe4403_reg_info[chan->address]; | 253 | unsigned int reg = afe4403_channel_values[chan->address]; |
254 | unsigned int field = afe4403_channel_leds[chan->address]; | ||
313 | int ret; | 255 | int ret; |
314 | 256 | ||
315 | switch (chan->type) { | 257 | switch (chan->type) { |
316 | case IIO_INTENSITY: | 258 | case IIO_INTENSITY: |
317 | switch (mask) { | 259 | switch (mask) { |
318 | case IIO_CHAN_INFO_RAW: | 260 | case IIO_CHAN_INFO_RAW: |
319 | ret = afe4403_read(afe, reg_info.reg, val); | 261 | ret = afe4403_read(afe, reg, val); |
320 | if (ret) | ||
321 | return ret; | ||
322 | return IIO_VAL_INT; | ||
323 | case IIO_CHAN_INFO_OFFSET: | ||
324 | ret = regmap_read(afe->regmap, reg_info.offreg, | ||
325 | val); | ||
326 | if (ret) | 262 | if (ret) |
327 | return ret; | 263 | return ret; |
328 | *val &= reg_info.mask; | ||
329 | *val >>= reg_info.shift; | ||
330 | return IIO_VAL_INT; | 264 | return IIO_VAL_INT; |
331 | } | 265 | } |
332 | break; | 266 | break; |
333 | case IIO_CURRENT: | 267 | case IIO_CURRENT: |
334 | switch (mask) { | 268 | switch (mask) { |
335 | case IIO_CHAN_INFO_RAW: | 269 | case IIO_CHAN_INFO_RAW: |
336 | ret = regmap_read(afe->regmap, reg_info.reg, val); | 270 | ret = regmap_field_read(afe->fields[field], val); |
337 | if (ret) | 271 | if (ret) |
338 | return ret; | 272 | return ret; |
339 | *val &= reg_info.mask; | ||
340 | *val >>= reg_info.shift; | ||
341 | return IIO_VAL_INT; | 273 | return IIO_VAL_INT; |
342 | case IIO_CHAN_INFO_SCALE: | 274 | case IIO_CHAN_INFO_SCALE: |
343 | *val = 0; | 275 | *val = 0; |
@@ -357,25 +289,13 @@ static int afe4403_write_raw(struct iio_dev *indio_dev, | |||
357 | int val, int val2, long mask) | 289 | int val, int val2, long mask) |
358 | { | 290 | { |
359 | struct afe4403_data *afe = iio_priv(indio_dev); | 291 | struct afe4403_data *afe = iio_priv(indio_dev); |
360 | const struct afe440x_reg_info reg_info = afe4403_reg_info[chan->address]; | 292 | unsigned int field = afe4403_channel_leds[chan->address]; |
361 | 293 | ||
362 | switch (chan->type) { | 294 | switch (chan->type) { |
363 | case IIO_INTENSITY: | ||
364 | switch (mask) { | ||
365 | case IIO_CHAN_INFO_OFFSET: | ||
366 | return regmap_update_bits(afe->regmap, | ||
367 | reg_info.offreg, | ||
368 | reg_info.mask, | ||
369 | (val << reg_info.shift)); | ||
370 | } | ||
371 | break; | ||
372 | case IIO_CURRENT: | 295 | case IIO_CURRENT: |
373 | switch (mask) { | 296 | switch (mask) { |
374 | case IIO_CHAN_INFO_RAW: | 297 | case IIO_CHAN_INFO_RAW: |
375 | return regmap_update_bits(afe->regmap, | 298 | return regmap_field_write(afe->fields[field], val); |
376 | reg_info.reg, | ||
377 | reg_info.mask, | ||
378 | (val << reg_info.shift)); | ||
379 | } | 299 | } |
380 | break; | 300 | break; |
381 | default: | 301 | default: |
@@ -410,7 +330,7 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private) | |||
410 | for_each_set_bit(bit, indio_dev->active_scan_mask, | 330 | for_each_set_bit(bit, indio_dev->active_scan_mask, |
411 | indio_dev->masklength) { | 331 | indio_dev->masklength) { |
412 | ret = spi_write_then_read(afe->spi, | 332 | ret = spi_write_then_read(afe->spi, |
413 | &afe4403_reg_info[bit].reg, 1, | 333 | &afe4403_channel_values[bit], 1, |
414 | rx, 3); | 334 | rx, 3); |
415 | if (ret) | 335 | if (ret) |
416 | goto err; | 336 | goto err; |
@@ -472,12 +392,8 @@ static const struct iio_trigger_ops afe4403_trigger_ops = { | |||
472 | 392 | ||
473 | static const struct reg_sequence afe4403_reg_sequences[] = { | 393 | static const struct reg_sequence afe4403_reg_sequences[] = { |
474 | AFE4403_TIMING_PAIRS, | 394 | AFE4403_TIMING_PAIRS, |
475 | { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN | 0x000007}, | 395 | { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN }, |
476 | { AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES_1_M }, | 396 | { AFE4403_TIAGAIN, AFE440X_TIAGAIN_ENSEPGAIN }, |
477 | { AFE440X_LEDCNTRL, (0x14 << AFE440X_LEDCNTRL_LED1_SHIFT) | | ||
478 | (0x14 << AFE440X_LEDCNTRL_LED2_SHIFT) }, | ||
479 | { AFE440X_CONTROL2, AFE440X_CONTROL2_TX_REF_050 << | ||
480 | AFE440X_CONTROL2_TX_REF_SHIFT }, | ||
481 | }; | 397 | }; |
482 | 398 | ||
483 | static const struct regmap_range afe4403_yes_ranges[] = { | 399 | static const struct regmap_range afe4403_yes_ranges[] = { |
@@ -498,13 +414,11 @@ static const struct regmap_config afe4403_regmap_config = { | |||
498 | .volatile_table = &afe4403_volatile_table, | 414 | .volatile_table = &afe4403_volatile_table, |
499 | }; | 415 | }; |
500 | 416 | ||
501 | #ifdef CONFIG_OF | ||
502 | static const struct of_device_id afe4403_of_match[] = { | 417 | static const struct of_device_id afe4403_of_match[] = { |
503 | { .compatible = "ti,afe4403", }, | 418 | { .compatible = "ti,afe4403", }, |
504 | { /* sentinel */ } | 419 | { /* sentinel */ } |
505 | }; | 420 | }; |
506 | MODULE_DEVICE_TABLE(of, afe4403_of_match); | 421 | MODULE_DEVICE_TABLE(of, afe4403_of_match); |
507 | #endif | ||
508 | 422 | ||
509 | static int __maybe_unused afe4403_suspend(struct device *dev) | 423 | static int __maybe_unused afe4403_suspend(struct device *dev) |
510 | { | 424 | { |
@@ -553,7 +467,7 @@ static int afe4403_probe(struct spi_device *spi) | |||
553 | { | 467 | { |
554 | struct iio_dev *indio_dev; | 468 | struct iio_dev *indio_dev; |
555 | struct afe4403_data *afe; | 469 | struct afe4403_data *afe; |
556 | int ret; | 470 | int i, ret; |
557 | 471 | ||
558 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*afe)); | 472 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*afe)); |
559 | if (!indio_dev) | 473 | if (!indio_dev) |
@@ -572,6 +486,15 @@ static int afe4403_probe(struct spi_device *spi) | |||
572 | return PTR_ERR(afe->regmap); | 486 | return PTR_ERR(afe->regmap); |
573 | } | 487 | } |
574 | 488 | ||
489 | for (i = 0; i < F_MAX_FIELDS; i++) { | ||
490 | afe->fields[i] = devm_regmap_field_alloc(afe->dev, afe->regmap, | ||
491 | afe4403_reg_fields[i]); | ||
492 | if (IS_ERR(afe->fields[i])) { | ||
493 | dev_err(afe->dev, "Unable to allocate regmap fields\n"); | ||
494 | return PTR_ERR(afe->fields[i]); | ||
495 | } | ||
496 | } | ||
497 | |||
575 | afe->regulator = devm_regulator_get(afe->dev, "tx_sup"); | 498 | afe->regulator = devm_regulator_get(afe->dev, "tx_sup"); |
576 | if (IS_ERR(afe->regulator)) { | 499 | if (IS_ERR(afe->regulator)) { |
577 | dev_err(afe->dev, "Unable to get regulator\n"); | 500 | dev_err(afe->dev, "Unable to get regulator\n"); |
@@ -694,7 +617,7 @@ MODULE_DEVICE_TABLE(spi, afe4403_ids); | |||
694 | static struct spi_driver afe4403_spi_driver = { | 617 | static struct spi_driver afe4403_spi_driver = { |
695 | .driver = { | 618 | .driver = { |
696 | .name = AFE4403_DRIVER_NAME, | 619 | .name = AFE4403_DRIVER_NAME, |
697 | .of_match_table = of_match_ptr(afe4403_of_match), | 620 | .of_match_table = afe4403_of_match, |
698 | .pm = &afe4403_pm_ops, | 621 | .pm = &afe4403_pm_ops, |
699 | }, | 622 | }, |
700 | .probe = afe4403_probe, | 623 | .probe = afe4403_probe, |
@@ -704,5 +627,5 @@ static struct spi_driver afe4403_spi_driver = { | |||
704 | module_spi_driver(afe4403_spi_driver); | 627 | module_spi_driver(afe4403_spi_driver); |
705 | 628 | ||
706 | MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); | 629 | MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); |
707 | MODULE_DESCRIPTION("TI AFE4403 Heart Rate and Pulse Oximeter"); | 630 | MODULE_DESCRIPTION("TI AFE4403 Heart Rate Monitor and Pulse Oximeter AFE"); |
708 | MODULE_LICENSE("GPL v2"); | 631 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c index 5096a4643784..45266404f7e3 100644 --- a/drivers/iio/health/afe4404.c +++ b/drivers/iio/health/afe4404.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * AFE4404 Heart Rate Monitors and Low-Cost Pulse Oximeters | 2 | * AFE4404 Heart Rate Monitors and Low-Cost Pulse Oximeters |
3 | * | 3 | * |
4 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ | 4 | * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ |
5 | * Andrew F. Davis <afd@ti.com> | 5 | * Andrew F. Davis <afd@ti.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -48,118 +48,102 @@ | |||
48 | #define AFE4404_AVG_LED2_ALED2VAL 0x3f | 48 | #define AFE4404_AVG_LED2_ALED2VAL 0x3f |
49 | #define AFE4404_AVG_LED1_ALED1VAL 0x40 | 49 | #define AFE4404_AVG_LED1_ALED1VAL 0x40 |
50 | 50 | ||
51 | /* AFE4404 GAIN register fields */ | 51 | /* AFE4404 CONTROL2 register fields */ |
52 | #define AFE4404_TIA_GAIN_RES_MASK GENMASK(2, 0) | 52 | #define AFE440X_CONTROL2_OSC_ENABLE BIT(9) |
53 | #define AFE4404_TIA_GAIN_RES_SHIFT 0 | ||
54 | #define AFE4404_TIA_GAIN_CAP_MASK GENMASK(5, 3) | ||
55 | #define AFE4404_TIA_GAIN_CAP_SHIFT 3 | ||
56 | 53 | ||
57 | /* AFE4404 LEDCNTRL register fields */ | 54 | enum afe4404_fields { |
58 | #define AFE4404_LEDCNTRL_ILED1_MASK GENMASK(5, 0) | 55 | /* Gains */ |
59 | #define AFE4404_LEDCNTRL_ILED1_SHIFT 0 | 56 | F_TIA_GAIN_SEP, F_TIA_CF_SEP, |
60 | #define AFE4404_LEDCNTRL_ILED2_MASK GENMASK(11, 6) | 57 | F_TIA_GAIN, TIA_CF, |
61 | #define AFE4404_LEDCNTRL_ILED2_SHIFT 6 | ||
62 | #define AFE4404_LEDCNTRL_ILED3_MASK GENMASK(17, 12) | ||
63 | #define AFE4404_LEDCNTRL_ILED3_SHIFT 12 | ||
64 | 58 | ||
65 | /* AFE4404 CONTROL2 register fields */ | 59 | /* LED Current */ |
66 | #define AFE440X_CONTROL2_ILED_2X_MASK BIT(17) | 60 | F_ILED1, F_ILED2, F_ILED3, |
67 | #define AFE440X_CONTROL2_ILED_2X_SHIFT 17 | 61 | |
68 | 62 | /* Offset DAC */ | |
69 | /* AFE4404 CONTROL3 register fields */ | 63 | F_OFFDAC_AMB2, F_OFFDAC_LED1, F_OFFDAC_AMB1, F_OFFDAC_LED2, |
70 | #define AFE440X_CONTROL3_OSC_ENABLE BIT(9) | 64 | |
71 | 65 | /* sentinel */ | |
72 | /* AFE4404 OFFDAC register current fields */ | 66 | F_MAX_FIELDS |
73 | #define AFE4404_OFFDAC_CURR_LED1_MASK GENMASK(9, 5) | 67 | }; |
74 | #define AFE4404_OFFDAC_CURR_LED1_SHIFT 5 | 68 | |
75 | #define AFE4404_OFFDAC_CURR_LED2_MASK GENMASK(19, 15) | 69 | static const struct reg_field afe4404_reg_fields[] = { |
76 | #define AFE4404_OFFDAC_CURR_LED2_SHIFT 15 | 70 | /* Gains */ |
77 | #define AFE4404_OFFDAC_CURR_LED3_MASK GENMASK(4, 0) | 71 | [F_TIA_GAIN_SEP] = REG_FIELD(AFE4404_TIA_GAIN_SEP, 0, 2), |
78 | #define AFE4404_OFFDAC_CURR_LED3_SHIFT 0 | 72 | [F_TIA_CF_SEP] = REG_FIELD(AFE4404_TIA_GAIN_SEP, 3, 5), |
79 | #define AFE4404_OFFDAC_CURR_ALED1_MASK GENMASK(14, 10) | 73 | [F_TIA_GAIN] = REG_FIELD(AFE4404_TIA_GAIN, 0, 2), |
80 | #define AFE4404_OFFDAC_CURR_ALED1_SHIFT 10 | 74 | [TIA_CF] = REG_FIELD(AFE4404_TIA_GAIN, 3, 5), |
81 | #define AFE4404_OFFDAC_CURR_ALED2_MASK GENMASK(4, 0) | 75 | /* LED Current */ |
82 | #define AFE4404_OFFDAC_CURR_ALED2_SHIFT 0 | 76 | [F_ILED1] = REG_FIELD(AFE440X_LEDCNTRL, 0, 5), |
83 | 77 | [F_ILED2] = REG_FIELD(AFE440X_LEDCNTRL, 6, 11), | |
84 | /* AFE4404 NULL fields */ | 78 | [F_ILED3] = REG_FIELD(AFE440X_LEDCNTRL, 12, 17), |
85 | #define NULL_MASK 0 | 79 | /* Offset DAC */ |
86 | #define NULL_SHIFT 0 | 80 | [F_OFFDAC_AMB2] = REG_FIELD(AFE4404_OFFDAC, 0, 4), |
87 | 81 | [F_OFFDAC_LED1] = REG_FIELD(AFE4404_OFFDAC, 5, 9), | |
88 | /* AFE4404 TIA_GAIN_CAP values */ | 82 | [F_OFFDAC_AMB1] = REG_FIELD(AFE4404_OFFDAC, 10, 14), |
89 | #define AFE4404_TIA_GAIN_CAP_5_P 0x0 | 83 | [F_OFFDAC_LED2] = REG_FIELD(AFE4404_OFFDAC, 15, 19), |
90 | #define AFE4404_TIA_GAIN_CAP_2_5_P 0x1 | 84 | }; |
91 | #define AFE4404_TIA_GAIN_CAP_10_P 0x2 | ||
92 | #define AFE4404_TIA_GAIN_CAP_7_5_P 0x3 | ||
93 | #define AFE4404_TIA_GAIN_CAP_20_P 0x4 | ||
94 | #define AFE4404_TIA_GAIN_CAP_17_5_P 0x5 | ||
95 | #define AFE4404_TIA_GAIN_CAP_25_P 0x6 | ||
96 | #define AFE4404_TIA_GAIN_CAP_22_5_P 0x7 | ||
97 | |||
98 | /* AFE4404 TIA_GAIN_RES values */ | ||
99 | #define AFE4404_TIA_GAIN_RES_500_K 0x0 | ||
100 | #define AFE4404_TIA_GAIN_RES_250_K 0x1 | ||
101 | #define AFE4404_TIA_GAIN_RES_100_K 0x2 | ||
102 | #define AFE4404_TIA_GAIN_RES_50_K 0x3 | ||
103 | #define AFE4404_TIA_GAIN_RES_25_K 0x4 | ||
104 | #define AFE4404_TIA_GAIN_RES_10_K 0x5 | ||
105 | #define AFE4404_TIA_GAIN_RES_1_M 0x6 | ||
106 | #define AFE4404_TIA_GAIN_RES_2_M 0x7 | ||
107 | 85 | ||
108 | /** | 86 | /** |
109 | * struct afe4404_data | 87 | * struct afe4404_data - AFE4404 device instance data |
110 | * @dev - Device structure | 88 | * @dev: Device structure |
111 | * @regmap - Register map of the device | 89 | * @regmap: Register map of the device |
112 | * @regulator - Pointer to the regulator for the IC | 90 | * @fields: Register fields of the device |
113 | * @trig - IIO trigger for this device | 91 | * @regulator: Pointer to the regulator for the IC |
114 | * @irq - ADC_RDY line interrupt number | 92 | * @trig: IIO trigger for this device |
93 | * @irq: ADC_RDY line interrupt number | ||
115 | */ | 94 | */ |
116 | struct afe4404_data { | 95 | struct afe4404_data { |
117 | struct device *dev; | 96 | struct device *dev; |
118 | struct regmap *regmap; | 97 | struct regmap *regmap; |
98 | struct regmap_field *fields[F_MAX_FIELDS]; | ||
119 | struct regulator *regulator; | 99 | struct regulator *regulator; |
120 | struct iio_trigger *trig; | 100 | struct iio_trigger *trig; |
121 | int irq; | 101 | int irq; |
122 | }; | 102 | }; |
123 | 103 | ||
124 | enum afe4404_chan_id { | 104 | enum afe4404_chan_id { |
105 | LED2 = 1, | ||
106 | ALED2, | ||
125 | LED1, | 107 | LED1, |
126 | ALED1, | 108 | ALED1, |
127 | LED2, | ||
128 | ALED2, | ||
129 | LED3, | ||
130 | LED1_ALED1, | ||
131 | LED2_ALED2, | 109 | LED2_ALED2, |
132 | ILED1, | 110 | LED1_ALED1, |
133 | ILED2, | 111 | }; |
134 | ILED3, | 112 | |
113 | static const unsigned int afe4404_channel_values[] = { | ||
114 | [LED2] = AFE440X_LED2VAL, | ||
115 | [ALED2] = AFE440X_ALED2VAL, | ||
116 | [LED1] = AFE440X_LED1VAL, | ||
117 | [ALED1] = AFE440X_ALED1VAL, | ||
118 | [LED2_ALED2] = AFE440X_LED2_ALED2VAL, | ||
119 | [LED1_ALED1] = AFE440X_LED1_ALED1VAL, | ||
135 | }; | 120 | }; |
136 | 121 | ||
137 | static const struct afe440x_reg_info afe4404_reg_info[] = { | 122 | static const unsigned int afe4404_channel_leds[] = { |
138 | [LED1] = AFE440X_REG_INFO(AFE440X_LED1VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_LED1), | 123 | [LED2] = F_ILED2, |
139 | [ALED1] = AFE440X_REG_INFO(AFE440X_ALED1VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_ALED1), | 124 | [ALED2] = F_ILED3, |
140 | [LED2] = AFE440X_REG_INFO(AFE440X_LED2VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_LED2), | 125 | [LED1] = F_ILED1, |
141 | [ALED2] = AFE440X_REG_INFO(AFE440X_ALED2VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_ALED2), | 126 | }; |
142 | [LED3] = AFE440X_REG_INFO(AFE440X_ALED2VAL, 0, NULL), | 127 | |
143 | [LED1_ALED1] = AFE440X_REG_INFO(AFE440X_LED1_ALED1VAL, 0, NULL), | 128 | static const unsigned int afe4404_channel_offdacs[] = { |
144 | [LED2_ALED2] = AFE440X_REG_INFO(AFE440X_LED2_ALED2VAL, 0, NULL), | 129 | [LED2] = F_OFFDAC_LED2, |
145 | [ILED1] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED1), | 130 | [ALED2] = F_OFFDAC_AMB2, |
146 | [ILED2] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED2), | 131 | [LED1] = F_OFFDAC_LED1, |
147 | [ILED3] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED3), | 132 | [ALED1] = F_OFFDAC_AMB1, |
148 | }; | 133 | }; |
149 | 134 | ||
150 | static const struct iio_chan_spec afe4404_channels[] = { | 135 | static const struct iio_chan_spec afe4404_channels[] = { |
151 | /* ADC values */ | 136 | /* ADC values */ |
152 | AFE440X_INTENSITY_CHAN(LED1, "led1", BIT(IIO_CHAN_INFO_OFFSET)), | 137 | AFE440X_INTENSITY_CHAN(LED2, BIT(IIO_CHAN_INFO_OFFSET)), |
153 | AFE440X_INTENSITY_CHAN(ALED1, "led1_ambient", BIT(IIO_CHAN_INFO_OFFSET)), | 138 | AFE440X_INTENSITY_CHAN(ALED2, BIT(IIO_CHAN_INFO_OFFSET)), |
154 | AFE440X_INTENSITY_CHAN(LED2, "led2", BIT(IIO_CHAN_INFO_OFFSET)), | 139 | AFE440X_INTENSITY_CHAN(LED1, BIT(IIO_CHAN_INFO_OFFSET)), |
155 | AFE440X_INTENSITY_CHAN(ALED2, "led2_ambient", BIT(IIO_CHAN_INFO_OFFSET)), | 140 | AFE440X_INTENSITY_CHAN(ALED1, BIT(IIO_CHAN_INFO_OFFSET)), |
156 | AFE440X_INTENSITY_CHAN(LED3, "led3", BIT(IIO_CHAN_INFO_OFFSET)), | 141 | AFE440X_INTENSITY_CHAN(LED2_ALED2, 0), |
157 | AFE440X_INTENSITY_CHAN(LED1_ALED1, "led1-led1_ambient", 0), | 142 | AFE440X_INTENSITY_CHAN(LED1_ALED1, 0), |
158 | AFE440X_INTENSITY_CHAN(LED2_ALED2, "led2-led2_ambient", 0), | ||
159 | /* LED current */ | 143 | /* LED current */ |
160 | AFE440X_CURRENT_CHAN(ILED1, "led1"), | 144 | AFE440X_CURRENT_CHAN(LED2), |
161 | AFE440X_CURRENT_CHAN(ILED2, "led2"), | 145 | AFE440X_CURRENT_CHAN(ALED2), |
162 | AFE440X_CURRENT_CHAN(ILED3, "led3"), | 146 | AFE440X_CURRENT_CHAN(LED1), |
163 | }; | 147 | }; |
164 | 148 | ||
165 | static const struct afe440x_val_table afe4404_res_table[] = { | 149 | static const struct afe440x_val_table afe4404_res_table[] = { |
@@ -172,7 +156,7 @@ static const struct afe440x_val_table afe4404_res_table[] = { | |||
172 | { .integer = 1000000, .fract = 0 }, | 156 | { .integer = 1000000, .fract = 0 }, |
173 | { .integer = 2000000, .fract = 0 }, | 157 | { .integer = 2000000, .fract = 0 }, |
174 | }; | 158 | }; |
175 | AFE440X_TABLE_ATTR(tia_resistance_available, afe4404_res_table); | 159 | AFE440X_TABLE_ATTR(in_intensity_resistance_available, afe4404_res_table); |
176 | 160 | ||
177 | static const struct afe440x_val_table afe4404_cap_table[] = { | 161 | static const struct afe440x_val_table afe4404_cap_table[] = { |
178 | { .integer = 0, .fract = 5000 }, | 162 | { .integer = 0, .fract = 5000 }, |
@@ -184,7 +168,7 @@ static const struct afe440x_val_table afe4404_cap_table[] = { | |||
184 | { .integer = 0, .fract = 25000 }, | 168 | { .integer = 0, .fract = 25000 }, |
185 | { .integer = 0, .fract = 22500 }, | 169 | { .integer = 0, .fract = 22500 }, |
186 | }; | 170 | }; |
187 | AFE440X_TABLE_ATTR(tia_capacitance_available, afe4404_cap_table); | 171 | AFE440X_TABLE_ATTR(in_intensity_capacitance_available, afe4404_cap_table); |
188 | 172 | ||
189 | static ssize_t afe440x_show_register(struct device *dev, | 173 | static ssize_t afe440x_show_register(struct device *dev, |
190 | struct device_attribute *attr, | 174 | struct device_attribute *attr, |
@@ -193,38 +177,21 @@ static ssize_t afe440x_show_register(struct device *dev, | |||
193 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 177 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
194 | struct afe4404_data *afe = iio_priv(indio_dev); | 178 | struct afe4404_data *afe = iio_priv(indio_dev); |
195 | struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); | 179 | struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); |
196 | unsigned int reg_val, type; | 180 | unsigned int reg_val; |
197 | int vals[2]; | 181 | int vals[2]; |
198 | int ret, val_len; | 182 | int ret; |
199 | 183 | ||
200 | ret = regmap_read(afe->regmap, afe440x_attr->reg, ®_val); | 184 | ret = regmap_field_read(afe->fields[afe440x_attr->field], ®_val); |
201 | if (ret) | 185 | if (ret) |
202 | return ret; | 186 | return ret; |
203 | 187 | ||
204 | reg_val &= afe440x_attr->mask; | 188 | if (reg_val >= afe440x_attr->table_size) |
205 | reg_val >>= afe440x_attr->shift; | ||
206 | |||
207 | switch (afe440x_attr->type) { | ||
208 | case SIMPLE: | ||
209 | type = IIO_VAL_INT; | ||
210 | val_len = 1; | ||
211 | vals[0] = reg_val; | ||
212 | break; | ||
213 | case RESISTANCE: | ||
214 | case CAPACITANCE: | ||
215 | type = IIO_VAL_INT_PLUS_MICRO; | ||
216 | val_len = 2; | ||
217 | if (reg_val < afe440x_attr->table_size) { | ||
218 | vals[0] = afe440x_attr->val_table[reg_val].integer; | ||
219 | vals[1] = afe440x_attr->val_table[reg_val].fract; | ||
220 | break; | ||
221 | } | ||
222 | return -EINVAL; | ||
223 | default: | ||
224 | return -EINVAL; | 189 | return -EINVAL; |
225 | } | ||
226 | 190 | ||
227 | return iio_format_value(buf, type, val_len, vals); | 191 | vals[0] = afe440x_attr->val_table[reg_val].integer; |
192 | vals[1] = afe440x_attr->val_table[reg_val].fract; | ||
193 | |||
194 | return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, 2, vals); | ||
228 | } | 195 | } |
229 | 196 | ||
230 | static ssize_t afe440x_store_register(struct device *dev, | 197 | static ssize_t afe440x_store_register(struct device *dev, |
@@ -240,48 +207,43 @@ static ssize_t afe440x_store_register(struct device *dev, | |||
240 | if (ret) | 207 | if (ret) |
241 | return ret; | 208 | return ret; |
242 | 209 | ||
243 | switch (afe440x_attr->type) { | 210 | for (val = 0; val < afe440x_attr->table_size; val++) |
244 | case SIMPLE: | 211 | if (afe440x_attr->val_table[val].integer == integer && |
245 | val = integer; | 212 | afe440x_attr->val_table[val].fract == fract) |
246 | break; | 213 | break; |
247 | case RESISTANCE: | 214 | if (val == afe440x_attr->table_size) |
248 | case CAPACITANCE: | ||
249 | for (val = 0; val < afe440x_attr->table_size; val++) | ||
250 | if (afe440x_attr->val_table[val].integer == integer && | ||
251 | afe440x_attr->val_table[val].fract == fract) | ||
252 | break; | ||
253 | if (val == afe440x_attr->table_size) | ||
254 | return -EINVAL; | ||
255 | break; | ||
256 | default: | ||
257 | return -EINVAL; | 215 | return -EINVAL; |
258 | } | ||
259 | 216 | ||
260 | ret = regmap_update_bits(afe->regmap, afe440x_attr->reg, | 217 | ret = regmap_field_write(afe->fields[afe440x_attr->field], val); |
261 | afe440x_attr->mask, | ||
262 | (val << afe440x_attr->shift)); | ||
263 | if (ret) | 218 | if (ret) |
264 | return ret; | 219 | return ret; |
265 | 220 | ||
266 | return count; | 221 | return count; |
267 | } | 222 | } |
268 | 223 | ||
269 | static AFE440X_ATTR(tia_separate_en, AFE4404_TIA_GAIN_SEP, AFE440X_TIAGAIN_ENSEPGAIN, SIMPLE, NULL, 0); | 224 | static AFE440X_ATTR(in_intensity1_resistance, F_TIA_GAIN_SEP, afe4404_res_table); |
225 | static AFE440X_ATTR(in_intensity1_capacitance, F_TIA_CF_SEP, afe4404_cap_table); | ||
226 | |||
227 | static AFE440X_ATTR(in_intensity2_resistance, F_TIA_GAIN_SEP, afe4404_res_table); | ||
228 | static AFE440X_ATTR(in_intensity2_capacitance, F_TIA_CF_SEP, afe4404_cap_table); | ||
270 | 229 | ||
271 | static AFE440X_ATTR(tia_resistance1, AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_RES, RESISTANCE, afe4404_res_table, ARRAY_SIZE(afe4404_res_table)); | 230 | static AFE440X_ATTR(in_intensity3_resistance, F_TIA_GAIN, afe4404_res_table); |
272 | static AFE440X_ATTR(tia_capacitance1, AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_CAP, CAPACITANCE, afe4404_cap_table, ARRAY_SIZE(afe4404_cap_table)); | 231 | static AFE440X_ATTR(in_intensity3_capacitance, TIA_CF, afe4404_cap_table); |
273 | 232 | ||
274 | static AFE440X_ATTR(tia_resistance2, AFE4404_TIA_GAIN_SEP, AFE4404_TIA_GAIN_RES, RESISTANCE, afe4404_res_table, ARRAY_SIZE(afe4404_res_table)); | 233 | static AFE440X_ATTR(in_intensity4_resistance, F_TIA_GAIN, afe4404_res_table); |
275 | static AFE440X_ATTR(tia_capacitance2, AFE4404_TIA_GAIN_SEP, AFE4404_TIA_GAIN_CAP, CAPACITANCE, afe4404_cap_table, ARRAY_SIZE(afe4404_cap_table)); | 234 | static AFE440X_ATTR(in_intensity4_capacitance, TIA_CF, afe4404_cap_table); |
276 | 235 | ||
277 | static struct attribute *afe440x_attributes[] = { | 236 | static struct attribute *afe440x_attributes[] = { |
278 | &afe440x_attr_tia_separate_en.dev_attr.attr, | 237 | &dev_attr_in_intensity_resistance_available.attr, |
279 | &afe440x_attr_tia_resistance1.dev_attr.attr, | 238 | &dev_attr_in_intensity_capacitance_available.attr, |
280 | &afe440x_attr_tia_capacitance1.dev_attr.attr, | 239 | &afe440x_attr_in_intensity1_resistance.dev_attr.attr, |
281 | &afe440x_attr_tia_resistance2.dev_attr.attr, | 240 | &afe440x_attr_in_intensity1_capacitance.dev_attr.attr, |
282 | &afe440x_attr_tia_capacitance2.dev_attr.attr, | 241 | &afe440x_attr_in_intensity2_resistance.dev_attr.attr, |
283 | &dev_attr_tia_resistance_available.attr, | 242 | &afe440x_attr_in_intensity2_capacitance.dev_attr.attr, |
284 | &dev_attr_tia_capacitance_available.attr, | 243 | &afe440x_attr_in_intensity3_resistance.dev_attr.attr, |
244 | &afe440x_attr_in_intensity3_capacitance.dev_attr.attr, | ||
245 | &afe440x_attr_in_intensity4_resistance.dev_attr.attr, | ||
246 | &afe440x_attr_in_intensity4_capacitance.dev_attr.attr, | ||
285 | NULL | 247 | NULL |
286 | }; | 248 | }; |
287 | 249 | ||
@@ -294,35 +256,32 @@ static int afe4404_read_raw(struct iio_dev *indio_dev, | |||
294 | int *val, int *val2, long mask) | 256 | int *val, int *val2, long mask) |
295 | { | 257 | { |
296 | struct afe4404_data *afe = iio_priv(indio_dev); | 258 | struct afe4404_data *afe = iio_priv(indio_dev); |
297 | const struct afe440x_reg_info reg_info = afe4404_reg_info[chan->address]; | 259 | unsigned int value_reg = afe4404_channel_values[chan->address]; |
260 | unsigned int led_field = afe4404_channel_leds[chan->address]; | ||
261 | unsigned int offdac_field = afe4404_channel_offdacs[chan->address]; | ||
298 | int ret; | 262 | int ret; |
299 | 263 | ||
300 | switch (chan->type) { | 264 | switch (chan->type) { |
301 | case IIO_INTENSITY: | 265 | case IIO_INTENSITY: |
302 | switch (mask) { | 266 | switch (mask) { |
303 | case IIO_CHAN_INFO_RAW: | 267 | case IIO_CHAN_INFO_RAW: |
304 | ret = regmap_read(afe->regmap, reg_info.reg, val); | 268 | ret = regmap_read(afe->regmap, value_reg, val); |
305 | if (ret) | 269 | if (ret) |
306 | return ret; | 270 | return ret; |
307 | return IIO_VAL_INT; | 271 | return IIO_VAL_INT; |
308 | case IIO_CHAN_INFO_OFFSET: | 272 | case IIO_CHAN_INFO_OFFSET: |
309 | ret = regmap_read(afe->regmap, reg_info.offreg, | 273 | ret = regmap_field_read(afe->fields[offdac_field], val); |
310 | val); | ||
311 | if (ret) | 274 | if (ret) |
312 | return ret; | 275 | return ret; |
313 | *val &= reg_info.mask; | ||
314 | *val >>= reg_info.shift; | ||
315 | return IIO_VAL_INT; | 276 | return IIO_VAL_INT; |
316 | } | 277 | } |
317 | break; | 278 | break; |
318 | case IIO_CURRENT: | 279 | case IIO_CURRENT: |
319 | switch (mask) { | 280 | switch (mask) { |
320 | case IIO_CHAN_INFO_RAW: | 281 | case IIO_CHAN_INFO_RAW: |
321 | ret = regmap_read(afe->regmap, reg_info.reg, val); | 282 | ret = regmap_field_read(afe->fields[led_field], val); |
322 | if (ret) | 283 | if (ret) |
323 | return ret; | 284 | return ret; |
324 | *val &= reg_info.mask; | ||
325 | *val >>= reg_info.shift; | ||
326 | return IIO_VAL_INT; | 285 | return IIO_VAL_INT; |
327 | case IIO_CHAN_INFO_SCALE: | 286 | case IIO_CHAN_INFO_SCALE: |
328 | *val = 0; | 287 | *val = 0; |
@@ -342,25 +301,20 @@ static int afe4404_write_raw(struct iio_dev *indio_dev, | |||
342 | int val, int val2, long mask) | 301 | int val, int val2, long mask) |
343 | { | 302 | { |
344 | struct afe4404_data *afe = iio_priv(indio_dev); | 303 | struct afe4404_data *afe = iio_priv(indio_dev); |
345 | const struct afe440x_reg_info reg_info = afe4404_reg_info[chan->address]; | 304 | unsigned int led_field = afe4404_channel_leds[chan->address]; |
305 | unsigned int offdac_field = afe4404_channel_offdacs[chan->address]; | ||
346 | 306 | ||
347 | switch (chan->type) { | 307 | switch (chan->type) { |
348 | case IIO_INTENSITY: | 308 | case IIO_INTENSITY: |
349 | switch (mask) { | 309 | switch (mask) { |
350 | case IIO_CHAN_INFO_OFFSET: | 310 | case IIO_CHAN_INFO_OFFSET: |
351 | return regmap_update_bits(afe->regmap, | 311 | return regmap_field_write(afe->fields[offdac_field], val); |
352 | reg_info.offreg, | ||
353 | reg_info.mask, | ||
354 | (val << reg_info.shift)); | ||
355 | } | 312 | } |
356 | break; | 313 | break; |
357 | case IIO_CURRENT: | 314 | case IIO_CURRENT: |
358 | switch (mask) { | 315 | switch (mask) { |
359 | case IIO_CHAN_INFO_RAW: | 316 | case IIO_CHAN_INFO_RAW: |
360 | return regmap_update_bits(afe->regmap, | 317 | return regmap_field_write(afe->fields[led_field], val); |
361 | reg_info.reg, | ||
362 | reg_info.mask, | ||
363 | (val << reg_info.shift)); | ||
364 | } | 318 | } |
365 | break; | 319 | break; |
366 | default: | 320 | default: |
@@ -387,7 +341,7 @@ static irqreturn_t afe4404_trigger_handler(int irq, void *private) | |||
387 | 341 | ||
388 | for_each_set_bit(bit, indio_dev->active_scan_mask, | 342 | for_each_set_bit(bit, indio_dev->active_scan_mask, |
389 | indio_dev->masklength) { | 343 | indio_dev->masklength) { |
390 | ret = regmap_read(afe->regmap, afe4404_reg_info[bit].reg, | 344 | ret = regmap_read(afe->regmap, afe4404_channel_values[bit], |
391 | &buffer[i++]); | 345 | &buffer[i++]); |
392 | if (ret) | 346 | if (ret) |
393 | goto err; | 347 | goto err; |
@@ -443,11 +397,8 @@ static const struct iio_trigger_ops afe4404_trigger_ops = { | |||
443 | static const struct reg_sequence afe4404_reg_sequences[] = { | 397 | static const struct reg_sequence afe4404_reg_sequences[] = { |
444 | AFE4404_TIMING_PAIRS, | 398 | AFE4404_TIMING_PAIRS, |
445 | { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN }, | 399 | { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN }, |
446 | { AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_RES_50_K }, | 400 | { AFE4404_TIA_GAIN_SEP, AFE440X_TIAGAIN_ENSEPGAIN }, |
447 | { AFE440X_LEDCNTRL, (0xf << AFE4404_LEDCNTRL_ILED1_SHIFT) | | 401 | { AFE440X_CONTROL2, AFE440X_CONTROL2_OSC_ENABLE }, |
448 | (0x3 << AFE4404_LEDCNTRL_ILED2_SHIFT) | | ||
449 | (0x3 << AFE4404_LEDCNTRL_ILED3_SHIFT) }, | ||
450 | { AFE440X_CONTROL2, AFE440X_CONTROL3_OSC_ENABLE }, | ||
451 | }; | 402 | }; |
452 | 403 | ||
453 | static const struct regmap_range afe4404_yes_ranges[] = { | 404 | static const struct regmap_range afe4404_yes_ranges[] = { |
@@ -469,13 +420,11 @@ static const struct regmap_config afe4404_regmap_config = { | |||
469 | .volatile_table = &afe4404_volatile_table, | 420 | .volatile_table = &afe4404_volatile_table, |
470 | }; | 421 | }; |
471 | 422 | ||
472 | #ifdef CONFIG_OF | ||
473 | static const struct of_device_id afe4404_of_match[] = { | 423 | static const struct of_device_id afe4404_of_match[] = { |
474 | { .compatible = "ti,afe4404", }, | 424 | { .compatible = "ti,afe4404", }, |
475 | { /* sentinel */ } | 425 | { /* sentinel */ } |
476 | }; | 426 | }; |
477 | MODULE_DEVICE_TABLE(of, afe4404_of_match); | 427 | MODULE_DEVICE_TABLE(of, afe4404_of_match); |
478 | #endif | ||
479 | 428 | ||
480 | static int __maybe_unused afe4404_suspend(struct device *dev) | 429 | static int __maybe_unused afe4404_suspend(struct device *dev) |
481 | { | 430 | { |
@@ -525,7 +474,7 @@ static int afe4404_probe(struct i2c_client *client, | |||
525 | { | 474 | { |
526 | struct iio_dev *indio_dev; | 475 | struct iio_dev *indio_dev; |
527 | struct afe4404_data *afe; | 476 | struct afe4404_data *afe; |
528 | int ret; | 477 | int i, ret; |
529 | 478 | ||
530 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*afe)); | 479 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*afe)); |
531 | if (!indio_dev) | 480 | if (!indio_dev) |
@@ -543,6 +492,15 @@ static int afe4404_probe(struct i2c_client *client, | |||
543 | return PTR_ERR(afe->regmap); | 492 | return PTR_ERR(afe->regmap); |
544 | } | 493 | } |
545 | 494 | ||
495 | for (i = 0; i < F_MAX_FIELDS; i++) { | ||
496 | afe->fields[i] = devm_regmap_field_alloc(afe->dev, afe->regmap, | ||
497 | afe4404_reg_fields[i]); | ||
498 | if (IS_ERR(afe->fields[i])) { | ||
499 | dev_err(afe->dev, "Unable to allocate regmap fields\n"); | ||
500 | return PTR_ERR(afe->fields[i]); | ||
501 | } | ||
502 | } | ||
503 | |||
546 | afe->regulator = devm_regulator_get(afe->dev, "tx_sup"); | 504 | afe->regulator = devm_regulator_get(afe->dev, "tx_sup"); |
547 | if (IS_ERR(afe->regulator)) { | 505 | if (IS_ERR(afe->regulator)) { |
548 | dev_err(afe->dev, "Unable to get regulator\n"); | 506 | dev_err(afe->dev, "Unable to get regulator\n"); |
@@ -665,7 +623,7 @@ MODULE_DEVICE_TABLE(i2c, afe4404_ids); | |||
665 | static struct i2c_driver afe4404_i2c_driver = { | 623 | static struct i2c_driver afe4404_i2c_driver = { |
666 | .driver = { | 624 | .driver = { |
667 | .name = AFE4404_DRIVER_NAME, | 625 | .name = AFE4404_DRIVER_NAME, |
668 | .of_match_table = of_match_ptr(afe4404_of_match), | 626 | .of_match_table = afe4404_of_match, |
669 | .pm = &afe4404_pm_ops, | 627 | .pm = &afe4404_pm_ops, |
670 | }, | 628 | }, |
671 | .probe = afe4404_probe, | 629 | .probe = afe4404_probe, |
@@ -675,5 +633,5 @@ static struct i2c_driver afe4404_i2c_driver = { | |||
675 | module_i2c_driver(afe4404_i2c_driver); | 633 | module_i2c_driver(afe4404_i2c_driver); |
676 | 634 | ||
677 | MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); | 635 | MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); |
678 | MODULE_DESCRIPTION("TI AFE4404 Heart Rate and Pulse Oximeter"); | 636 | MODULE_DESCRIPTION("TI AFE4404 Heart Rate Monitor and Pulse Oximeter AFE"); |
679 | MODULE_LICENSE("GPL v2"); | 637 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/iio/health/afe440x.h b/drivers/iio/health/afe440x.h index c671ab78a23a..1a0f247043ca 100644 --- a/drivers/iio/health/afe440x.h +++ b/drivers/iio/health/afe440x.h | |||
@@ -71,8 +71,7 @@ | |||
71 | #define AFE440X_CONTROL1_TIMEREN BIT(8) | 71 | #define AFE440X_CONTROL1_TIMEREN BIT(8) |
72 | 72 | ||
73 | /* TIAGAIN register fields */ | 73 | /* TIAGAIN register fields */ |
74 | #define AFE440X_TIAGAIN_ENSEPGAIN_MASK BIT(15) | 74 | #define AFE440X_TIAGAIN_ENSEPGAIN BIT(15) |
75 | #define AFE440X_TIAGAIN_ENSEPGAIN_SHIFT 15 | ||
76 | 75 | ||
77 | /* CONTROL2 register fields */ | 76 | /* CONTROL2 register fields */ |
78 | #define AFE440X_CONTROL2_PDN_AFE BIT(0) | 77 | #define AFE440X_CONTROL2_PDN_AFE BIT(0) |
@@ -89,22 +88,7 @@ | |||
89 | #define AFE440X_CONTROL0_WRITE 0x0 | 88 | #define AFE440X_CONTROL0_WRITE 0x0 |
90 | #define AFE440X_CONTROL0_READ 0x1 | 89 | #define AFE440X_CONTROL0_READ 0x1 |
91 | 90 | ||
92 | struct afe440x_reg_info { | 91 | #define AFE440X_INTENSITY_CHAN(_index, _mask) \ |
93 | unsigned int reg; | ||
94 | unsigned int offreg; | ||
95 | unsigned int shift; | ||
96 | unsigned int mask; | ||
97 | }; | ||
98 | |||
99 | #define AFE440X_REG_INFO(_reg, _offreg, _sm) \ | ||
100 | { \ | ||
101 | .reg = _reg, \ | ||
102 | .offreg = _offreg, \ | ||
103 | .shift = _sm ## _SHIFT, \ | ||
104 | .mask = _sm ## _MASK, \ | ||
105 | } | ||
106 | |||
107 | #define AFE440X_INTENSITY_CHAN(_index, _name, _mask) \ | ||
108 | { \ | 92 | { \ |
109 | .type = IIO_INTENSITY, \ | 93 | .type = IIO_INTENSITY, \ |
110 | .channel = _index, \ | 94 | .channel = _index, \ |
@@ -116,29 +100,23 @@ struct afe440x_reg_info { | |||
116 | .storagebits = 32, \ | 100 | .storagebits = 32, \ |
117 | .endianness = IIO_CPU, \ | 101 | .endianness = IIO_CPU, \ |
118 | }, \ | 102 | }, \ |
119 | .extend_name = _name, \ | ||
120 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | 103 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
121 | _mask, \ | 104 | _mask, \ |
105 | .indexed = true, \ | ||
122 | } | 106 | } |
123 | 107 | ||
124 | #define AFE440X_CURRENT_CHAN(_index, _name) \ | 108 | #define AFE440X_CURRENT_CHAN(_index) \ |
125 | { \ | 109 | { \ |
126 | .type = IIO_CURRENT, \ | 110 | .type = IIO_CURRENT, \ |
127 | .channel = _index, \ | 111 | .channel = _index, \ |
128 | .address = _index, \ | 112 | .address = _index, \ |
129 | .scan_index = _index, \ | 113 | .scan_index = -1, \ |
130 | .extend_name = _name, \ | ||
131 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | 114 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
132 | BIT(IIO_CHAN_INFO_SCALE), \ | 115 | BIT(IIO_CHAN_INFO_SCALE), \ |
116 | .indexed = true, \ | ||
133 | .output = true, \ | 117 | .output = true, \ |
134 | } | 118 | } |
135 | 119 | ||
136 | enum afe440x_reg_type { | ||
137 | SIMPLE, | ||
138 | RESISTANCE, | ||
139 | CAPACITANCE, | ||
140 | }; | ||
141 | |||
142 | struct afe440x_val_table { | 120 | struct afe440x_val_table { |
143 | int integer; | 121 | int integer; |
144 | int fract; | 122 | int fract; |
@@ -164,10 +142,7 @@ static DEVICE_ATTR_RO(_name) | |||
164 | 142 | ||
165 | struct afe440x_attr { | 143 | struct afe440x_attr { |
166 | struct device_attribute dev_attr; | 144 | struct device_attribute dev_attr; |
167 | unsigned int reg; | 145 | unsigned int field; |
168 | unsigned int shift; | ||
169 | unsigned int mask; | ||
170 | enum afe440x_reg_type type; | ||
171 | const struct afe440x_val_table *val_table; | 146 | const struct afe440x_val_table *val_table; |
172 | unsigned int table_size; | 147 | unsigned int table_size; |
173 | }; | 148 | }; |
@@ -175,17 +150,14 @@ struct afe440x_attr { | |||
175 | #define to_afe440x_attr(_dev_attr) \ | 150 | #define to_afe440x_attr(_dev_attr) \ |
176 | container_of(_dev_attr, struct afe440x_attr, dev_attr) | 151 | container_of(_dev_attr, struct afe440x_attr, dev_attr) |
177 | 152 | ||
178 | #define AFE440X_ATTR(_name, _reg, _field, _type, _table, _size) \ | 153 | #define AFE440X_ATTR(_name, _field, _table) \ |
179 | struct afe440x_attr afe440x_attr_##_name = { \ | 154 | struct afe440x_attr afe440x_attr_##_name = { \ |
180 | .dev_attr = __ATTR(_name, (S_IRUGO | S_IWUSR), \ | 155 | .dev_attr = __ATTR(_name, (S_IRUGO | S_IWUSR), \ |
181 | afe440x_show_register, \ | 156 | afe440x_show_register, \ |
182 | afe440x_store_register), \ | 157 | afe440x_store_register), \ |
183 | .reg = _reg, \ | 158 | .field = _field, \ |
184 | .shift = _field ## _SHIFT, \ | ||
185 | .mask = _field ## _MASK, \ | ||
186 | .type = _type, \ | ||
187 | .val_table = _table, \ | 159 | .val_table = _table, \ |
188 | .table_size = _size, \ | 160 | .table_size = ARRAY_SIZE(_table), \ |
189 | } | 161 | } |
190 | 162 | ||
191 | #endif /* _AFE440X_H */ | 163 | #endif /* _AFE440X_H */ |
diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index 3be6d209a159..8de39bd349f9 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c | |||
@@ -278,6 +278,7 @@ static const struct i2c_device_id am2315_i2c_id[] = { | |||
278 | {"am2315", 0}, | 278 | {"am2315", 0}, |
279 | {} | 279 | {} |
280 | }; | 280 | }; |
281 | MODULE_DEVICE_TABLE(i2c, am2315_i2c_id); | ||
281 | 282 | ||
282 | static const struct acpi_device_id am2315_acpi_id[] = { | 283 | static const struct acpi_device_id am2315_acpi_id[] = { |
283 | {"AOS2315", 0}, | 284 | {"AOS2315", 0}, |
diff --git a/drivers/iio/humidity/htu21.c b/drivers/iio/humidity/htu21.c index 11cbc38b450f..0fbbd8c40894 100644 --- a/drivers/iio/humidity/htu21.c +++ b/drivers/iio/humidity/htu21.c | |||
@@ -236,6 +236,7 @@ static const struct i2c_device_id htu21_id[] = { | |||
236 | {"ms8607-humidity", MS8607}, | 236 | {"ms8607-humidity", MS8607}, |
237 | {} | 237 | {} |
238 | }; | 238 | }; |
239 | MODULE_DEVICE_TABLE(i2c, htu21_id); | ||
239 | 240 | ||
240 | static struct i2c_driver htu21_driver = { | 241 | static struct i2c_driver htu21_driver = { |
241 | .probe = htu21_probe, | 242 | .probe = htu21_probe, |
diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c index 0bf92b06d7d8..914e2e7971be 100644 --- a/drivers/iio/imu/bmi160/bmi160_core.c +++ b/drivers/iio/imu/bmi160/bmi160_core.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/iio/triggered_buffer.h> | 20 | #include <linux/iio/triggered_buffer.h> |
21 | #include <linux/iio/trigger_consumer.h> | 21 | #include <linux/iio/trigger_consumer.h> |
22 | #include <linux/iio/buffer.h> | 22 | #include <linux/iio/buffer.h> |
23 | #include <linux/iio/sysfs.h> | ||
23 | 24 | ||
24 | #include "bmi160.h" | 25 | #include "bmi160.h" |
25 | 26 | ||
@@ -466,10 +467,36 @@ static int bmi160_write_raw(struct iio_dev *indio_dev, | |||
466 | return 0; | 467 | return 0; |
467 | } | 468 | } |
468 | 469 | ||
470 | static | ||
471 | IIO_CONST_ATTR(in_accel_sampling_frequency_available, | ||
472 | "0.78125 1.5625 3.125 6.25 12.5 25 50 100 200 400 800 1600"); | ||
473 | static | ||
474 | IIO_CONST_ATTR(in_anglvel_sampling_frequency_available, | ||
475 | "25 50 100 200 400 800 1600 3200"); | ||
476 | static | ||
477 | IIO_CONST_ATTR(in_accel_scale_available, | ||
478 | "0.000598 0.001197 0.002394 0.004788"); | ||
479 | static | ||
480 | IIO_CONST_ATTR(in_anglvel_scale_available, | ||
481 | "0.001065 0.000532 0.000266 0.000133 0.000066"); | ||
482 | |||
483 | static struct attribute *bmi160_attrs[] = { | ||
484 | &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr, | ||
485 | &iio_const_attr_in_anglvel_sampling_frequency_available.dev_attr.attr, | ||
486 | &iio_const_attr_in_accel_scale_available.dev_attr.attr, | ||
487 | &iio_const_attr_in_anglvel_scale_available.dev_attr.attr, | ||
488 | NULL, | ||
489 | }; | ||
490 | |||
491 | static const struct attribute_group bmi160_attrs_group = { | ||
492 | .attrs = bmi160_attrs, | ||
493 | }; | ||
494 | |||
469 | static const struct iio_info bmi160_info = { | 495 | static const struct iio_info bmi160_info = { |
470 | .driver_module = THIS_MODULE, | 496 | .driver_module = THIS_MODULE, |
471 | .read_raw = bmi160_read_raw, | 497 | .read_raw = bmi160_read_raw, |
472 | .write_raw = bmi160_write_raw, | 498 | .write_raw = bmi160_write_raw, |
499 | .attrs = &bmi160_attrs_group, | ||
473 | }; | 500 | }; |
474 | 501 | ||
475 | static const char *bmi160_match_acpi_device(struct device *dev) | 502 | static const char *bmi160_match_acpi_device(struct device *dev) |
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index e6319a9346b2..2a85bd888619 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c | |||
@@ -80,6 +80,7 @@ static const char * const iio_chan_type_name_spec[] = { | |||
80 | [IIO_RESISTANCE] = "resistance", | 80 | [IIO_RESISTANCE] = "resistance", |
81 | [IIO_PH] = "ph", | 81 | [IIO_PH] = "ph", |
82 | [IIO_UVINDEX] = "uvindex", | 82 | [IIO_UVINDEX] = "uvindex", |
83 | [IIO_ELECTRICALCONDUCTIVITY] = "electricalconductivity", | ||
83 | }; | 84 | }; |
84 | 85 | ||
85 | static const char * const iio_modifier_names[] = { | 86 | static const char * const iio_modifier_names[] = { |
diff --git a/drivers/iio/industrialio-sw-device.c b/drivers/iio/industrialio-sw-device.c new file mode 100644 index 000000000000..81b49cfca452 --- /dev/null +++ b/drivers/iio/industrialio-sw-device.c | |||
@@ -0,0 +1,182 @@ | |||
1 | /* | ||
2 | * The Industrial I/O core, software IIO devices functions | ||
3 | * | ||
4 | * Copyright (c) 2016 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/kmod.h> | ||
14 | #include <linux/list.h> | ||
15 | #include <linux/slab.h> | ||
16 | |||
17 | #include <linux/iio/sw_device.h> | ||
18 | #include <linux/iio/configfs.h> | ||
19 | #include <linux/configfs.h> | ||
20 | |||
21 | static struct config_group *iio_devices_group; | ||
22 | static struct config_item_type iio_device_type_group_type; | ||
23 | |||
24 | static struct config_item_type iio_devices_group_type = { | ||
25 | .ct_owner = THIS_MODULE, | ||
26 | }; | ||
27 | |||
28 | static LIST_HEAD(iio_device_types_list); | ||
29 | static DEFINE_MUTEX(iio_device_types_lock); | ||
30 | |||
31 | static | ||
32 | struct iio_sw_device_type *__iio_find_sw_device_type(const char *name, | ||
33 | unsigned len) | ||
34 | { | ||
35 | struct iio_sw_device_type *d = NULL, *iter; | ||
36 | |||
37 | list_for_each_entry(iter, &iio_device_types_list, list) | ||
38 | if (!strcmp(iter->name, name)) { | ||
39 | d = iter; | ||
40 | break; | ||
41 | } | ||
42 | |||
43 | return d; | ||
44 | } | ||
45 | |||
46 | int iio_register_sw_device_type(struct iio_sw_device_type *d) | ||
47 | { | ||
48 | struct iio_sw_device_type *iter; | ||
49 | int ret = 0; | ||
50 | |||
51 | mutex_lock(&iio_device_types_lock); | ||
52 | iter = __iio_find_sw_device_type(d->name, strlen(d->name)); | ||
53 | if (iter) | ||
54 | ret = -EBUSY; | ||
55 | else | ||
56 | list_add_tail(&d->list, &iio_device_types_list); | ||
57 | mutex_unlock(&iio_device_types_lock); | ||
58 | |||
59 | if (ret) | ||
60 | return ret; | ||
61 | |||
62 | d->group = configfs_register_default_group(iio_devices_group, d->name, | ||
63 | &iio_device_type_group_type); | ||
64 | if (IS_ERR(d->group)) | ||
65 | ret = PTR_ERR(d->group); | ||
66 | |||
67 | return ret; | ||
68 | } | ||
69 | EXPORT_SYMBOL(iio_register_sw_device_type); | ||
70 | |||
71 | void iio_unregister_sw_device_type(struct iio_sw_device_type *dt) | ||
72 | { | ||
73 | struct iio_sw_device_type *iter; | ||
74 | |||
75 | mutex_lock(&iio_device_types_lock); | ||
76 | iter = __iio_find_sw_device_type(dt->name, strlen(dt->name)); | ||
77 | if (iter) | ||
78 | list_del(&dt->list); | ||
79 | mutex_unlock(&iio_device_types_lock); | ||
80 | |||
81 | configfs_unregister_default_group(dt->group); | ||
82 | } | ||
83 | EXPORT_SYMBOL(iio_unregister_sw_device_type); | ||
84 | |||
85 | static | ||
86 | struct iio_sw_device_type *iio_get_sw_device_type(const char *name) | ||
87 | { | ||
88 | struct iio_sw_device_type *dt; | ||
89 | |||
90 | mutex_lock(&iio_device_types_lock); | ||
91 | dt = __iio_find_sw_device_type(name, strlen(name)); | ||
92 | if (dt && !try_module_get(dt->owner)) | ||
93 | dt = NULL; | ||
94 | mutex_unlock(&iio_device_types_lock); | ||
95 | |||
96 | return dt; | ||
97 | } | ||
98 | |||
99 | struct iio_sw_device *iio_sw_device_create(const char *type, const char *name) | ||
100 | { | ||
101 | struct iio_sw_device *d; | ||
102 | struct iio_sw_device_type *dt; | ||
103 | |||
104 | dt = iio_get_sw_device_type(type); | ||
105 | if (!dt) { | ||
106 | pr_err("Invalid device type: %s\n", type); | ||
107 | return ERR_PTR(-EINVAL); | ||
108 | } | ||
109 | d = dt->ops->probe(name); | ||
110 | if (IS_ERR(d)) | ||
111 | goto out_module_put; | ||
112 | |||
113 | d->device_type = dt; | ||
114 | |||
115 | return d; | ||
116 | out_module_put: | ||
117 | module_put(dt->owner); | ||
118 | return d; | ||
119 | } | ||
120 | EXPORT_SYMBOL(iio_sw_device_create); | ||
121 | |||
122 | void iio_sw_device_destroy(struct iio_sw_device *d) | ||
123 | { | ||
124 | struct iio_sw_device_type *dt = d->device_type; | ||
125 | |||
126 | dt->ops->remove(d); | ||
127 | module_put(dt->owner); | ||
128 | } | ||
129 | EXPORT_SYMBOL(iio_sw_device_destroy); | ||
130 | |||
131 | static struct config_group *device_make_group(struct config_group *group, | ||
132 | const char *name) | ||
133 | { | ||
134 | struct iio_sw_device *d; | ||
135 | |||
136 | d = iio_sw_device_create(group->cg_item.ci_name, name); | ||
137 | if (IS_ERR(d)) | ||
138 | return ERR_CAST(d); | ||
139 | |||
140 | config_item_set_name(&d->group.cg_item, "%s", name); | ||
141 | |||
142 | return &d->group; | ||
143 | } | ||
144 | |||
145 | static void device_drop_group(struct config_group *group, | ||
146 | struct config_item *item) | ||
147 | { | ||
148 | struct iio_sw_device *d = to_iio_sw_device(item); | ||
149 | |||
150 | iio_sw_device_destroy(d); | ||
151 | config_item_put(item); | ||
152 | } | ||
153 | |||
154 | static struct configfs_group_operations device_ops = { | ||
155 | .make_group = &device_make_group, | ||
156 | .drop_item = &device_drop_group, | ||
157 | }; | ||
158 | |||
159 | static struct config_item_type iio_device_type_group_type = { | ||
160 | .ct_group_ops = &device_ops, | ||
161 | .ct_owner = THIS_MODULE, | ||
162 | }; | ||
163 | |||
164 | static int __init iio_sw_device_init(void) | ||
165 | { | ||
166 | iio_devices_group = | ||
167 | configfs_register_default_group(&iio_configfs_subsys.su_group, | ||
168 | "devices", | ||
169 | &iio_devices_group_type); | ||
170 | return PTR_ERR_OR_ZERO(iio_devices_group); | ||
171 | } | ||
172 | module_init(iio_sw_device_init); | ||
173 | |||
174 | static void __exit iio_sw_device_exit(void) | ||
175 | { | ||
176 | configfs_unregister_default_group(iio_devices_group); | ||
177 | } | ||
178 | module_exit(iio_sw_device_exit); | ||
179 | |||
180 | MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); | ||
181 | MODULE_DESCRIPTION("Industrial I/O software devices support"); | ||
182 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index ae2806aafb72..672911293987 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c | |||
@@ -68,6 +68,10 @@ int iio_trigger_register(struct iio_trigger *trig_info) | |||
68 | { | 68 | { |
69 | int ret; | 69 | int ret; |
70 | 70 | ||
71 | /* trig_info->ops is required for the module member */ | ||
72 | if (!trig_info->ops) | ||
73 | return -EINVAL; | ||
74 | |||
71 | trig_info->id = ida_simple_get(&iio_trigger_ida, 0, 0, GFP_KERNEL); | 75 | trig_info->id = ida_simple_get(&iio_trigger_ida, 0, 0, GFP_KERNEL); |
72 | if (trig_info->id < 0) | 76 | if (trig_info->id < 0) |
73 | return trig_info->id; | 77 | return trig_info->id; |
@@ -164,8 +168,7 @@ EXPORT_SYMBOL(iio_trigger_poll_chained); | |||
164 | 168 | ||
165 | void iio_trigger_notify_done(struct iio_trigger *trig) | 169 | void iio_trigger_notify_done(struct iio_trigger *trig) |
166 | { | 170 | { |
167 | if (atomic_dec_and_test(&trig->use_count) && trig->ops && | 171 | if (atomic_dec_and_test(&trig->use_count) && trig->ops->try_reenable) |
168 | trig->ops->try_reenable) | ||
169 | if (trig->ops->try_reenable(trig)) | 172 | if (trig->ops->try_reenable(trig)) |
170 | /* Missed an interrupt so launch new poll now */ | 173 | /* Missed an interrupt so launch new poll now */ |
171 | iio_trigger_poll(trig); | 174 | iio_trigger_poll(trig); |
@@ -219,7 +222,7 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig, | |||
219 | return ret; | 222 | return ret; |
220 | } | 223 | } |
221 | 224 | ||
222 | if (trig->ops && trig->ops->set_trigger_state && notinuse) { | 225 | if (trig->ops->set_trigger_state && notinuse) { |
223 | ret = trig->ops->set_trigger_state(trig, true); | 226 | ret = trig->ops->set_trigger_state(trig, true); |
224 | if (ret < 0) | 227 | if (ret < 0) |
225 | module_put(pf->indio_dev->info->driver_module); | 228 | module_put(pf->indio_dev->info->driver_module); |
@@ -236,7 +239,7 @@ static int iio_trigger_detach_poll_func(struct iio_trigger *trig, | |||
236 | = (bitmap_weight(trig->pool, | 239 | = (bitmap_weight(trig->pool, |
237 | CONFIG_IIO_CONSUMERS_PER_TRIGGER) | 240 | CONFIG_IIO_CONSUMERS_PER_TRIGGER) |
238 | == 1); | 241 | == 1); |
239 | if (trig->ops && trig->ops->set_trigger_state && no_other_users) { | 242 | if (trig->ops->set_trigger_state && no_other_users) { |
240 | ret = trig->ops->set_trigger_state(trig, false); | 243 | ret = trig->ops->set_trigger_state(trig, false); |
241 | if (ret) | 244 | if (ret) |
242 | return ret; | 245 | return ret; |
@@ -358,7 +361,7 @@ static ssize_t iio_trigger_write_current(struct device *dev, | |||
358 | return ret; | 361 | return ret; |
359 | } | 362 | } |
360 | 363 | ||
361 | if (trig && trig->ops && trig->ops->validate_device) { | 364 | if (trig && trig->ops->validate_device) { |
362 | ret = trig->ops->validate_device(trig, indio_dev); | 365 | ret = trig->ops->validate_device(trig, indio_dev); |
363 | if (ret) | 366 | if (ret) |
364 | return ret; | 367 | return ret; |
diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c index 99a62816c3b4..e8a8931b4f50 100644 --- a/drivers/iio/light/jsa1212.c +++ b/drivers/iio/light/jsa1212.c | |||
@@ -325,9 +325,6 @@ static int jsa1212_probe(struct i2c_client *client, | |||
325 | struct regmap *regmap; | 325 | struct regmap *regmap; |
326 | int ret; | 326 | int ret; |
327 | 327 | ||
328 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
329 | return -EOPNOTSUPP; | ||
330 | |||
331 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | 328 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); |
332 | if (!indio_dev) | 329 | if (!indio_dev) |
333 | return -ENOMEM; | 330 | return -ENOMEM; |
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index 84e6559ccc65..1f842abcb4a4 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig | |||
@@ -44,6 +44,7 @@ config BMC150_MAGN_I2C | |||
44 | This driver is only implementing magnetometer part, which has | 44 | This driver is only implementing magnetometer part, which has |
45 | its own address and register map. | 45 | its own address and register map. |
46 | 46 | ||
47 | This driver also supports I2C Bosch BMC156 and BMM150 chips. | ||
47 | To compile this driver as a module, choose M here: the module will be | 48 | To compile this driver as a module, choose M here: the module will be |
48 | called bmc150_magn_i2c. | 49 | called bmc150_magn_i2c. |
49 | 50 | ||
@@ -60,6 +61,7 @@ config BMC150_MAGN_SPI | |||
60 | This driver is only implementing magnetometer part, which has | 61 | This driver is only implementing magnetometer part, which has |
61 | its own address and register map. | 62 | its own address and register map. |
62 | 63 | ||
64 | This driver also supports SPI Bosch BMC156 and BMM150 chips. | ||
63 | To compile this driver as a module, choose M here: the module will be | 65 | To compile this driver as a module, choose M here: the module will be |
64 | called bmc150_magn_spi. | 66 | called bmc150_magn_spi. |
65 | 67 | ||
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 609a2c401b5d..57d3654d7caf 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c | |||
@@ -430,8 +430,8 @@ static int ak8975_who_i_am(struct i2c_client *client, | |||
430 | * AK8975 | DEVICE_ID | NA | 430 | * AK8975 | DEVICE_ID | NA |
431 | * AK8963 | DEVICE_ID | NA | 431 | * AK8963 | DEVICE_ID | NA |
432 | */ | 432 | */ |
433 | ret = i2c_smbus_read_i2c_block_data(client, AK09912_REG_WIA1, | 433 | ret = i2c_smbus_read_i2c_block_data_or_emulated( |
434 | 2, wia_val); | 434 | client, AK09912_REG_WIA1, 2, wia_val); |
435 | if (ret < 0) { | 435 | if (ret < 0) { |
436 | dev_err(&client->dev, "Error reading WIA\n"); | 436 | dev_err(&client->dev, "Error reading WIA\n"); |
437 | return ret; | 437 | return ret; |
@@ -543,9 +543,9 @@ static int ak8975_setup(struct i2c_client *client) | |||
543 | } | 543 | } |
544 | 544 | ||
545 | /* Get asa data and store in the device data. */ | 545 | /* Get asa data and store in the device data. */ |
546 | ret = i2c_smbus_read_i2c_block_data(client, | 546 | ret = i2c_smbus_read_i2c_block_data_or_emulated( |
547 | data->def->ctrl_regs[ASA_BASE], | 547 | client, data->def->ctrl_regs[ASA_BASE], |
548 | 3, data->asa); | 548 | 3, data->asa); |
549 | if (ret < 0) { | 549 | if (ret < 0) { |
550 | dev_err(&client->dev, "Not able to read asa data\n"); | 550 | dev_err(&client->dev, "Not able to read asa data\n"); |
551 | return ret; | 551 | return ret; |
@@ -686,6 +686,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) | |||
686 | struct ak8975_data *data = iio_priv(indio_dev); | 686 | struct ak8975_data *data = iio_priv(indio_dev); |
687 | const struct i2c_client *client = data->client; | 687 | const struct i2c_client *client = data->client; |
688 | const struct ak_def *def = data->def; | 688 | const struct ak_def *def = data->def; |
689 | u16 buff; | ||
689 | int ret; | 690 | int ret; |
690 | 691 | ||
691 | mutex_lock(&data->lock); | 692 | mutex_lock(&data->lock); |
@@ -694,14 +695,17 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) | |||
694 | if (ret) | 695 | if (ret) |
695 | goto exit; | 696 | goto exit; |
696 | 697 | ||
697 | ret = i2c_smbus_read_word_data(client, def->data_regs[index]); | 698 | ret = i2c_smbus_read_i2c_block_data_or_emulated( |
699 | client, def->data_regs[index], | ||
700 | sizeof(buff), (u8*)&buff); | ||
698 | if (ret < 0) | 701 | if (ret < 0) |
699 | goto exit; | 702 | goto exit; |
700 | 703 | ||
701 | mutex_unlock(&data->lock); | 704 | mutex_unlock(&data->lock); |
702 | 705 | ||
703 | /* Clamp to valid range. */ | 706 | /* Swap bytes and convert to valid range. */ |
704 | *val = clamp_t(s16, ret, -def->range, def->range); | 707 | buff = le16_to_cpu(buff); |
708 | *val = clamp_t(s16, buff, -def->range, def->range); | ||
705 | return IIO_VAL_INT; | 709 | return IIO_VAL_INT; |
706 | 710 | ||
707 | exit: | 711 | exit: |
diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c index eddc7f0d0096..ee05722587aa 100644 --- a/drivers/iio/magnetometer/bmc150_magn_i2c.c +++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * 3-axis magnetometer driver supporting following I2C Bosch-Sensortec chips: | 2 | * 3-axis magnetometer driver supporting following I2C Bosch-Sensortec chips: |
3 | * - BMC150 | 3 | * - BMC150 |
4 | * - BMC156 | 4 | * - BMC156 |
5 | * - BMM150 | ||
5 | * | 6 | * |
6 | * Copyright (c) 2016, Intel Corporation. | 7 | * Copyright (c) 2016, Intel Corporation. |
7 | * | 8 | * |
@@ -49,6 +50,7 @@ static int bmc150_magn_i2c_remove(struct i2c_client *client) | |||
49 | static const struct acpi_device_id bmc150_magn_acpi_match[] = { | 50 | static const struct acpi_device_id bmc150_magn_acpi_match[] = { |
50 | {"BMC150B", 0}, | 51 | {"BMC150B", 0}, |
51 | {"BMC156B", 0}, | 52 | {"BMC156B", 0}, |
53 | {"BMM150B", 0}, | ||
52 | {}, | 54 | {}, |
53 | }; | 55 | }; |
54 | MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); | 56 | MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); |
@@ -56,6 +58,7 @@ MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); | |||
56 | static const struct i2c_device_id bmc150_magn_i2c_id[] = { | 58 | static const struct i2c_device_id bmc150_magn_i2c_id[] = { |
57 | {"bmc150_magn", 0}, | 59 | {"bmc150_magn", 0}, |
58 | {"bmc156_magn", 0}, | 60 | {"bmc156_magn", 0}, |
61 | {"bmm150_magn", 0}, | ||
59 | {} | 62 | {} |
60 | }; | 63 | }; |
61 | MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id); | 64 | MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id); |
diff --git a/drivers/iio/magnetometer/bmc150_magn_spi.c b/drivers/iio/magnetometer/bmc150_magn_spi.c index c4c738a07695..7d4152d4d01e 100644 --- a/drivers/iio/magnetometer/bmc150_magn_spi.c +++ b/drivers/iio/magnetometer/bmc150_magn_spi.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * 3-axis magnetometer driver support following SPI Bosch-Sensortec chips: | 2 | * 3-axis magnetometer driver support following SPI Bosch-Sensortec chips: |
3 | * - BMC150 | 3 | * - BMC150 |
4 | * - BMC156 | 4 | * - BMC156 |
5 | * - BMM150 | ||
5 | * | 6 | * |
6 | * Copyright (c) 2016, Intel Corporation. | 7 | * Copyright (c) 2016, Intel Corporation. |
7 | * | 8 | * |
@@ -41,6 +42,7 @@ static int bmc150_magn_spi_remove(struct spi_device *spi) | |||
41 | static const struct spi_device_id bmc150_magn_spi_id[] = { | 42 | static const struct spi_device_id bmc150_magn_spi_id[] = { |
42 | {"bmc150_magn", 0}, | 43 | {"bmc150_magn", 0}, |
43 | {"bmc156_magn", 0}, | 44 | {"bmc156_magn", 0}, |
45 | {"bmm150_magn", 0}, | ||
44 | {} | 46 | {} |
45 | }; | 47 | }; |
46 | MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id); | 48 | MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id); |
@@ -48,6 +50,7 @@ MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id); | |||
48 | static const struct acpi_device_id bmc150_magn_acpi_match[] = { | 50 | static const struct acpi_device_id bmc150_magn_acpi_match[] = { |
49 | {"BMC150B", 0}, | 51 | {"BMC150B", 0}, |
50 | {"BMC156B", 0}, | 52 | {"BMC156B", 0}, |
53 | {"BMM150B", 0}, | ||
51 | {}, | 54 | {}, |
52 | }; | 55 | }; |
53 | MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); | 56 | MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); |
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 62036d2a9956..7c94adc3ff1d 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c | |||
@@ -588,13 +588,15 @@ int st_magn_common_probe(struct iio_dev *indio_dev) | |||
588 | indio_dev->info = &magn_info; | 588 | indio_dev->info = &magn_info; |
589 | mutex_init(&mdata->tb.buf_lock); | 589 | mutex_init(&mdata->tb.buf_lock); |
590 | 590 | ||
591 | st_sensors_power_enable(indio_dev); | 591 | err = st_sensors_power_enable(indio_dev); |
592 | if (err) | ||
593 | return err; | ||
592 | 594 | ||
593 | err = st_sensors_check_device_support(indio_dev, | 595 | err = st_sensors_check_device_support(indio_dev, |
594 | ARRAY_SIZE(st_magn_sensors_settings), | 596 | ARRAY_SIZE(st_magn_sensors_settings), |
595 | st_magn_sensors_settings); | 597 | st_magn_sensors_settings); |
596 | if (err < 0) | 598 | if (err < 0) |
597 | return err; | 599 | goto st_magn_power_off; |
598 | 600 | ||
599 | mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS; | 601 | mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS; |
600 | mdata->multiread_bit = mdata->sensor_settings->multi_read_bit; | 602 | mdata->multiread_bit = mdata->sensor_settings->multi_read_bit; |
@@ -607,11 +609,11 @@ int st_magn_common_probe(struct iio_dev *indio_dev) | |||
607 | 609 | ||
608 | err = st_sensors_init_sensor(indio_dev, NULL); | 610 | err = st_sensors_init_sensor(indio_dev, NULL); |
609 | if (err < 0) | 611 | if (err < 0) |
610 | return err; | 612 | goto st_magn_power_off; |
611 | 613 | ||
612 | err = st_magn_allocate_ring(indio_dev); | 614 | err = st_magn_allocate_ring(indio_dev); |
613 | if (err < 0) | 615 | if (err < 0) |
614 | return err; | 616 | goto st_magn_power_off; |
615 | 617 | ||
616 | if (irq > 0) { | 618 | if (irq > 0) { |
617 | err = st_sensors_allocate_trigger(indio_dev, | 619 | err = st_sensors_allocate_trigger(indio_dev, |
@@ -634,6 +636,8 @@ st_magn_device_register_error: | |||
634 | st_sensors_deallocate_trigger(indio_dev); | 636 | st_sensors_deallocate_trigger(indio_dev); |
635 | st_magn_probe_trigger_error: | 637 | st_magn_probe_trigger_error: |
636 | st_magn_deallocate_ring(indio_dev); | 638 | st_magn_deallocate_ring(indio_dev); |
639 | st_magn_power_off: | ||
640 | st_sensors_power_disable(indio_dev); | ||
637 | 641 | ||
638 | return err; | 642 | return err; |
639 | } | 643 | } |
diff --git a/drivers/iio/potentiometer/Kconfig b/drivers/iio/potentiometer/Kconfig index 6acb23810bb4..0941c8d490a0 100644 --- a/drivers/iio/potentiometer/Kconfig +++ b/drivers/iio/potentiometer/Kconfig | |||
@@ -15,6 +15,17 @@ config DS1803 | |||
15 | To compile this driver as a module, choose M here: the | 15 | To compile this driver as a module, choose M here: the |
16 | module will be called ds1803. | 16 | module will be called ds1803. |
17 | 17 | ||
18 | config MAX5487 | ||
19 | tristate "Maxim MAX5487/MAX5488/MAX5489 Digital Potentiometer driver" | ||
20 | depends on SPI | ||
21 | help | ||
22 | Say yes here to build support for the Maxim | ||
23 | MAX5487, MAX5488, MAX5489 digital potentiometer | ||
24 | chips. | ||
25 | |||
26 | To compile this driver as a module, choose M here: the | ||
27 | module will be called max5487. | ||
28 | |||
18 | config MCP4131 | 29 | config MCP4131 |
19 | tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver" | 30 | tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver" |
20 | depends on SPI | 31 | depends on SPI |
diff --git a/drivers/iio/potentiometer/Makefile b/drivers/iio/potentiometer/Makefile index 6007faa2fb02..8adb58f38c0b 100644 --- a/drivers/iio/potentiometer/Makefile +++ b/drivers/iio/potentiometer/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_DS1803) += ds1803.o | 6 | obj-$(CONFIG_DS1803) += ds1803.o |
7 | obj-$(CONFIG_MAX5487) += max5487.o | ||
7 | obj-$(CONFIG_MCP4131) += mcp4131.o | 8 | obj-$(CONFIG_MCP4131) += mcp4131.o |
8 | obj-$(CONFIG_MCP4531) += mcp4531.o | 9 | obj-$(CONFIG_MCP4531) += mcp4531.o |
9 | obj-$(CONFIG_TPL0102) += tpl0102.o | 10 | obj-$(CONFIG_TPL0102) += tpl0102.o |
diff --git a/drivers/iio/potentiometer/max5487.c b/drivers/iio/potentiometer/max5487.c new file mode 100644 index 000000000000..6c50939a2e83 --- /dev/null +++ b/drivers/iio/potentiometer/max5487.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * max5487.c - Support for MAX5487, MAX5488, MAX5489 digital potentiometers | ||
3 | * | ||
4 | * Copyright (C) 2016 Cristina-Gabriela Moraru <cristina.moraru09@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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/spi/spi.h> | ||
13 | #include <linux/acpi.h> | ||
14 | |||
15 | #include <linux/iio/sysfs.h> | ||
16 | #include <linux/iio/iio.h> | ||
17 | |||
18 | #define MAX5487_WRITE_WIPER_A (0x01 << 8) | ||
19 | #define MAX5487_WRITE_WIPER_B (0x02 << 8) | ||
20 | |||
21 | /* copy both wiper regs to NV regs */ | ||
22 | #define MAX5487_COPY_AB_TO_NV (0x23 << 8) | ||
23 | /* copy both NV regs to wiper regs */ | ||
24 | #define MAX5487_COPY_NV_TO_AB (0x33 << 8) | ||
25 | |||
26 | #define MAX5487_MAX_POS 255 | ||
27 | |||
28 | struct max5487_data { | ||
29 | struct spi_device *spi; | ||
30 | int kohms; | ||
31 | }; | ||
32 | |||
33 | #define MAX5487_CHANNEL(ch, addr) { \ | ||
34 | .type = IIO_RESISTANCE, \ | ||
35 | .indexed = 1, \ | ||
36 | .output = 1, \ | ||
37 | .channel = ch, \ | ||
38 | .address = addr, \ | ||
39 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
40 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | ||
41 | } | ||
42 | |||
43 | static const struct iio_chan_spec max5487_channels[] = { | ||
44 | MAX5487_CHANNEL(0, MAX5487_WRITE_WIPER_A), | ||
45 | MAX5487_CHANNEL(1, MAX5487_WRITE_WIPER_B), | ||
46 | }; | ||
47 | |||
48 | static int max5487_write_cmd(struct spi_device *spi, u16 cmd) | ||
49 | { | ||
50 | return spi_write(spi, (const void *) &cmd, sizeof(u16)); | ||
51 | } | ||
52 | |||
53 | static int max5487_read_raw(struct iio_dev *indio_dev, | ||
54 | struct iio_chan_spec const *chan, | ||
55 | int *val, int *val2, long mask) | ||
56 | { | ||
57 | struct max5487_data *data = iio_priv(indio_dev); | ||
58 | |||
59 | if (mask != IIO_CHAN_INFO_SCALE) | ||
60 | return -EINVAL; | ||
61 | |||
62 | *val = 1000 * data->kohms; | ||
63 | *val2 = MAX5487_MAX_POS; | ||
64 | |||
65 | return IIO_VAL_FRACTIONAL; | ||
66 | } | ||
67 | |||
68 | static int max5487_write_raw(struct iio_dev *indio_dev, | ||
69 | struct iio_chan_spec const *chan, | ||
70 | int val, int val2, long mask) | ||
71 | { | ||
72 | struct max5487_data *data = iio_priv(indio_dev); | ||
73 | |||
74 | if (mask != IIO_CHAN_INFO_RAW) | ||
75 | return -EINVAL; | ||
76 | |||
77 | if (val < 0 || val > MAX5487_MAX_POS) | ||
78 | return -EINVAL; | ||
79 | |||
80 | return max5487_write_cmd(data->spi, chan->address | val); | ||
81 | } | ||
82 | |||
83 | static const struct iio_info max5487_info = { | ||
84 | .read_raw = max5487_read_raw, | ||
85 | .write_raw = max5487_write_raw, | ||
86 | .driver_module = THIS_MODULE, | ||
87 | }; | ||
88 | |||
89 | static int max5487_spi_probe(struct spi_device *spi) | ||
90 | { | ||
91 | struct iio_dev *indio_dev; | ||
92 | struct max5487_data *data; | ||
93 | const struct spi_device_id *id = spi_get_device_id(spi); | ||
94 | int ret; | ||
95 | |||
96 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data)); | ||
97 | if (!indio_dev) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | dev_set_drvdata(&spi->dev, indio_dev); | ||
101 | data = iio_priv(indio_dev); | ||
102 | |||
103 | data->spi = spi; | ||
104 | data->kohms = id->driver_data; | ||
105 | |||
106 | indio_dev->info = &max5487_info; | ||
107 | indio_dev->name = id->name; | ||
108 | indio_dev->dev.parent = &spi->dev; | ||
109 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
110 | indio_dev->channels = max5487_channels; | ||
111 | indio_dev->num_channels = ARRAY_SIZE(max5487_channels); | ||
112 | |||
113 | /* restore both wiper regs from NV regs */ | ||
114 | ret = max5487_write_cmd(data->spi, MAX5487_COPY_NV_TO_AB); | ||
115 | if (ret < 0) | ||
116 | return ret; | ||
117 | |||
118 | return iio_device_register(indio_dev); | ||
119 | } | ||
120 | |||
121 | static int max5487_spi_remove(struct spi_device *spi) | ||
122 | { | ||
123 | struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev); | ||
124 | |||
125 | iio_device_unregister(indio_dev); | ||
126 | |||
127 | /* save both wiper regs to NV regs */ | ||
128 | return max5487_write_cmd(spi, MAX5487_COPY_AB_TO_NV); | ||
129 | } | ||
130 | |||
131 | static const struct spi_device_id max5487_id[] = { | ||
132 | { "MAX5487", 10 }, | ||
133 | { "MAX5488", 50 }, | ||
134 | { "MAX5489", 100 }, | ||
135 | { } | ||
136 | }; | ||
137 | MODULE_DEVICE_TABLE(spi, max5487_id); | ||
138 | |||
139 | static const struct acpi_device_id max5487_acpi_match[] = { | ||
140 | { "MAX5487", 10 }, | ||
141 | { "MAX5488", 50 }, | ||
142 | { "MAX5489", 100 }, | ||
143 | { }, | ||
144 | }; | ||
145 | MODULE_DEVICE_TABLE(acpi, max5487_acpi_match); | ||
146 | |||
147 | static struct spi_driver max5487_driver = { | ||
148 | .driver = { | ||
149 | .name = "max5487", | ||
150 | .owner = THIS_MODULE, | ||
151 | .acpi_match_table = ACPI_PTR(max5487_acpi_match), | ||
152 | }, | ||
153 | .id_table = max5487_id, | ||
154 | .probe = max5487_spi_probe, | ||
155 | .remove = max5487_spi_remove | ||
156 | }; | ||
157 | module_spi_driver(max5487_driver); | ||
158 | |||
159 | MODULE_AUTHOR("Cristina-Gabriela Moraru <cristina.moraru09@gmail.com>"); | ||
160 | MODULE_DESCRIPTION("max5487 SPI driver"); | ||
161 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/iio/potentiometer/tpl0102.c b/drivers/iio/potentiometer/tpl0102.c index 5c304d42d713..7b6b54531ea2 100644 --- a/drivers/iio/potentiometer/tpl0102.c +++ b/drivers/iio/potentiometer/tpl0102.c | |||
@@ -116,10 +116,6 @@ static int tpl0102_probe(struct i2c_client *client, | |||
116 | struct tpl0102_data *data; | 116 | struct tpl0102_data *data; |
117 | struct iio_dev *indio_dev; | 117 | struct iio_dev *indio_dev; |
118 | 118 | ||
119 | if (!i2c_check_functionality(client->adapter, | ||
120 | I2C_FUNC_SMBUS_WORD_DATA)) | ||
121 | return -EOPNOTSUPP; | ||
122 | |||
123 | indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); | 119 | indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); |
124 | if (!indio_dev) | 120 | if (!indio_dev) |
125 | return -ENOMEM; | 121 | return -ENOMEM; |
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index cda9f128f3a4..8d654f671b6b 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig | |||
@@ -12,7 +12,8 @@ config BMP280 | |||
12 | select REGMAP_I2C | 12 | select REGMAP_I2C |
13 | help | 13 | help |
14 | Say yes here to build support for Bosch Sensortec BMP180 and BMP280 | 14 | Say yes here to build support for Bosch Sensortec BMP180 and BMP280 |
15 | pressure and temperature sensors. | 15 | pressure and temperature sensors. Also supports the BE280 with |
16 | an additional humidty sensor channel. | ||
16 | 17 | ||
17 | To compile this driver as a module, choose M here: the module | 18 | To compile this driver as a module, choose M here: the module |
18 | will be called bmp280. | 19 | will be called bmp280. |
@@ -130,7 +131,7 @@ config IIO_ST_PRESS | |||
130 | select IIO_TRIGGERED_BUFFER if (IIO_BUFFER) | 131 | select IIO_TRIGGERED_BUFFER if (IIO_BUFFER) |
131 | help | 132 | help |
132 | Say yes here to build support for STMicroelectronics pressure | 133 | Say yes here to build support for STMicroelectronics pressure |
133 | sensors: LPS001WP, LPS25H, LPS331AP. | 134 | sensors: LPS001WP, LPS25H, LPS331AP, LPS22HB. |
134 | 135 | ||
135 | This driver can also be built as a module. If so, these modules | 136 | This driver can also be built as a module. If so, these modules |
136 | will be created: | 137 | will be created: |
diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c index 2f1498e12bb2..1876b50cc84a 100644 --- a/drivers/iio/pressure/bmp280.c +++ b/drivers/iio/pressure/bmp280.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * Datasheet: | 10 | * Datasheet: |
11 | * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf | 11 | * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf |
12 | * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf | 12 | * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf |
13 | * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME280_DS001-11.pdf | ||
13 | */ | 14 | */ |
14 | 15 | ||
15 | #define pr_fmt(fmt) "bmp280: " fmt | 16 | #define pr_fmt(fmt) "bmp280: " fmt |
@@ -23,6 +24,8 @@ | |||
23 | #include <linux/iio/sysfs.h> | 24 | #include <linux/iio/sysfs.h> |
24 | 25 | ||
25 | /* BMP280 specific registers */ | 26 | /* BMP280 specific registers */ |
27 | #define BMP280_REG_HUMIDITY_LSB 0xFE | ||
28 | #define BMP280_REG_HUMIDITY_MSB 0xFD | ||
26 | #define BMP280_REG_TEMP_XLSB 0xFC | 29 | #define BMP280_REG_TEMP_XLSB 0xFC |
27 | #define BMP280_REG_TEMP_LSB 0xFB | 30 | #define BMP280_REG_TEMP_LSB 0xFB |
28 | #define BMP280_REG_TEMP_MSB 0xFA | 31 | #define BMP280_REG_TEMP_MSB 0xFA |
@@ -31,7 +34,17 @@ | |||
31 | #define BMP280_REG_PRESS_MSB 0xF7 | 34 | #define BMP280_REG_PRESS_MSB 0xF7 |
32 | 35 | ||
33 | #define BMP280_REG_CONFIG 0xF5 | 36 | #define BMP280_REG_CONFIG 0xF5 |
37 | #define BMP280_REG_CTRL_MEAS 0xF4 | ||
34 | #define BMP280_REG_STATUS 0xF3 | 38 | #define BMP280_REG_STATUS 0xF3 |
39 | #define BMP280_REG_CTRL_HUMIDITY 0xF2 | ||
40 | |||
41 | /* Due to non linear mapping, and data sizes we can't do a bulk read */ | ||
42 | #define BMP280_REG_COMP_H1 0xA1 | ||
43 | #define BMP280_REG_COMP_H2 0xE1 | ||
44 | #define BMP280_REG_COMP_H3 0xE3 | ||
45 | #define BMP280_REG_COMP_H4 0xE4 | ||
46 | #define BMP280_REG_COMP_H5 0xE5 | ||
47 | #define BMP280_REG_COMP_H6 0xE7 | ||
35 | 48 | ||
36 | #define BMP280_REG_COMP_TEMP_START 0x88 | 49 | #define BMP280_REG_COMP_TEMP_START 0x88 |
37 | #define BMP280_COMP_TEMP_REG_COUNT 6 | 50 | #define BMP280_COMP_TEMP_REG_COUNT 6 |
@@ -46,6 +59,15 @@ | |||
46 | #define BMP280_FILTER_8X (BIT(3) | BIT(2)) | 59 | #define BMP280_FILTER_8X (BIT(3) | BIT(2)) |
47 | #define BMP280_FILTER_16X BIT(4) | 60 | #define BMP280_FILTER_16X BIT(4) |
48 | 61 | ||
62 | #define BMP280_OSRS_HUMIDITY_MASK (BIT(2) | BIT(1) | BIT(0)) | ||
63 | #define BMP280_OSRS_HUMIDITIY_X(osrs_h) ((osrs_h) << 0) | ||
64 | #define BMP280_OSRS_HUMIDITY_SKIP 0 | ||
65 | #define BMP280_OSRS_HUMIDITY_1X BMP280_OSRS_HUMIDITIY_X(1) | ||
66 | #define BMP280_OSRS_HUMIDITY_2X BMP280_OSRS_HUMIDITIY_X(2) | ||
67 | #define BMP280_OSRS_HUMIDITY_4X BMP280_OSRS_HUMIDITIY_X(3) | ||
68 | #define BMP280_OSRS_HUMIDITY_8X BMP280_OSRS_HUMIDITIY_X(4) | ||
69 | #define BMP280_OSRS_HUMIDITY_16X BMP280_OSRS_HUMIDITIY_X(5) | ||
70 | |||
49 | #define BMP280_OSRS_TEMP_MASK (BIT(7) | BIT(6) | BIT(5)) | 71 | #define BMP280_OSRS_TEMP_MASK (BIT(7) | BIT(6) | BIT(5)) |
50 | #define BMP280_OSRS_TEMP_SKIP 0 | 72 | #define BMP280_OSRS_TEMP_SKIP 0 |
51 | #define BMP280_OSRS_TEMP_X(osrs_t) ((osrs_t) << 5) | 73 | #define BMP280_OSRS_TEMP_X(osrs_t) ((osrs_t) << 5) |
@@ -92,6 +114,7 @@ | |||
92 | 114 | ||
93 | #define BMP180_CHIP_ID 0x55 | 115 | #define BMP180_CHIP_ID 0x55 |
94 | #define BMP280_CHIP_ID 0x58 | 116 | #define BMP280_CHIP_ID 0x58 |
117 | #define BME280_CHIP_ID 0x60 | ||
95 | #define BMP280_SOFT_RESET_VAL 0xB6 | 118 | #define BMP280_SOFT_RESET_VAL 0xB6 |
96 | 119 | ||
97 | struct bmp280_data { | 120 | struct bmp280_data { |
@@ -103,6 +126,7 @@ struct bmp280_data { | |||
103 | /* log of base 2 of oversampling rate */ | 126 | /* log of base 2 of oversampling rate */ |
104 | u8 oversampling_press; | 127 | u8 oversampling_press; |
105 | u8 oversampling_temp; | 128 | u8 oversampling_temp; |
129 | u8 oversampling_humid; | ||
106 | 130 | ||
107 | /* | 131 | /* |
108 | * Carryover value from temperature conversion, used in pressure | 132 | * Carryover value from temperature conversion, used in pressure |
@@ -120,9 +144,13 @@ struct bmp280_chip_info { | |||
120 | const int *oversampling_press_avail; | 144 | const int *oversampling_press_avail; |
121 | int num_oversampling_press_avail; | 145 | int num_oversampling_press_avail; |
122 | 146 | ||
147 | const int *oversampling_humid_avail; | ||
148 | int num_oversampling_humid_avail; | ||
149 | |||
123 | int (*chip_config)(struct bmp280_data *); | 150 | int (*chip_config)(struct bmp280_data *); |
124 | int (*read_temp)(struct bmp280_data *, int *); | 151 | int (*read_temp)(struct bmp280_data *, int *); |
125 | int (*read_press)(struct bmp280_data *, int *, int *); | 152 | int (*read_press)(struct bmp280_data *, int *, int *); |
153 | int (*read_humid)(struct bmp280_data *, int *, int *); | ||
126 | }; | 154 | }; |
127 | 155 | ||
128 | /* | 156 | /* |
@@ -143,12 +171,18 @@ static const struct iio_chan_spec bmp280_channels[] = { | |||
143 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | | 171 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | |
144 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), | 172 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), |
145 | }, | 173 | }, |
174 | { | ||
175 | .type = IIO_HUMIDITYRELATIVE, | ||
176 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | | ||
177 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), | ||
178 | }, | ||
146 | }; | 179 | }; |
147 | 180 | ||
148 | static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg) | 181 | static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg) |
149 | { | 182 | { |
150 | switch (reg) { | 183 | switch (reg) { |
151 | case BMP280_REG_CONFIG: | 184 | case BMP280_REG_CONFIG: |
185 | case BMP280_REG_CTRL_HUMIDITY: | ||
152 | case BMP280_REG_CTRL_MEAS: | 186 | case BMP280_REG_CTRL_MEAS: |
153 | case BMP280_REG_RESET: | 187 | case BMP280_REG_RESET: |
154 | return true; | 188 | return true; |
@@ -160,6 +194,8 @@ static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg) | |||
160 | static bool bmp280_is_volatile_reg(struct device *dev, unsigned int reg) | 194 | static bool bmp280_is_volatile_reg(struct device *dev, unsigned int reg) |
161 | { | 195 | { |
162 | switch (reg) { | 196 | switch (reg) { |
197 | case BMP280_REG_HUMIDITY_LSB: | ||
198 | case BMP280_REG_HUMIDITY_MSB: | ||
163 | case BMP280_REG_TEMP_XLSB: | 199 | case BMP280_REG_TEMP_XLSB: |
164 | case BMP280_REG_TEMP_LSB: | 200 | case BMP280_REG_TEMP_LSB: |
165 | case BMP280_REG_TEMP_MSB: | 201 | case BMP280_REG_TEMP_MSB: |
@@ -177,7 +213,7 @@ static const struct regmap_config bmp280_regmap_config = { | |||
177 | .reg_bits = 8, | 213 | .reg_bits = 8, |
178 | .val_bits = 8, | 214 | .val_bits = 8, |
179 | 215 | ||
180 | .max_register = BMP280_REG_TEMP_XLSB, | 216 | .max_register = BMP280_REG_HUMIDITY_LSB, |
181 | .cache_type = REGCACHE_RBTREE, | 217 | .cache_type = REGCACHE_RBTREE, |
182 | 218 | ||
183 | .writeable_reg = bmp280_is_writeable_reg, | 219 | .writeable_reg = bmp280_is_writeable_reg, |
@@ -185,6 +221,70 @@ static const struct regmap_config bmp280_regmap_config = { | |||
185 | }; | 221 | }; |
186 | 222 | ||
187 | /* | 223 | /* |
224 | * Returns humidity in percent, resolution is 0.01 percent. Output value of | ||
225 | * "47445" represents 47445/1024 = 46.333 %RH. | ||
226 | * | ||
227 | * Taken from BME280 datasheet, Section 4.2.3, "Compensation formula". | ||
228 | */ | ||
229 | |||
230 | static u32 bmp280_compensate_humidity(struct bmp280_data *data, | ||
231 | s32 adc_humidity) | ||
232 | { | ||
233 | struct device *dev = &data->client->dev; | ||
234 | unsigned int H1, H3, tmp; | ||
235 | int H2, H4, H5, H6, ret, var; | ||
236 | |||
237 | ret = regmap_read(data->regmap, BMP280_REG_COMP_H1, &H1); | ||
238 | if (ret < 0) { | ||
239 | dev_err(dev, "failed to read H1 comp value\n"); | ||
240 | return ret; | ||
241 | } | ||
242 | |||
243 | ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2, &tmp, 2); | ||
244 | if (ret < 0) { | ||
245 | dev_err(dev, "failed to read H2 comp value\n"); | ||
246 | return ret; | ||
247 | } | ||
248 | H2 = sign_extend32(le16_to_cpu(tmp), 15); | ||
249 | |||
250 | ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &H3); | ||
251 | if (ret < 0) { | ||
252 | dev_err(dev, "failed to read H3 comp value\n"); | ||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4, &tmp, 2); | ||
257 | if (ret < 0) { | ||
258 | dev_err(dev, "failed to read H4 comp value\n"); | ||
259 | return ret; | ||
260 | } | ||
261 | H4 = sign_extend32(((be16_to_cpu(tmp) >> 4) & 0xff0) | | ||
262 | (be16_to_cpu(tmp) & 0xf), 11); | ||
263 | |||
264 | ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H5, &tmp, 2); | ||
265 | if (ret < 0) { | ||
266 | dev_err(dev, "failed to read H5 comp value\n"); | ||
267 | return ret; | ||
268 | } | ||
269 | H5 = sign_extend32(((le16_to_cpu(tmp) >> 4) & 0xfff), 11); | ||
270 | |||
271 | ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp); | ||
272 | if (ret < 0) { | ||
273 | dev_err(dev, "failed to read H6 comp value\n"); | ||
274 | return ret; | ||
275 | } | ||
276 | H6 = sign_extend32(tmp, 7); | ||
277 | |||
278 | var = ((s32)data->t_fine) - 76800; | ||
279 | var = ((((adc_humidity << 14) - (H4 << 20) - (H5 * var)) + 16384) >> 15) | ||
280 | * (((((((var * H6) >> 10) * (((var * H3) >> 11) + 32768)) >> 10) | ||
281 | + 2097152) * H2 + 8192) >> 14); | ||
282 | var -= ((((var >> 15) * (var >> 15)) >> 7) * H1) >> 4; | ||
283 | |||
284 | return var >> 12; | ||
285 | }; | ||
286 | |||
287 | /* | ||
188 | * Returns temperature in DegC, resolution is 0.01 DegC. Output value of | 288 | * Returns temperature in DegC, resolution is 0.01 DegC. Output value of |
189 | * "5123" equals 51.23 DegC. t_fine carries fine temperature as global | 289 | * "5123" equals 51.23 DegC. t_fine carries fine temperature as global |
190 | * value. | 290 | * value. |
@@ -324,6 +424,34 @@ static int bmp280_read_press(struct bmp280_data *data, | |||
324 | return IIO_VAL_FRACTIONAL; | 424 | return IIO_VAL_FRACTIONAL; |
325 | } | 425 | } |
326 | 426 | ||
427 | static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2) | ||
428 | { | ||
429 | int ret; | ||
430 | __be16 tmp = 0; | ||
431 | s32 adc_humidity; | ||
432 | u32 comp_humidity; | ||
433 | |||
434 | /* Read and compensate temperature so we get a reading of t_fine. */ | ||
435 | ret = bmp280_read_temp(data, NULL); | ||
436 | if (ret < 0) | ||
437 | return ret; | ||
438 | |||
439 | ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB, | ||
440 | (u8 *) &tmp, 2); | ||
441 | if (ret < 0) { | ||
442 | dev_err(&data->client->dev, "failed to read humidity\n"); | ||
443 | return ret; | ||
444 | } | ||
445 | |||
446 | adc_humidity = be16_to_cpu(tmp); | ||
447 | comp_humidity = bmp280_compensate_humidity(data, adc_humidity); | ||
448 | |||
449 | *val = comp_humidity; | ||
450 | *val2 = 1024; | ||
451 | |||
452 | return IIO_VAL_FRACTIONAL; | ||
453 | } | ||
454 | |||
327 | static int bmp280_read_raw(struct iio_dev *indio_dev, | 455 | static int bmp280_read_raw(struct iio_dev *indio_dev, |
328 | struct iio_chan_spec const *chan, | 456 | struct iio_chan_spec const *chan, |
329 | int *val, int *val2, long mask) | 457 | int *val, int *val2, long mask) |
@@ -336,6 +464,9 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, | |||
336 | switch (mask) { | 464 | switch (mask) { |
337 | case IIO_CHAN_INFO_PROCESSED: | 465 | case IIO_CHAN_INFO_PROCESSED: |
338 | switch (chan->type) { | 466 | switch (chan->type) { |
467 | case IIO_HUMIDITYRELATIVE: | ||
468 | ret = data->chip_info->read_humid(data, val, val2); | ||
469 | break; | ||
339 | case IIO_PRESSURE: | 470 | case IIO_PRESSURE: |
340 | ret = data->chip_info->read_press(data, val, val2); | 471 | ret = data->chip_info->read_press(data, val, val2); |
341 | break; | 472 | break; |
@@ -349,6 +480,10 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, | |||
349 | break; | 480 | break; |
350 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | 481 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
351 | switch (chan->type) { | 482 | switch (chan->type) { |
483 | case IIO_HUMIDITYRELATIVE: | ||
484 | *val = 1 << data->oversampling_humid; | ||
485 | ret = IIO_VAL_INT; | ||
486 | break; | ||
352 | case IIO_PRESSURE: | 487 | case IIO_PRESSURE: |
353 | *val = 1 << data->oversampling_press; | 488 | *val = 1 << data->oversampling_press; |
354 | ret = IIO_VAL_INT; | 489 | ret = IIO_VAL_INT; |
@@ -372,6 +507,23 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, | |||
372 | return ret; | 507 | return ret; |
373 | } | 508 | } |
374 | 509 | ||
510 | static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data, | ||
511 | int val) | ||
512 | { | ||
513 | int i; | ||
514 | const int *avail = data->chip_info->oversampling_humid_avail; | ||
515 | const int n = data->chip_info->num_oversampling_humid_avail; | ||
516 | |||
517 | for (i = 0; i < n; i++) { | ||
518 | if (avail[i] == val) { | ||
519 | data->oversampling_humid = ilog2(val); | ||
520 | |||
521 | return data->chip_info->chip_config(data); | ||
522 | } | ||
523 | } | ||
524 | return -EINVAL; | ||
525 | } | ||
526 | |||
375 | static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data, | 527 | static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data, |
376 | int val) | 528 | int val) |
377 | { | 529 | { |
@@ -417,6 +569,9 @@ static int bmp280_write_raw(struct iio_dev *indio_dev, | |||
417 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | 569 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
418 | mutex_lock(&data->lock); | 570 | mutex_lock(&data->lock); |
419 | switch (chan->type) { | 571 | switch (chan->type) { |
572 | case IIO_HUMIDITYRELATIVE: | ||
573 | ret = bmp280_write_oversampling_ratio_humid(data, val); | ||
574 | break; | ||
420 | case IIO_PRESSURE: | 575 | case IIO_PRESSURE: |
421 | ret = bmp280_write_oversampling_ratio_press(data, val); | 576 | ret = bmp280_write_oversampling_ratio_press(data, val); |
422 | break; | 577 | break; |
@@ -535,6 +690,37 @@ static const struct bmp280_chip_info bmp280_chip_info = { | |||
535 | .read_press = bmp280_read_press, | 690 | .read_press = bmp280_read_press, |
536 | }; | 691 | }; |
537 | 692 | ||
693 | static int bme280_chip_config(struct bmp280_data *data) | ||
694 | { | ||
695 | int ret = bmp280_chip_config(data); | ||
696 | u8 osrs = BMP280_OSRS_HUMIDITIY_X(data->oversampling_humid + 1); | ||
697 | |||
698 | if (ret < 0) | ||
699 | return ret; | ||
700 | |||
701 | return regmap_update_bits(data->regmap, BMP280_REG_CTRL_HUMIDITY, | ||
702 | BMP280_OSRS_HUMIDITY_MASK, osrs); | ||
703 | } | ||
704 | |||
705 | static const struct bmp280_chip_info bme280_chip_info = { | ||
706 | .regmap_config = &bmp280_regmap_config, | ||
707 | |||
708 | .oversampling_temp_avail = bmp280_oversampling_avail, | ||
709 | .num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail), | ||
710 | |||
711 | .oversampling_press_avail = bmp280_oversampling_avail, | ||
712 | .num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail), | ||
713 | |||
714 | .oversampling_humid_avail = bmp280_oversampling_avail, | ||
715 | .num_oversampling_humid_avail = ARRAY_SIZE(bmp280_oversampling_avail), | ||
716 | |||
717 | .chip_config = bme280_chip_config, | ||
718 | .read_temp = bmp280_read_temp, | ||
719 | .read_press = bmp280_read_press, | ||
720 | .read_humid = bmp280_read_humid, | ||
721 | }; | ||
722 | |||
723 | |||
538 | static bool bmp180_is_writeable_reg(struct device *dev, unsigned int reg) | 724 | static bool bmp180_is_writeable_reg(struct device *dev, unsigned int reg) |
539 | { | 725 | { |
540 | switch (reg) { | 726 | switch (reg) { |
@@ -849,21 +1035,29 @@ static int bmp280_probe(struct i2c_client *client, | |||
849 | indio_dev->dev.parent = &client->dev; | 1035 | indio_dev->dev.parent = &client->dev; |
850 | indio_dev->name = id->name; | 1036 | indio_dev->name = id->name; |
851 | indio_dev->channels = bmp280_channels; | 1037 | indio_dev->channels = bmp280_channels; |
852 | indio_dev->num_channels = ARRAY_SIZE(bmp280_channels); | ||
853 | indio_dev->info = &bmp280_info; | 1038 | indio_dev->info = &bmp280_info; |
854 | indio_dev->modes = INDIO_DIRECT_MODE; | 1039 | indio_dev->modes = INDIO_DIRECT_MODE; |
855 | 1040 | ||
856 | switch (id->driver_data) { | 1041 | switch (id->driver_data) { |
857 | case BMP180_CHIP_ID: | 1042 | case BMP180_CHIP_ID: |
1043 | indio_dev->num_channels = 2; | ||
858 | data->chip_info = &bmp180_chip_info; | 1044 | data->chip_info = &bmp180_chip_info; |
859 | data->oversampling_press = ilog2(8); | 1045 | data->oversampling_press = ilog2(8); |
860 | data->oversampling_temp = ilog2(1); | 1046 | data->oversampling_temp = ilog2(1); |
861 | break; | 1047 | break; |
862 | case BMP280_CHIP_ID: | 1048 | case BMP280_CHIP_ID: |
1049 | indio_dev->num_channels = 2; | ||
863 | data->chip_info = &bmp280_chip_info; | 1050 | data->chip_info = &bmp280_chip_info; |
864 | data->oversampling_press = ilog2(16); | 1051 | data->oversampling_press = ilog2(16); |
865 | data->oversampling_temp = ilog2(2); | 1052 | data->oversampling_temp = ilog2(2); |
866 | break; | 1053 | break; |
1054 | case BME280_CHIP_ID: | ||
1055 | indio_dev->num_channels = 3; | ||
1056 | data->chip_info = &bme280_chip_info; | ||
1057 | data->oversampling_press = ilog2(16); | ||
1058 | data->oversampling_humid = ilog2(16); | ||
1059 | data->oversampling_temp = ilog2(2); | ||
1060 | break; | ||
867 | default: | 1061 | default: |
868 | return -EINVAL; | 1062 | return -EINVAL; |
869 | } | 1063 | } |
@@ -895,6 +1089,7 @@ static const struct acpi_device_id bmp280_acpi_match[] = { | |||
895 | {"BMP0280", BMP280_CHIP_ID }, | 1089 | {"BMP0280", BMP280_CHIP_ID }, |
896 | {"BMP0180", BMP180_CHIP_ID }, | 1090 | {"BMP0180", BMP180_CHIP_ID }, |
897 | {"BMP0085", BMP180_CHIP_ID }, | 1091 | {"BMP0085", BMP180_CHIP_ID }, |
1092 | {"BME0280", BME280_CHIP_ID }, | ||
898 | { }, | 1093 | { }, |
899 | }; | 1094 | }; |
900 | MODULE_DEVICE_TABLE(acpi, bmp280_acpi_match); | 1095 | MODULE_DEVICE_TABLE(acpi, bmp280_acpi_match); |
@@ -903,6 +1098,7 @@ static const struct i2c_device_id bmp280_id[] = { | |||
903 | {"bmp280", BMP280_CHIP_ID }, | 1098 | {"bmp280", BMP280_CHIP_ID }, |
904 | {"bmp180", BMP180_CHIP_ID }, | 1099 | {"bmp180", BMP180_CHIP_ID }, |
905 | {"bmp085", BMP180_CHIP_ID }, | 1100 | {"bmp085", BMP180_CHIP_ID }, |
1101 | {"bme280", BME280_CHIP_ID }, | ||
906 | { }, | 1102 | { }, |
907 | }; | 1103 | }; |
908 | MODULE_DEVICE_TABLE(i2c, bmp280_id); | 1104 | MODULE_DEVICE_TABLE(i2c, bmp280_id); |
diff --git a/drivers/iio/pressure/hp206c.c b/drivers/iio/pressure/hp206c.c index 90f2b6e4a920..12f769e86355 100644 --- a/drivers/iio/pressure/hp206c.c +++ b/drivers/iio/pressure/hp206c.c | |||
@@ -401,6 +401,7 @@ static const struct i2c_device_id hp206c_id[] = { | |||
401 | {"hp206c"}, | 401 | {"hp206c"}, |
402 | {} | 402 | {} |
403 | }; | 403 | }; |
404 | MODULE_DEVICE_TABLE(i2c, hp206c_id); | ||
404 | 405 | ||
405 | #ifdef CONFIG_ACPI | 406 | #ifdef CONFIG_ACPI |
406 | static const struct acpi_device_id hp206c_acpi_match[] = { | 407 | static const struct acpi_device_id hp206c_acpi_match[] = { |
diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c index e68052c118e6..8fb6f7ab97e4 100644 --- a/drivers/iio/pressure/ms5637.c +++ b/drivers/iio/pressure/ms5637.c | |||
@@ -173,6 +173,7 @@ static const struct i2c_device_id ms5637_id[] = { | |||
173 | {"ms8607-temppressure", 1}, | 173 | {"ms8607-temppressure", 1}, |
174 | {} | 174 | {} |
175 | }; | 175 | }; |
176 | MODULE_DEVICE_TABLE(i2c, ms5637_id); | ||
176 | 177 | ||
177 | static struct i2c_driver ms5637_driver = { | 178 | static struct i2c_driver ms5637_driver = { |
178 | .probe = ms5637_probe, | 179 | .probe = ms5637_probe, |
diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h index f5f41490060b..903a21e46874 100644 --- a/drivers/iio/pressure/st_pressure.h +++ b/drivers/iio/pressure/st_pressure.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #define LPS001WP_PRESS_DEV_NAME "lps001wp" | 17 | #define LPS001WP_PRESS_DEV_NAME "lps001wp" |
18 | #define LPS25H_PRESS_DEV_NAME "lps25h" | 18 | #define LPS25H_PRESS_DEV_NAME "lps25h" |
19 | #define LPS331AP_PRESS_DEV_NAME "lps331ap" | 19 | #define LPS331AP_PRESS_DEV_NAME "lps331ap" |
20 | #define LPS22HB_PRESS_DEV_NAME "lps22hb" | ||
20 | 21 | ||
21 | /** | 22 | /** |
22 | * struct st_sensors_platform_data - default press platform data | 23 | * struct st_sensors_platform_data - default press platform data |
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index 9e9b72a8f18f..4d317af55405 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c | |||
@@ -113,6 +113,26 @@ | |||
113 | #define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28 | 113 | #define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28 |
114 | #define ST_TEMP_LPS25H_OUT_L_ADDR 0x2b | 114 | #define ST_TEMP_LPS25H_OUT_L_ADDR 0x2b |
115 | 115 | ||
116 | /* CUSTOM VALUES FOR LPS22HB SENSOR */ | ||
117 | #define ST_PRESS_LPS22HB_WAI_EXP 0xb1 | ||
118 | #define ST_PRESS_LPS22HB_ODR_ADDR 0x10 | ||
119 | #define ST_PRESS_LPS22HB_ODR_MASK 0x70 | ||
120 | #define ST_PRESS_LPS22HB_ODR_AVL_1HZ_VAL 0x01 | ||
121 | #define ST_PRESS_LPS22HB_ODR_AVL_10HZ_VAL 0x02 | ||
122 | #define ST_PRESS_LPS22HB_ODR_AVL_25HZ_VAL 0x03 | ||
123 | #define ST_PRESS_LPS22HB_ODR_AVL_50HZ_VAL 0x04 | ||
124 | #define ST_PRESS_LPS22HB_ODR_AVL_75HZ_VAL 0x05 | ||
125 | #define ST_PRESS_LPS22HB_PW_ADDR 0x10 | ||
126 | #define ST_PRESS_LPS22HB_PW_MASK 0x70 | ||
127 | #define ST_PRESS_LPS22HB_BDU_ADDR 0x10 | ||
128 | #define ST_PRESS_LPS22HB_BDU_MASK 0x02 | ||
129 | #define ST_PRESS_LPS22HB_DRDY_IRQ_ADDR 0x12 | ||
130 | #define ST_PRESS_LPS22HB_DRDY_IRQ_INT1_MASK 0x04 | ||
131 | #define ST_PRESS_LPS22HB_DRDY_IRQ_INT2_MASK 0x08 | ||
132 | #define ST_PRESS_LPS22HB_IHL_IRQ_ADDR 0x12 | ||
133 | #define ST_PRESS_LPS22HB_IHL_IRQ_MASK 0x80 | ||
134 | #define ST_PRESS_LPS22HB_MULTIREAD_BIT true | ||
135 | |||
116 | static const struct iio_chan_spec st_press_1_channels[] = { | 136 | static const struct iio_chan_spec st_press_1_channels[] = { |
117 | { | 137 | { |
118 | .type = IIO_PRESSURE, | 138 | .type = IIO_PRESSURE, |
@@ -183,6 +203,27 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = { | |||
183 | IIO_CHAN_SOFT_TIMESTAMP(1) | 203 | IIO_CHAN_SOFT_TIMESTAMP(1) |
184 | }; | 204 | }; |
185 | 205 | ||
206 | static const struct iio_chan_spec st_press_lps22hb_channels[] = { | ||
207 | { | ||
208 | .type = IIO_PRESSURE, | ||
209 | .channel2 = IIO_NO_MOD, | ||
210 | .address = ST_PRESS_1_OUT_XL_ADDR, | ||
211 | .scan_index = 0, | ||
212 | .scan_type = { | ||
213 | .sign = 'u', | ||
214 | .realbits = 24, | ||
215 | .storagebits = 24, | ||
216 | .endianness = IIO_LE, | ||
217 | }, | ||
218 | .info_mask_separate = | ||
219 | BIT(IIO_CHAN_INFO_RAW) | | ||
220 | BIT(IIO_CHAN_INFO_SCALE), | ||
221 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), | ||
222 | .modified = 0, | ||
223 | }, | ||
224 | IIO_CHAN_SOFT_TIMESTAMP(1) | ||
225 | }; | ||
226 | |||
186 | static const struct st_sensor_settings st_press_sensors_settings[] = { | 227 | static const struct st_sensor_settings st_press_sensors_settings[] = { |
187 | { | 228 | { |
188 | .wai = ST_PRESS_LPS331AP_WAI_EXP, | 229 | .wai = ST_PRESS_LPS331AP_WAI_EXP, |
@@ -326,6 +367,51 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { | |||
326 | .multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT, | 367 | .multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT, |
327 | .bootime = 2, | 368 | .bootime = 2, |
328 | }, | 369 | }, |
370 | { | ||
371 | .wai = ST_PRESS_LPS22HB_WAI_EXP, | ||
372 | .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, | ||
373 | .sensors_supported = { | ||
374 | [0] = LPS22HB_PRESS_DEV_NAME, | ||
375 | }, | ||
376 | .ch = (struct iio_chan_spec *)st_press_lps22hb_channels, | ||
377 | .num_ch = ARRAY_SIZE(st_press_lps22hb_channels), | ||
378 | .odr = { | ||
379 | .addr = ST_PRESS_LPS22HB_ODR_ADDR, | ||
380 | .mask = ST_PRESS_LPS22HB_ODR_MASK, | ||
381 | .odr_avl = { | ||
382 | { 1, ST_PRESS_LPS22HB_ODR_AVL_1HZ_VAL, }, | ||
383 | { 10, ST_PRESS_LPS22HB_ODR_AVL_10HZ_VAL, }, | ||
384 | { 25, ST_PRESS_LPS22HB_ODR_AVL_25HZ_VAL, }, | ||
385 | { 50, ST_PRESS_LPS22HB_ODR_AVL_50HZ_VAL, }, | ||
386 | { 75, ST_PRESS_LPS22HB_ODR_AVL_75HZ_VAL, }, | ||
387 | }, | ||
388 | }, | ||
389 | .pw = { | ||
390 | .addr = ST_PRESS_LPS22HB_PW_ADDR, | ||
391 | .mask = ST_PRESS_LPS22HB_PW_MASK, | ||
392 | .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, | ||
393 | }, | ||
394 | .fs = { | ||
395 | .fs_avl = { | ||
396 | [0] = { | ||
397 | .num = ST_PRESS_FS_AVL_1260MB, | ||
398 | .gain = ST_PRESS_KPASCAL_NANO_SCALE, | ||
399 | }, | ||
400 | }, | ||
401 | }, | ||
402 | .bdu = { | ||
403 | .addr = ST_PRESS_LPS22HB_BDU_ADDR, | ||
404 | .mask = ST_PRESS_LPS22HB_BDU_MASK, | ||
405 | }, | ||
406 | .drdy_irq = { | ||
407 | .addr = ST_PRESS_LPS22HB_DRDY_IRQ_ADDR, | ||
408 | .mask_int1 = ST_PRESS_LPS22HB_DRDY_IRQ_INT1_MASK, | ||
409 | .mask_int2 = ST_PRESS_LPS22HB_DRDY_IRQ_INT2_MASK, | ||
410 | .addr_ihl = ST_PRESS_LPS22HB_IHL_IRQ_ADDR, | ||
411 | .mask_ihl = ST_PRESS_LPS22HB_IHL_IRQ_MASK, | ||
412 | }, | ||
413 | .multi_read_bit = ST_PRESS_LPS22HB_MULTIREAD_BIT, | ||
414 | }, | ||
329 | }; | 415 | }; |
330 | 416 | ||
331 | static int st_press_write_raw(struct iio_dev *indio_dev, | 417 | static int st_press_write_raw(struct iio_dev *indio_dev, |
@@ -441,23 +527,24 @@ int st_press_common_probe(struct iio_dev *indio_dev) | |||
441 | indio_dev->info = &press_info; | 527 | indio_dev->info = &press_info; |
442 | mutex_init(&press_data->tb.buf_lock); | 528 | mutex_init(&press_data->tb.buf_lock); |
443 | 529 | ||
444 | st_sensors_power_enable(indio_dev); | 530 | err = st_sensors_power_enable(indio_dev); |
531 | if (err) | ||
532 | return err; | ||
445 | 533 | ||
446 | err = st_sensors_check_device_support(indio_dev, | 534 | err = st_sensors_check_device_support(indio_dev, |
447 | ARRAY_SIZE(st_press_sensors_settings), | 535 | ARRAY_SIZE(st_press_sensors_settings), |
448 | st_press_sensors_settings); | 536 | st_press_sensors_settings); |
449 | if (err < 0) | 537 | if (err < 0) |
450 | return err; | 538 | goto st_press_power_off; |
451 | 539 | ||
452 | press_data->num_data_channels = ST_PRESS_NUMBER_DATA_CHANNELS; | 540 | press_data->num_data_channels = ST_PRESS_NUMBER_DATA_CHANNELS; |
453 | press_data->multiread_bit = press_data->sensor_settings->multi_read_bit; | 541 | press_data->multiread_bit = press_data->sensor_settings->multi_read_bit; |
454 | indio_dev->channels = press_data->sensor_settings->ch; | 542 | indio_dev->channels = press_data->sensor_settings->ch; |
455 | indio_dev->num_channels = press_data->sensor_settings->num_ch; | 543 | indio_dev->num_channels = press_data->sensor_settings->num_ch; |
456 | 544 | ||
457 | if (press_data->sensor_settings->fs.addr != 0) | 545 | press_data->current_fullscale = |
458 | press_data->current_fullscale = | 546 | (struct st_sensor_fullscale_avl *) |
459 | (struct st_sensor_fullscale_avl *) | 547 | &press_data->sensor_settings->fs.fs_avl[0]; |
460 | &press_data->sensor_settings->fs.fs_avl[0]; | ||
461 | 548 | ||
462 | press_data->odr = press_data->sensor_settings->odr.odr_avl[0].hz; | 549 | press_data->odr = press_data->sensor_settings->odr.odr_avl[0].hz; |
463 | 550 | ||
@@ -469,11 +556,11 @@ int st_press_common_probe(struct iio_dev *indio_dev) | |||
469 | 556 | ||
470 | err = st_sensors_init_sensor(indio_dev, press_data->dev->platform_data); | 557 | err = st_sensors_init_sensor(indio_dev, press_data->dev->platform_data); |
471 | if (err < 0) | 558 | if (err < 0) |
472 | return err; | 559 | goto st_press_power_off; |
473 | 560 | ||
474 | err = st_press_allocate_ring(indio_dev); | 561 | err = st_press_allocate_ring(indio_dev); |
475 | if (err < 0) | 562 | if (err < 0) |
476 | return err; | 563 | goto st_press_power_off; |
477 | 564 | ||
478 | if (irq > 0) { | 565 | if (irq > 0) { |
479 | err = st_sensors_allocate_trigger(indio_dev, | 566 | err = st_sensors_allocate_trigger(indio_dev, |
@@ -496,6 +583,8 @@ st_press_device_register_error: | |||
496 | st_sensors_deallocate_trigger(indio_dev); | 583 | st_sensors_deallocate_trigger(indio_dev); |
497 | st_press_probe_trigger_error: | 584 | st_press_probe_trigger_error: |
498 | st_press_deallocate_ring(indio_dev); | 585 | st_press_deallocate_ring(indio_dev); |
586 | st_press_power_off: | ||
587 | st_sensors_power_disable(indio_dev); | ||
499 | 588 | ||
500 | return err; | 589 | return err; |
501 | } | 590 | } |
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index 8fcf9766eaec..ed18701c68c9 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c | |||
@@ -32,6 +32,10 @@ static const struct of_device_id st_press_of_match[] = { | |||
32 | .compatible = "st,lps331ap-press", | 32 | .compatible = "st,lps331ap-press", |
33 | .data = LPS331AP_PRESS_DEV_NAME, | 33 | .data = LPS331AP_PRESS_DEV_NAME, |
34 | }, | 34 | }, |
35 | { | ||
36 | .compatible = "st,lps22hb-press", | ||
37 | .data = LPS22HB_PRESS_DEV_NAME, | ||
38 | }, | ||
35 | {}, | 39 | {}, |
36 | }; | 40 | }; |
37 | MODULE_DEVICE_TABLE(of, st_press_of_match); | 41 | MODULE_DEVICE_TABLE(of, st_press_of_match); |
diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index 40c0692ff1de..550508025af1 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c | |||
@@ -50,6 +50,7 @@ static const struct spi_device_id st_press_id_table[] = { | |||
50 | { LPS001WP_PRESS_DEV_NAME }, | 50 | { LPS001WP_PRESS_DEV_NAME }, |
51 | { LPS25H_PRESS_DEV_NAME }, | 51 | { LPS25H_PRESS_DEV_NAME }, |
52 | { LPS331AP_PRESS_DEV_NAME }, | 52 | { LPS331AP_PRESS_DEV_NAME }, |
53 | { LPS22HB_PRESS_DEV_NAME }, | ||
53 | {}, | 54 | {}, |
54 | }; | 55 | }; |
55 | MODULE_DEVICE_TABLE(spi, st_press_id_table); | 56 | MODULE_DEVICE_TABLE(spi, st_press_id_table); |
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index f4d29d5dbd5f..c12fde23c7ef 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c | |||
@@ -461,4 +461,3 @@ module_spi_driver(as3935_driver); | |||
461 | MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); | 461 | MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); |
462 | MODULE_DESCRIPTION("AS3935 lightning sensor"); | 462 | MODULE_DESCRIPTION("AS3935 lightning sensor"); |
463 | MODULE_LICENSE("GPL"); | 463 | MODULE_LICENSE("GPL"); |
464 | MODULE_ALIAS("spi:as3935"); | ||
diff --git a/drivers/iio/temperature/tsys02d.c b/drivers/iio/temperature/tsys02d.c index ab6fe8f6f2d1..c0a19a000387 100644 --- a/drivers/iio/temperature/tsys02d.c +++ b/drivers/iio/temperature/tsys02d.c | |||
@@ -174,6 +174,7 @@ static const struct i2c_device_id tsys02d_id[] = { | |||
174 | {"tsys02d", 0}, | 174 | {"tsys02d", 0}, |
175 | {} | 175 | {} |
176 | }; | 176 | }; |
177 | MODULE_DEVICE_TABLE(i2c, tsys02d_id); | ||
177 | 178 | ||
178 | static struct i2c_driver tsys02d_driver = { | 179 | static struct i2c_driver tsys02d_driver = { |
179 | .probe = tsys02d_probe, | 180 | .probe = tsys02d_probe, |
diff --git a/drivers/iio/trigger/Kconfig b/drivers/iio/trigger/Kconfig index 519e6772f6f5..809b2e7d58fa 100644 --- a/drivers/iio/trigger/Kconfig +++ b/drivers/iio/trigger/Kconfig | |||
@@ -24,6 +24,18 @@ config IIO_INTERRUPT_TRIGGER | |||
24 | To compile this driver as a module, choose M here: the | 24 | To compile this driver as a module, choose M here: the |
25 | module will be called iio-trig-interrupt. | 25 | module will be called iio-trig-interrupt. |
26 | 26 | ||
27 | config IIO_TIGHTLOOP_TRIGGER | ||
28 | tristate "A kthread based hammering loop trigger" | ||
29 | depends on IIO_SW_TRIGGER | ||
30 | help | ||
31 | An experimental trigger, used to allow sensors to be sampled as fast | ||
32 | as possible under the limitations of whatever else is going on. | ||
33 | Uses a tight loop in a kthread. Will only work with lower half only | ||
34 | trigger consumers. | ||
35 | |||
36 | To compile this driver as a module, choose M here: the | ||
37 | module will be called iio-trig-loop. | ||
38 | |||
27 | config IIO_SYSFS_TRIGGER | 39 | config IIO_SYSFS_TRIGGER |
28 | tristate "SYSFS trigger" | 40 | tristate "SYSFS trigger" |
29 | depends on SYSFS | 41 | depends on SYSFS |
diff --git a/drivers/iio/trigger/Makefile b/drivers/iio/trigger/Makefile index fe06eb564367..aab4dc23303d 100644 --- a/drivers/iio/trigger/Makefile +++ b/drivers/iio/trigger/Makefile | |||
@@ -7,3 +7,4 @@ | |||
7 | obj-$(CONFIG_IIO_HRTIMER_TRIGGER) += iio-trig-hrtimer.o | 7 | obj-$(CONFIG_IIO_HRTIMER_TRIGGER) += iio-trig-hrtimer.o |
8 | obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o | 8 | obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o |
9 | obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o | 9 | obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o |
10 | obj-$(CONFIG_IIO_TIGHTLOOP_TRIGGER) += iio-trig-loop.o | ||
diff --git a/drivers/iio/trigger/iio-trig-loop.c b/drivers/iio/trigger/iio-trig-loop.c new file mode 100644 index 000000000000..dc6be28f96fe --- /dev/null +++ b/drivers/iio/trigger/iio-trig-loop.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * Copyright 2016 Jonathan Cameron <jic23@kernel.org> | ||
3 | * | ||
4 | * Licensed under the GPL-2. | ||
5 | * | ||
6 | * Based on a mashup of the hrtimer trigger and continuous sampling proposal of | ||
7 | * Gregor Boirie <gregor.boirie@parrot.com> | ||
8 | * | ||
9 | * Note this is still rather experimental and may eat babies. | ||
10 | * | ||
11 | * Todo | ||
12 | * * Protect against connection of devices that 'need' the top half | ||
13 | * handler. | ||
14 | * * Work out how to run top half handlers in this context if it is | ||
15 | * safe to do so (timestamp grabbing for example) | ||
16 | * | ||
17 | * Tested against a max1363. Used about 33% cpu for the thread and 20% | ||
18 | * for generic_buffer piping to /dev/null. Watermark set at 64 on a 128 | ||
19 | * element kfifo buffer. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/irq_work.h> | ||
27 | #include <linux/kthread.h> | ||
28 | #include <linux/freezer.h> | ||
29 | |||
30 | #include <linux/iio/iio.h> | ||
31 | #include <linux/iio/trigger.h> | ||
32 | #include <linux/iio/sw_trigger.h> | ||
33 | |||
34 | struct iio_loop_info { | ||
35 | struct iio_sw_trigger swt; | ||
36 | struct task_struct *task; | ||
37 | }; | ||
38 | |||
39 | static struct config_item_type iio_loop_type = { | ||
40 | .ct_owner = THIS_MODULE, | ||
41 | }; | ||
42 | |||
43 | static int iio_loop_thread(void *data) | ||
44 | { | ||
45 | struct iio_trigger *trig = data; | ||
46 | |||
47 | set_freezable(); | ||
48 | |||
49 | do { | ||
50 | iio_trigger_poll_chained(trig); | ||
51 | } while (likely(!kthread_freezable_should_stop(NULL))); | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static int iio_loop_trigger_set_state(struct iio_trigger *trig, bool state) | ||
57 | { | ||
58 | struct iio_loop_info *loop_trig = iio_trigger_get_drvdata(trig); | ||
59 | |||
60 | if (state) { | ||
61 | loop_trig->task = kthread_run(iio_loop_thread, | ||
62 | trig, trig->name); | ||
63 | if (unlikely(IS_ERR(loop_trig->task))) { | ||
64 | dev_err(&trig->dev, | ||
65 | "failed to create trigger loop thread\n"); | ||
66 | return PTR_ERR(loop_trig->task); | ||
67 | } | ||
68 | } else { | ||
69 | kthread_stop(loop_trig->task); | ||
70 | } | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static const struct iio_trigger_ops iio_loop_trigger_ops = { | ||
76 | .set_trigger_state = iio_loop_trigger_set_state, | ||
77 | .owner = THIS_MODULE, | ||
78 | }; | ||
79 | |||
80 | static struct iio_sw_trigger *iio_trig_loop_probe(const char *name) | ||
81 | { | ||
82 | struct iio_loop_info *trig_info; | ||
83 | int ret; | ||
84 | |||
85 | trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL); | ||
86 | if (!trig_info) | ||
87 | return ERR_PTR(-ENOMEM); | ||
88 | |||
89 | trig_info->swt.trigger = iio_trigger_alloc("%s", name); | ||
90 | if (!trig_info->swt.trigger) { | ||
91 | ret = -ENOMEM; | ||
92 | goto err_free_trig_info; | ||
93 | } | ||
94 | |||
95 | iio_trigger_set_drvdata(trig_info->swt.trigger, trig_info); | ||
96 | trig_info->swt.trigger->ops = &iio_loop_trigger_ops; | ||
97 | |||
98 | ret = iio_trigger_register(trig_info->swt.trigger); | ||
99 | if (ret) | ||
100 | goto err_free_trigger; | ||
101 | |||
102 | iio_swt_group_init_type_name(&trig_info->swt, name, &iio_loop_type); | ||
103 | |||
104 | return &trig_info->swt; | ||
105 | |||
106 | err_free_trigger: | ||
107 | iio_trigger_free(trig_info->swt.trigger); | ||
108 | err_free_trig_info: | ||
109 | kfree(trig_info); | ||
110 | |||
111 | return ERR_PTR(ret); | ||
112 | } | ||
113 | |||
114 | static int iio_trig_loop_remove(struct iio_sw_trigger *swt) | ||
115 | { | ||
116 | struct iio_loop_info *trig_info; | ||
117 | |||
118 | trig_info = iio_trigger_get_drvdata(swt->trigger); | ||
119 | |||
120 | iio_trigger_unregister(swt->trigger); | ||
121 | iio_trigger_free(swt->trigger); | ||
122 | kfree(trig_info); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static const struct iio_sw_trigger_ops iio_trig_loop_ops = { | ||
128 | .probe = iio_trig_loop_probe, | ||
129 | .remove = iio_trig_loop_remove, | ||
130 | }; | ||
131 | |||
132 | static struct iio_sw_trigger_type iio_trig_loop = { | ||
133 | .name = "loop", | ||
134 | .owner = THIS_MODULE, | ||
135 | .ops = &iio_trig_loop_ops, | ||
136 | }; | ||
137 | |||
138 | module_iio_sw_trigger_driver(iio_trig_loop); | ||
139 | |||
140 | MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); | ||
141 | MODULE_DESCRIPTION("Loop based trigger for the iio subsystem"); | ||
142 | MODULE_LICENSE("GPL v2"); | ||
143 | MODULE_ALIAS("platform:iio-trig-loop"); | ||
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index d029ffac0d69..91d5f684a53a 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h | |||
@@ -251,8 +251,6 @@ struct st_sensor_data { | |||
251 | 251 | ||
252 | #ifdef CONFIG_IIO_BUFFER | 252 | #ifdef CONFIG_IIO_BUFFER |
253 | irqreturn_t st_sensors_trigger_handler(int irq, void *p); | 253 | irqreturn_t st_sensors_trigger_handler(int irq, void *p); |
254 | |||
255 | int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf); | ||
256 | #endif | 254 | #endif |
257 | 255 | ||
258 | #ifdef CONFIG_IIO_TRIGGER | 256 | #ifdef CONFIG_IIO_TRIGGER |
@@ -280,7 +278,7 @@ int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable); | |||
280 | 278 | ||
281 | int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable); | 279 | int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable); |
282 | 280 | ||
283 | void st_sensors_power_enable(struct iio_dev *indio_dev); | 281 | int st_sensors_power_enable(struct iio_dev *indio_dev); |
284 | 282 | ||
285 | void st_sensors_power_disable(struct iio_dev *indio_dev); | 283 | void st_sensors_power_disable(struct iio_dev *indio_dev); |
286 | 284 | ||
diff --git a/include/linux/iio/sw_device.h b/include/linux/iio/sw_device.h new file mode 100644 index 000000000000..23ca41515527 --- /dev/null +++ b/include/linux/iio/sw_device.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Industrial I/O software device interface | ||
3 | * | ||
4 | * Copyright (c) 2016 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __IIO_SW_DEVICE | ||
12 | #define __IIO_SW_DEVICE | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/iio/iio.h> | ||
17 | #include <linux/configfs.h> | ||
18 | |||
19 | #define module_iio_sw_device_driver(__iio_sw_device_type) \ | ||
20 | module_driver(__iio_sw_device_type, iio_register_sw_device_type, \ | ||
21 | iio_unregister_sw_device_type) | ||
22 | |||
23 | struct iio_sw_device_ops; | ||
24 | |||
25 | struct iio_sw_device_type { | ||
26 | const char *name; | ||
27 | struct module *owner; | ||
28 | const struct iio_sw_device_ops *ops; | ||
29 | struct list_head list; | ||
30 | struct config_group *group; | ||
31 | }; | ||
32 | |||
33 | struct iio_sw_device { | ||
34 | struct iio_dev *device; | ||
35 | struct iio_sw_device_type *device_type; | ||
36 | struct config_group group; | ||
37 | }; | ||
38 | |||
39 | struct iio_sw_device_ops { | ||
40 | struct iio_sw_device* (*probe)(const char *); | ||
41 | int (*remove)(struct iio_sw_device *); | ||
42 | }; | ||
43 | |||
44 | static inline | ||
45 | struct iio_sw_device *to_iio_sw_device(struct config_item *item) | ||
46 | { | ||
47 | return container_of(to_config_group(item), struct iio_sw_device, | ||
48 | group); | ||
49 | } | ||
50 | |||
51 | int iio_register_sw_device_type(struct iio_sw_device_type *dt); | ||
52 | void iio_unregister_sw_device_type(struct iio_sw_device_type *dt); | ||
53 | |||
54 | struct iio_sw_device *iio_sw_device_create(const char *, const char *); | ||
55 | void iio_sw_device_destroy(struct iio_sw_device *); | ||
56 | |||
57 | int iio_sw_device_type_configfs_register(struct iio_sw_device_type *dt); | ||
58 | void iio_sw_device_type_configfs_unregister(struct iio_sw_device_type *dt); | ||
59 | |||
60 | static inline | ||
61 | void iio_swd_group_init_type_name(struct iio_sw_device *d, | ||
62 | const char *name, | ||
63 | struct config_item_type *type) | ||
64 | { | ||
65 | #ifdef CONFIG_CONFIGFS_FS | ||
66 | config_group_init_type_name(&d->group, name, type); | ||
67 | #endif | ||
68 | } | ||
69 | |||
70 | #endif /* __IIO_SW_DEVICE */ | ||
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index b0916fc72cce..22e5e589a274 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h | |||
@@ -39,6 +39,7 @@ enum iio_chan_type { | |||
39 | IIO_RESISTANCE, | 39 | IIO_RESISTANCE, |
40 | IIO_PH, | 40 | IIO_PH, |
41 | IIO_UVINDEX, | 41 | IIO_UVINDEX, |
42 | IIO_ELECTRICALCONDUCTIVITY, | ||
42 | }; | 43 | }; |
43 | 44 | ||
44 | enum iio_modifier { | 45 | enum iio_modifier { |
diff --git a/tools/iio/Makefile b/tools/iio/Makefile index 3a7a54f59713..5446d625e17d 100644 --- a/tools/iio/Makefile +++ b/tools/iio/Makefile | |||
@@ -1,16 +1,31 @@ | |||
1 | CC = $(CROSS_COMPILE)gcc | 1 | CC = $(CROSS_COMPILE)gcc |
2 | CFLAGS += -Wall -g -D_GNU_SOURCE | 2 | CFLAGS += -Wall -g -D_GNU_SOURCE |
3 | 3 | ||
4 | all: iio_event_monitor lsiio generic_buffer | 4 | BINDIR=usr/bin |
5 | INSTALL_PROGRAM=install -m 755 -p | ||
6 | DEL_FILE=rm -f | ||
7 | |||
8 | all: iio_event_monitor lsiio iio_generic_buffer | ||
5 | 9 | ||
6 | iio_event_monitor: iio_event_monitor.o iio_utils.o | 10 | iio_event_monitor: iio_event_monitor.o iio_utils.o |
7 | 11 | ||
8 | lsiio: lsiio.o iio_utils.o | 12 | lsiio: lsiio.o iio_utils.o |
9 | 13 | ||
10 | generic_buffer: generic_buffer.o iio_utils.o | 14 | iio_generic_buffer: iio_generic_buffer.o iio_utils.o |
11 | 15 | ||
12 | %.o: %.c iio_utils.h | 16 | %.o: %.c iio_utils.h |
13 | 17 | ||
18 | install: | ||
19 | - mkdir -p $(INSTALL_ROOT)/$(BINDIR) | ||
20 | - $(INSTALL_PROGRAM) "iio_event_monitor" "$(INSTALL_ROOT)/$(BINDIR)/iio_event_monitor" | ||
21 | - $(INSTALL_PROGRAM) "lsiio" "$(INSTALL_ROOT)/$(BINDIR)/lsiio" | ||
22 | - $(INSTALL_PROGRAM) "iio_generic_buffer" "$(INSTALL_ROOT)/$(BINDIR)/iio_generic_buffer" | ||
23 | |||
24 | uninstall: | ||
25 | $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/iio_event_monitor" | ||
26 | $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/lsiio" | ||
27 | $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/iio_generic_buffer" | ||
28 | |||
14 | .PHONY: clean | 29 | .PHONY: clean |
15 | clean: | 30 | clean: |
16 | rm -f *.o iio_event_monitor lsiio generic_buffer | 31 | rm -f *.o iio_event_monitor lsiio iio_generic_buffer |
diff --git a/tools/iio/generic_buffer.c b/tools/iio/iio_generic_buffer.c index 2429c78de940..e8c30521e99c 100644 --- a/tools/iio/generic_buffer.c +++ b/tools/iio/iio_generic_buffer.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <endian.h> | 32 | #include <endian.h> |
33 | #include <getopt.h> | 33 | #include <getopt.h> |
34 | #include <inttypes.h> | 34 | #include <inttypes.h> |
35 | #include <stdbool.h> | ||
36 | #include <signal.h> | ||
35 | #include "iio_utils.h" | 37 | #include "iio_utils.h" |
36 | 38 | ||
37 | /** | 39 | /** |
@@ -249,11 +251,82 @@ void print_usage(void) | |||
249 | " -e Disable wait for event (new data)\n" | 251 | " -e Disable wait for event (new data)\n" |
250 | " -g Use trigger-less mode\n" | 252 | " -g Use trigger-less mode\n" |
251 | " -l <n> Set buffer length to n samples\n" | 253 | " -l <n> Set buffer length to n samples\n" |
252 | " -n <name> Set device name (mandatory)\n" | 254 | " --device-name -n <name>\n" |
253 | " -t <name> Set trigger name\n" | 255 | " --device-num -N <num>\n" |
256 | " Set device by name or number (mandatory)\n" | ||
257 | " --trigger-name -t <name>\n" | ||
258 | " --trigger-num -T <num>\n" | ||
259 | " Set trigger by name or number\n" | ||
254 | " -w <n> Set delay between reads in us (event-less mode)\n"); | 260 | " -w <n> Set delay between reads in us (event-less mode)\n"); |
255 | } | 261 | } |
256 | 262 | ||
263 | enum autochan autochannels = AUTOCHANNELS_DISABLED; | ||
264 | char *dev_dir_name = NULL; | ||
265 | char *buf_dir_name = NULL; | ||
266 | bool current_trigger_set = false; | ||
267 | |||
268 | void cleanup(void) | ||
269 | { | ||
270 | int ret; | ||
271 | |||
272 | /* Disable trigger */ | ||
273 | if (dev_dir_name && current_trigger_set) { | ||
274 | /* Disconnect the trigger - just write a dummy name. */ | ||
275 | ret = write_sysfs_string("trigger/current_trigger", | ||
276 | dev_dir_name, "NULL"); | ||
277 | if (ret < 0) | ||
278 | fprintf(stderr, "Failed to disable trigger: %s\n", | ||
279 | strerror(-ret)); | ||
280 | current_trigger_set = false; | ||
281 | } | ||
282 | |||
283 | /* Disable buffer */ | ||
284 | if (buf_dir_name) { | ||
285 | ret = write_sysfs_int("enable", buf_dir_name, 0); | ||
286 | if (ret < 0) | ||
287 | fprintf(stderr, "Failed to disable buffer: %s\n", | ||
288 | strerror(-ret)); | ||
289 | } | ||
290 | |||
291 | /* Disable channels if auto-enabled */ | ||
292 | if (dev_dir_name && autochannels == AUTOCHANNELS_ACTIVE) { | ||
293 | ret = enable_disable_all_channels(dev_dir_name, 0); | ||
294 | if (ret) | ||
295 | fprintf(stderr, "Failed to disable all channels\n"); | ||
296 | autochannels = AUTOCHANNELS_DISABLED; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | void sig_handler(int signum) | ||
301 | { | ||
302 | fprintf(stderr, "Caught signal %d\n", signum); | ||
303 | cleanup(); | ||
304 | exit(-signum); | ||
305 | } | ||
306 | |||
307 | void register_cleanup(void) | ||
308 | { | ||
309 | struct sigaction sa = { .sa_handler = sig_handler }; | ||
310 | const int signums[] = { SIGINT, SIGTERM, SIGABRT }; | ||
311 | int ret, i; | ||
312 | |||
313 | for (i = 0; i < ARRAY_SIZE(signums); ++i) { | ||
314 | ret = sigaction(signums[i], &sa, NULL); | ||
315 | if (ret) { | ||
316 | perror("Failed to register signal handler"); | ||
317 | exit(-1); | ||
318 | } | ||
319 | } | ||
320 | } | ||
321 | |||
322 | static const struct option longopts[] = { | ||
323 | { "device-name", 1, 0, 'n' }, | ||
324 | { "device-num", 1, 0, 'N' }, | ||
325 | { "trigger-name", 1, 0, 't' }, | ||
326 | { "trigger-num", 1, 0, 'T' }, | ||
327 | { }, | ||
328 | }; | ||
329 | |||
257 | int main(int argc, char **argv) | 330 | int main(int argc, char **argv) |
258 | { | 331 | { |
259 | unsigned long num_loops = 2; | 332 | unsigned long num_loops = 2; |
@@ -261,26 +334,25 @@ int main(int argc, char **argv) | |||
261 | unsigned long buf_len = 128; | 334 | unsigned long buf_len = 128; |
262 | 335 | ||
263 | int ret, c, i, j, toread; | 336 | int ret, c, i, j, toread; |
264 | int fp; | 337 | int fp = -1; |
265 | 338 | ||
266 | int num_channels; | 339 | int num_channels = 0; |
267 | char *trigger_name = NULL, *device_name = NULL; | 340 | char *trigger_name = NULL, *device_name = NULL; |
268 | char *dev_dir_name, *buf_dir_name; | ||
269 | 341 | ||
270 | int datardytrigger = 1; | 342 | char *data = NULL; |
271 | char *data; | ||
272 | ssize_t read_size; | 343 | ssize_t read_size; |
273 | int dev_num, trig_num; | 344 | int dev_num = -1, trig_num; |
274 | char *buffer_access; | 345 | char *buffer_access = NULL; |
275 | int scan_size; | 346 | int scan_size; |
276 | int noevents = 0; | 347 | int noevents = 0; |
277 | int notrigger = 0; | 348 | int notrigger = 0; |
278 | enum autochan autochannels = AUTOCHANNELS_DISABLED; | ||
279 | char *dummy; | 349 | char *dummy; |
280 | 350 | ||
281 | struct iio_channel_info *channels; | 351 | struct iio_channel_info *channels; |
282 | 352 | ||
283 | while ((c = getopt(argc, argv, "ac:egl:n:t:w:")) != -1) { | 353 | register_cleanup(); |
354 | |||
355 | while ((c = getopt_long(argc, argv, "ac:egl:n:N:t:T:w:", longopts, NULL)) != -1) { | ||
284 | switch (c) { | 356 | switch (c) { |
285 | case 'a': | 357 | case 'a': |
286 | autochannels = AUTOCHANNELS_ENABLED; | 358 | autochannels = AUTOCHANNELS_ENABLED; |
@@ -288,8 +360,10 @@ int main(int argc, char **argv) | |||
288 | case 'c': | 360 | case 'c': |
289 | errno = 0; | 361 | errno = 0; |
290 | num_loops = strtoul(optarg, &dummy, 10); | 362 | num_loops = strtoul(optarg, &dummy, 10); |
291 | if (errno) | 363 | if (errno) { |
292 | return -errno; | 364 | ret = -errno; |
365 | goto error; | ||
366 | } | ||
293 | 367 | ||
294 | break; | 368 | break; |
295 | case 'e': | 369 | case 'e': |
@@ -301,49 +375,102 @@ int main(int argc, char **argv) | |||
301 | case 'l': | 375 | case 'l': |
302 | errno = 0; | 376 | errno = 0; |
303 | buf_len = strtoul(optarg, &dummy, 10); | 377 | buf_len = strtoul(optarg, &dummy, 10); |
304 | if (errno) | 378 | if (errno) { |
305 | return -errno; | 379 | ret = -errno; |
380 | goto error; | ||
381 | } | ||
306 | 382 | ||
307 | break; | 383 | break; |
308 | case 'n': | 384 | case 'n': |
309 | device_name = optarg; | 385 | device_name = strdup(optarg); |
386 | break; | ||
387 | case 'N': | ||
388 | errno = 0; | ||
389 | dev_num = strtoul(optarg, &dummy, 10); | ||
390 | if (errno) { | ||
391 | ret = -errno; | ||
392 | goto error; | ||
393 | } | ||
310 | break; | 394 | break; |
311 | case 't': | 395 | case 't': |
312 | trigger_name = optarg; | 396 | trigger_name = strdup(optarg); |
313 | datardytrigger = 0; | ||
314 | break; | 397 | break; |
315 | case 'w': | 398 | case 'T': |
316 | errno = 0; | 399 | errno = 0; |
317 | timedelay = strtoul(optarg, &dummy, 10); | 400 | trig_num = strtoul(optarg, &dummy, 10); |
318 | if (errno) | 401 | if (errno) |
319 | return -errno; | 402 | return -errno; |
320 | break; | 403 | break; |
404 | case 'w': | ||
405 | errno = 0; | ||
406 | timedelay = strtoul(optarg, &dummy, 10); | ||
407 | if (errno) { | ||
408 | ret = -errno; | ||
409 | goto error; | ||
410 | } | ||
411 | break; | ||
321 | case '?': | 412 | case '?': |
322 | print_usage(); | 413 | print_usage(); |
323 | return -1; | 414 | ret = -1; |
415 | goto error; | ||
324 | } | 416 | } |
325 | } | 417 | } |
326 | 418 | ||
327 | if (!device_name) { | ||
328 | fprintf(stderr, "Device name not set\n"); | ||
329 | print_usage(); | ||
330 | return -1; | ||
331 | } | ||
332 | |||
333 | /* Find the device requested */ | 419 | /* Find the device requested */ |
334 | dev_num = find_type_by_name(device_name, "iio:device"); | 420 | if (dev_num < 0 && !device_name) { |
335 | if (dev_num < 0) { | 421 | fprintf(stderr, "Device not set\n"); |
336 | fprintf(stderr, "Failed to find the %s\n", device_name); | 422 | print_usage(); |
337 | return dev_num; | 423 | ret = -1; |
424 | goto error; | ||
425 | } else if (dev_num >= 0 && device_name) { | ||
426 | fprintf(stderr, "Only one of --device-num or --device-name needs to be set\n"); | ||
427 | print_usage(); | ||
428 | ret = -1; | ||
429 | goto error; | ||
430 | } else if (dev_num < 0) { | ||
431 | dev_num = find_type_by_name(device_name, "iio:device"); | ||
432 | if (dev_num < 0) { | ||
433 | fprintf(stderr, "Failed to find the %s\n", device_name); | ||
434 | ret = dev_num; | ||
435 | goto error; | ||
436 | } | ||
338 | } | 437 | } |
339 | |||
340 | printf("iio device number being used is %d\n", dev_num); | 438 | printf("iio device number being used is %d\n", dev_num); |
341 | 439 | ||
342 | ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num); | 440 | ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num); |
343 | if (ret < 0) | 441 | if (ret < 0) |
344 | return -ENOMEM; | 442 | return -ENOMEM; |
443 | /* Fetch device_name if specified by number */ | ||
444 | if (!device_name) { | ||
445 | device_name = malloc(IIO_MAX_NAME_LENGTH); | ||
446 | if (!device_name) { | ||
447 | ret = -ENOMEM; | ||
448 | goto error; | ||
449 | } | ||
450 | ret = read_sysfs_string("name", dev_dir_name, device_name); | ||
451 | if (ret < 0) { | ||
452 | fprintf(stderr, "Failed to read name of device %d\n", dev_num); | ||
453 | goto error; | ||
454 | } | ||
455 | } | ||
345 | 456 | ||
346 | if (!notrigger) { | 457 | if (notrigger) { |
458 | printf("trigger-less mode selected\n"); | ||
459 | } if (trig_num > 0) { | ||
460 | char *trig_dev_name; | ||
461 | ret = asprintf(&trig_dev_name, "%strigger%d", iio_dir, trig_num); | ||
462 | if (ret < 0) { | ||
463 | return -ENOMEM; | ||
464 | } | ||
465 | trigger_name = malloc(IIO_MAX_NAME_LENGTH); | ||
466 | ret = read_sysfs_string("name", trig_dev_name, trigger_name); | ||
467 | free(trig_dev_name); | ||
468 | if (ret < 0) { | ||
469 | fprintf(stderr, "Failed to read trigger%d name from\n", trig_num); | ||
470 | return ret; | ||
471 | } | ||
472 | printf("iio trigger number being used is %d\n", trig_num); | ||
473 | } else { | ||
347 | if (!trigger_name) { | 474 | if (!trigger_name) { |
348 | /* | 475 | /* |
349 | * Build the trigger name. If it is device associated | 476 | * Build the trigger name. If it is device associated |
@@ -354,7 +481,7 @@ int main(int argc, char **argv) | |||
354 | "%s-dev%d", device_name, dev_num); | 481 | "%s-dev%d", device_name, dev_num); |
355 | if (ret < 0) { | 482 | if (ret < 0) { |
356 | ret = -ENOMEM; | 483 | ret = -ENOMEM; |
357 | goto error_free_dev_dir_name; | 484 | goto error; |
358 | } | 485 | } |
359 | } | 486 | } |
360 | 487 | ||
@@ -367,7 +494,7 @@ int main(int argc, char **argv) | |||
367 | "%s-trigger", device_name); | 494 | "%s-trigger", device_name); |
368 | if (ret < 0) { | 495 | if (ret < 0) { |
369 | ret = -ENOMEM; | 496 | ret = -ENOMEM; |
370 | goto error_free_dev_dir_name; | 497 | goto error; |
371 | } | 498 | } |
372 | } | 499 | } |
373 | 500 | ||
@@ -376,12 +503,10 @@ int main(int argc, char **argv) | |||
376 | fprintf(stderr, "Failed to find the trigger %s\n", | 503 | fprintf(stderr, "Failed to find the trigger %s\n", |
377 | trigger_name); | 504 | trigger_name); |
378 | ret = trig_num; | 505 | ret = trig_num; |
379 | goto error_free_triggername; | 506 | goto error; |
380 | } | 507 | } |
381 | 508 | ||
382 | printf("iio trigger number being used is %d\n", trig_num); | 509 | printf("iio trigger number being used is %d\n", trig_num); |
383 | } else { | ||
384 | printf("trigger-less mode selected\n"); | ||
385 | } | 510 | } |
386 | 511 | ||
387 | /* | 512 | /* |
@@ -392,7 +517,7 @@ int main(int argc, char **argv) | |||
392 | if (ret) { | 517 | if (ret) { |
393 | fprintf(stderr, "Problem reading scan element information\n" | 518 | fprintf(stderr, "Problem reading scan element information\n" |
394 | "diag %s\n", dev_dir_name); | 519 | "diag %s\n", dev_dir_name); |
395 | goto error_free_triggername; | 520 | goto error; |
396 | } | 521 | } |
397 | if (num_channels && autochannels == AUTOCHANNELS_ENABLED) { | 522 | if (num_channels && autochannels == AUTOCHANNELS_ENABLED) { |
398 | fprintf(stderr, "Auto-channels selected but some channels " | 523 | fprintf(stderr, "Auto-channels selected but some channels " |
@@ -407,7 +532,7 @@ int main(int argc, char **argv) | |||
407 | ret = enable_disable_all_channels(dev_dir_name, 1); | 532 | ret = enable_disable_all_channels(dev_dir_name, 1); |
408 | if (ret) { | 533 | if (ret) { |
409 | fprintf(stderr, "Failed to enable all channels\n"); | 534 | fprintf(stderr, "Failed to enable all channels\n"); |
410 | goto error_free_triggername; | 535 | goto error; |
411 | } | 536 | } |
412 | 537 | ||
413 | /* This flags that we need to disable the channels again */ | 538 | /* This flags that we need to disable the channels again */ |
@@ -419,12 +544,12 @@ int main(int argc, char **argv) | |||
419 | fprintf(stderr, "Problem reading scan element " | 544 | fprintf(stderr, "Problem reading scan element " |
420 | "information\n" | 545 | "information\n" |
421 | "diag %s\n", dev_dir_name); | 546 | "diag %s\n", dev_dir_name); |
422 | goto error_disable_channels; | 547 | goto error; |
423 | } | 548 | } |
424 | if (!num_channels) { | 549 | if (!num_channels) { |
425 | fprintf(stderr, "Still no channels after " | 550 | fprintf(stderr, "Still no channels after " |
426 | "auto-enabling, giving up\n"); | 551 | "auto-enabling, giving up\n"); |
427 | goto error_disable_channels; | 552 | goto error; |
428 | } | 553 | } |
429 | } | 554 | } |
430 | 555 | ||
@@ -436,7 +561,7 @@ int main(int argc, char **argv) | |||
436 | "/*_en or pass -a to autoenable channels and " | 561 | "/*_en or pass -a to autoenable channels and " |
437 | "try again.\n", dev_dir_name); | 562 | "try again.\n", dev_dir_name); |
438 | ret = -ENOENT; | 563 | ret = -ENOENT; |
439 | goto error_free_triggername; | 564 | goto error; |
440 | } | 565 | } |
441 | 566 | ||
442 | /* | 567 | /* |
@@ -448,7 +573,7 @@ int main(int argc, char **argv) | |||
448 | "%siio:device%d/buffer", iio_dir, dev_num); | 573 | "%siio:device%d/buffer", iio_dir, dev_num); |
449 | if (ret < 0) { | 574 | if (ret < 0) { |
450 | ret = -ENOMEM; | 575 | ret = -ENOMEM; |
451 | goto error_free_channels; | 576 | goto error; |
452 | } | 577 | } |
453 | 578 | ||
454 | if (!notrigger) { | 579 | if (!notrigger) { |
@@ -463,34 +588,34 @@ int main(int argc, char **argv) | |||
463 | if (ret < 0) { | 588 | if (ret < 0) { |
464 | fprintf(stderr, | 589 | fprintf(stderr, |
465 | "Failed to write current_trigger file\n"); | 590 | "Failed to write current_trigger file\n"); |
466 | goto error_free_buf_dir_name; | 591 | goto error; |
467 | } | 592 | } |
468 | } | 593 | } |
469 | 594 | ||
470 | /* Setup ring buffer parameters */ | 595 | /* Setup ring buffer parameters */ |
471 | ret = write_sysfs_int("length", buf_dir_name, buf_len); | 596 | ret = write_sysfs_int("length", buf_dir_name, buf_len); |
472 | if (ret < 0) | 597 | if (ret < 0) |
473 | goto error_free_buf_dir_name; | 598 | goto error; |
474 | 599 | ||
475 | /* Enable the buffer */ | 600 | /* Enable the buffer */ |
476 | ret = write_sysfs_int("enable", buf_dir_name, 1); | 601 | ret = write_sysfs_int("enable", buf_dir_name, 1); |
477 | if (ret < 0) { | 602 | if (ret < 0) { |
478 | fprintf(stderr, | 603 | fprintf(stderr, |
479 | "Failed to enable buffer: %s\n", strerror(-ret)); | 604 | "Failed to enable buffer: %s\n", strerror(-ret)); |
480 | goto error_free_buf_dir_name; | 605 | goto error; |
481 | } | 606 | } |
482 | 607 | ||
483 | scan_size = size_from_channelarray(channels, num_channels); | 608 | scan_size = size_from_channelarray(channels, num_channels); |
484 | data = malloc(scan_size * buf_len); | 609 | data = malloc(scan_size * buf_len); |
485 | if (!data) { | 610 | if (!data) { |
486 | ret = -ENOMEM; | 611 | ret = -ENOMEM; |
487 | goto error_free_buf_dir_name; | 612 | goto error; |
488 | } | 613 | } |
489 | 614 | ||
490 | ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num); | 615 | ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num); |
491 | if (ret < 0) { | 616 | if (ret < 0) { |
492 | ret = -ENOMEM; | 617 | ret = -ENOMEM; |
493 | goto error_free_data; | 618 | goto error; |
494 | } | 619 | } |
495 | 620 | ||
496 | /* Attempt to open non blocking the access dev */ | 621 | /* Attempt to open non blocking the access dev */ |
@@ -498,7 +623,7 @@ int main(int argc, char **argv) | |||
498 | if (fp == -1) { /* TODO: If it isn't there make the node */ | 623 | if (fp == -1) { /* TODO: If it isn't there make the node */ |
499 | ret = -errno; | 624 | ret = -errno; |
500 | fprintf(stderr, "Failed to open %s\n", buffer_access); | 625 | fprintf(stderr, "Failed to open %s\n", buffer_access); |
501 | goto error_free_buffer_access; | 626 | goto error; |
502 | } | 627 | } |
503 | 628 | ||
504 | for (j = 0; j < num_loops; j++) { | 629 | for (j = 0; j < num_loops; j++) { |
@@ -511,7 +636,7 @@ int main(int argc, char **argv) | |||
511 | ret = poll(&pfd, 1, -1); | 636 | ret = poll(&pfd, 1, -1); |
512 | if (ret < 0) { | 637 | if (ret < 0) { |
513 | ret = -errno; | 638 | ret = -errno; |
514 | goto error_close_buffer_access; | 639 | goto error; |
515 | } else if (ret == 0) { | 640 | } else if (ret == 0) { |
516 | continue; | 641 | continue; |
517 | } | 642 | } |
@@ -536,45 +661,21 @@ int main(int argc, char **argv) | |||
536 | num_channels); | 661 | num_channels); |
537 | } | 662 | } |
538 | 663 | ||
539 | /* Stop the buffer */ | 664 | error: |
540 | ret = write_sysfs_int("enable", buf_dir_name, 0); | 665 | cleanup(); |
541 | if (ret < 0) | ||
542 | goto error_close_buffer_access; | ||
543 | 666 | ||
544 | if (!notrigger) | 667 | if (fp >= 0 && close(fp) == -1) |
545 | /* Disconnect the trigger - just write a dummy name. */ | ||
546 | ret = write_sysfs_string("trigger/current_trigger", | ||
547 | dev_dir_name, "NULL"); | ||
548 | if (ret < 0) | ||
549 | fprintf(stderr, "Failed to write to %s\n", | ||
550 | dev_dir_name); | ||
551 | |||
552 | error_close_buffer_access: | ||
553 | if (close(fp) == -1) | ||
554 | perror("Failed to close buffer"); | 668 | perror("Failed to close buffer"); |
555 | |||
556 | error_free_buffer_access: | ||
557 | free(buffer_access); | 669 | free(buffer_access); |
558 | error_free_data: | ||
559 | free(data); | 670 | free(data); |
560 | error_free_buf_dir_name: | ||
561 | free(buf_dir_name); | 671 | free(buf_dir_name); |
562 | error_free_channels: | ||
563 | for (i = num_channels - 1; i >= 0; i--) { | 672 | for (i = num_channels - 1; i >= 0; i--) { |
564 | free(channels[i].name); | 673 | free(channels[i].name); |
565 | free(channels[i].generic_name); | 674 | free(channels[i].generic_name); |
566 | } | 675 | } |
567 | free(channels); | 676 | free(channels); |
568 | error_free_triggername: | 677 | free(trigger_name); |
569 | if (datardytrigger) | 678 | free(device_name); |
570 | free(trigger_name); | ||
571 | error_disable_channels: | ||
572 | if (autochannels == AUTOCHANNELS_ACTIVE) { | ||
573 | ret = enable_disable_all_channels(dev_dir_name, 0); | ||
574 | if (ret) | ||
575 | fprintf(stderr, "Failed to disable all channels\n"); | ||
576 | } | ||
577 | error_free_dev_dir_name: | ||
578 | free(dev_dir_name); | 679 | free(dev_dir_name); |
579 | 680 | ||
580 | return ret; | 681 | return ret; |