aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2016-04-14 04:45:21 -0400
committerJonathan Cameron <jic23@kernel.org>2016-04-19 14:58:13 -0400
commit0e6f6871a1591f4bb0971809c45bc91a991f1967 (patch)
tree45aa87a59f586c7aff129809ca3cc017b4d36895
parent97865fe41322d83dac4373fe0a0de5b1a1b318c5 (diff)
iio: st_sensors: support open drain mode
Some types of ST Sensors can be connected to the same IRQ line as other peripherals using open drain. Add a device tree binding and a sensor data property to flip the right bit in the interrupt control register to enable open drain mode on the INT line. If the line is set to be open drain, also tag on IRQF_SHARED to the IRQ flags when requesting the interrupt, as the whole point of using open drain interrupt lines is to share them with more than one peripheral (wire-or). Cc: devicetree@vger.kernel.org Cc: Giuseppe Barba <giuseppe.barba@st.com> Cc: Denis Ciocca <denis.ciocca@st.com> Acked-by: Rob Herring <rob@kernel.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--Documentation/devicetree/bindings/iio/st-sensors.txt4
-rw-r--r--drivers/iio/accel/st_accel_core.c8
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_core.c20
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_trigger.c13
-rw-r--r--drivers/iio/pressure/st_pressure_core.c8
-rw-r--r--include/linux/iio/common/st_sensors.h6
-rw-r--r--include/linux/platform_data/st_sensors_pdata.h2
7 files changed, 61 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt
index 71b7bdff21cd..637e283f4a8b 100644
--- a/Documentation/devicetree/bindings/iio/st-sensors.txt
+++ b/Documentation/devicetree/bindings/iio/st-sensors.txt
@@ -16,6 +16,10 @@ Optional properties:
16- st,drdy-int-pin: the pin on the package that will be used to signal 16- st,drdy-int-pin: the pin on the package that will be used to signal
17 "data ready" (valid values: 1 or 2). This property is not configurable 17 "data ready" (valid values: 1 or 2). This property is not configurable
18 on all sensors. 18 on all sensors.
19- drive-open-drain: the interrupt/data ready line will be configured
20 as open drain, which is useful if several sensors share the same
21 interrupt line. (This binding is taken from pinctrl/pinctrl-bindings.txt)
22 This is a boolean property.
19 23
20Sensors may also have applicable pin control settings, those use the 24Sensors may also have applicable pin control settings, those use the
21standard bindings from pinctrl/pinctrl-bindings.txt. 25standard bindings from pinctrl/pinctrl-bindings.txt.
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 9fb6d35fce5b..dc73f2d85e6d 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -99,6 +99,8 @@
99#define ST_ACCEL_2_DRDY_IRQ_INT2_MASK 0x10 99#define ST_ACCEL_2_DRDY_IRQ_INT2_MASK 0x10
100#define ST_ACCEL_2_IHL_IRQ_ADDR 0x22 100#define ST_ACCEL_2_IHL_IRQ_ADDR 0x22
101#define ST_ACCEL_2_IHL_IRQ_MASK 0x80 101#define ST_ACCEL_2_IHL_IRQ_MASK 0x80
102#define ST_ACCEL_2_OD_IRQ_ADDR 0x22
103#define ST_ACCEL_2_OD_IRQ_MASK 0x40
102#define ST_ACCEL_2_MULTIREAD_BIT true 104#define ST_ACCEL_2_MULTIREAD_BIT true
103 105
104/* CUSTOM VALUES FOR SENSOR 3 */ 106/* CUSTOM VALUES FOR SENSOR 3 */
@@ -180,6 +182,8 @@
180#define ST_ACCEL_5_DRDY_IRQ_INT2_MASK 0x20 182#define ST_ACCEL_5_DRDY_IRQ_INT2_MASK 0x20
181#define ST_ACCEL_5_IHL_IRQ_ADDR 0x22 183#define ST_ACCEL_5_IHL_IRQ_ADDR 0x22
182#define ST_ACCEL_5_IHL_IRQ_MASK 0x80 184#define ST_ACCEL_5_IHL_IRQ_MASK 0x80
185#define ST_ACCEL_5_OD_IRQ_ADDR 0x22
186#define ST_ACCEL_5_OD_IRQ_MASK 0x40
183#define ST_ACCEL_5_IG1_EN_ADDR 0x21 187#define ST_ACCEL_5_IG1_EN_ADDR 0x21
184#define ST_ACCEL_5_IG1_EN_MASK 0x08 188#define ST_ACCEL_5_IG1_EN_MASK 0x08
185#define ST_ACCEL_5_MULTIREAD_BIT false 189#define ST_ACCEL_5_MULTIREAD_BIT false
@@ -398,6 +402,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
398 .mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK, 402 .mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK,
399 .addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR, 403 .addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR,
400 .mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK, 404 .mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK,
405 .addr_od = ST_ACCEL_2_OD_IRQ_ADDR,
406 .mask_od = ST_ACCEL_2_OD_IRQ_MASK,
401 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, 407 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
402 }, 408 },
403 .multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT, 409 .multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
@@ -587,6 +593,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
587 .mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK, 593 .mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK,
588 .addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR, 594 .addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR,
589 .mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK, 595 .mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK,
596 .addr_od = ST_ACCEL_5_OD_IRQ_ADDR,
597 .mask_od = ST_ACCEL_5_OD_IRQ_MASK,
590 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, 598 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
591 }, 599 },
592 .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT, 600 .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT,
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
index f5a2d445d0c0..dffe00692169 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.c
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -301,6 +301,14 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
301 return -EINVAL; 301 return -EINVAL;
302 } 302 }
303 303
304 if (pdata->open_drain) {
305 if (!sdata->sensor_settings->drdy_irq.addr_od)
306 dev_err(&indio_dev->dev,
307 "open drain requested but unsupported.\n");
308 else
309 sdata->int_pin_open_drain = true;
310 }
311
304 return 0; 312 return 0;
305} 313}
306 314
@@ -321,6 +329,8 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
321 else 329 else
322 pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0; 330 pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0;
323 331
332 pdata->open_drain = of_property_read_bool(np, "drive-open-drain");
333
324 return pdata; 334 return pdata;
325} 335}
326#else 336#else
@@ -374,6 +384,16 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,
374 return err; 384 return err;
375 } 385 }
376 386
387 if (sdata->int_pin_open_drain) {
388 dev_info(&indio_dev->dev,
389 "set interrupt line to open drain mode\n");
390 err = st_sensors_write_data_with_mask(indio_dev,
391 sdata->sensor_settings->drdy_irq.addr_od,
392 sdata->sensor_settings->drdy_irq.mask_od, 1);
393 if (err < 0)
394 return err;
395 }
396
377 err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); 397 err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
378 398
379 return err; 399 return err;
diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
index 6a8c98327945..da72279fcf99 100644
--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c
+++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
@@ -64,6 +64,19 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
64 "rising edge\n", irq_trig); 64 "rising edge\n", irq_trig);
65 irq_trig = IRQF_TRIGGER_RISING; 65 irq_trig = IRQF_TRIGGER_RISING;
66 } 66 }
67
68 /*
69 * If the interrupt pin is Open Drain, by definition this
70 * means that the interrupt line may be shared with other
71 * peripherals. But to do this we also need to have a status
72 * register and mask to figure out if this sensor was firing
73 * the IRQ or not, so we can tell the interrupt handle that
74 * it was "our" interrupt.
75 */
76 if (sdata->int_pin_open_drain &&
77 sdata->sensor_settings->drdy_irq.addr_stat_drdy)
78 irq_trig |= IRQF_SHARED;
79
67 err = request_threaded_irq(irq, 80 err = request_threaded_irq(irq,
68 iio_trigger_generic_data_rdy_poll, 81 iio_trigger_generic_data_rdy_poll,
69 NULL, 82 NULL,
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index 1cd37eaa4a57..9e9b72a8f18f 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -64,6 +64,8 @@
64#define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK 0x20 64#define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK 0x20
65#define ST_PRESS_LPS331AP_IHL_IRQ_ADDR 0x22 65#define ST_PRESS_LPS331AP_IHL_IRQ_ADDR 0x22
66#define ST_PRESS_LPS331AP_IHL_IRQ_MASK 0x80 66#define ST_PRESS_LPS331AP_IHL_IRQ_MASK 0x80
67#define ST_PRESS_LPS331AP_OD_IRQ_ADDR 0x22
68#define ST_PRESS_LPS331AP_OD_IRQ_MASK 0x40
67#define ST_PRESS_LPS331AP_MULTIREAD_BIT true 69#define ST_PRESS_LPS331AP_MULTIREAD_BIT true
68#define ST_PRESS_LPS331AP_TEMP_OFFSET 42500 70#define ST_PRESS_LPS331AP_TEMP_OFFSET 42500
69 71
@@ -104,6 +106,8 @@
104#define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK 0x10 106#define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK 0x10
105#define ST_PRESS_LPS25H_IHL_IRQ_ADDR 0x22 107#define ST_PRESS_LPS25H_IHL_IRQ_ADDR 0x22
106#define ST_PRESS_LPS25H_IHL_IRQ_MASK 0x80 108#define ST_PRESS_LPS25H_IHL_IRQ_MASK 0x80
109#define ST_PRESS_LPS25H_OD_IRQ_ADDR 0x22
110#define ST_PRESS_LPS25H_OD_IRQ_MASK 0x40
107#define ST_PRESS_LPS25H_MULTIREAD_BIT true 111#define ST_PRESS_LPS25H_MULTIREAD_BIT true
108#define ST_PRESS_LPS25H_TEMP_OFFSET 42500 112#define ST_PRESS_LPS25H_TEMP_OFFSET 42500
109#define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28 113#define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28
@@ -226,6 +230,8 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
226 .mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK, 230 .mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK,
227 .addr_ihl = ST_PRESS_LPS331AP_IHL_IRQ_ADDR, 231 .addr_ihl = ST_PRESS_LPS331AP_IHL_IRQ_ADDR,
228 .mask_ihl = ST_PRESS_LPS331AP_IHL_IRQ_MASK, 232 .mask_ihl = ST_PRESS_LPS331AP_IHL_IRQ_MASK,
233 .addr_od = ST_PRESS_LPS331AP_OD_IRQ_ADDR,
234 .mask_od = ST_PRESS_LPS331AP_OD_IRQ_MASK,
229 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, 235 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
230 }, 236 },
231 .multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT, 237 .multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT,
@@ -313,6 +319,8 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
313 .mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK, 319 .mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK,
314 .addr_ihl = ST_PRESS_LPS25H_IHL_IRQ_ADDR, 320 .addr_ihl = ST_PRESS_LPS25H_IHL_IRQ_ADDR,
315 .mask_ihl = ST_PRESS_LPS25H_IHL_IRQ_MASK, 321 .mask_ihl = ST_PRESS_LPS25H_IHL_IRQ_MASK,
322 .addr_od = ST_PRESS_LPS25H_OD_IRQ_ADDR,
323 .mask_od = ST_PRESS_LPS25H_OD_IRQ_MASK,
316 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, 324 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
317 }, 325 },
318 .multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT, 326 .multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT,
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
index d8da075bfda0..d029ffac0d69 100644
--- a/include/linux/iio/common/st_sensors.h
+++ b/include/linux/iio/common/st_sensors.h
@@ -122,6 +122,8 @@ struct st_sensor_bdu {
122 * @mask_int2: mask to enable/disable IRQ on INT2 pin. 122 * @mask_int2: mask to enable/disable IRQ on INT2 pin.
123 * @addr_ihl: address to enable/disable active low on the INT lines. 123 * @addr_ihl: address to enable/disable active low on the INT lines.
124 * @mask_ihl: mask to enable/disable active low on the INT lines. 124 * @mask_ihl: mask to enable/disable active low on the INT lines.
125 * @addr_od: address to enable/disable Open Drain on the INT lines.
126 * @mask_od: mask to enable/disable Open Drain on the INT lines.
125 * @addr_stat_drdy: address to read status of DRDY (data ready) interrupt 127 * @addr_stat_drdy: address to read status of DRDY (data ready) interrupt
126 * struct ig1 - represents the Interrupt Generator 1 of sensors. 128 * struct ig1 - represents the Interrupt Generator 1 of sensors.
127 * @en_addr: address of the enable ig1 register. 129 * @en_addr: address of the enable ig1 register.
@@ -133,6 +135,8 @@ struct st_sensor_data_ready_irq {
133 u8 mask_int2; 135 u8 mask_int2;
134 u8 addr_ihl; 136 u8 addr_ihl;
135 u8 mask_ihl; 137 u8 mask_ihl;
138 u8 addr_od;
139 u8 mask_od;
136 u8 addr_stat_drdy; 140 u8 addr_stat_drdy;
137 struct { 141 struct {
138 u8 en_addr; 142 u8 en_addr;
@@ -215,6 +219,7 @@ struct st_sensor_settings {
215 * @odr: Output data rate of the sensor [Hz]. 219 * @odr: Output data rate of the sensor [Hz].
216 * num_data_channels: Number of data channels used in buffer. 220 * num_data_channels: Number of data channels used in buffer.
217 * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). 221 * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2).
222 * @int_pin_open_drain: Set the interrupt/DRDY to open drain.
218 * @get_irq_data_ready: Function to get the IRQ used for data ready signal. 223 * @get_irq_data_ready: Function to get the IRQ used for data ready signal.
219 * @tf: Transfer function structure used by I/O operations. 224 * @tf: Transfer function structure used by I/O operations.
220 * @tb: Transfer buffers and mutex used by I/O operations. 225 * @tb: Transfer buffers and mutex used by I/O operations.
@@ -236,6 +241,7 @@ struct st_sensor_data {
236 unsigned int num_data_channels; 241 unsigned int num_data_channels;
237 242
238 u8 drdy_int_pin; 243 u8 drdy_int_pin;
244 bool int_pin_open_drain;
239 245
240 unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev); 246 unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev);
241 247
diff --git a/include/linux/platform_data/st_sensors_pdata.h b/include/linux/platform_data/st_sensors_pdata.h
index 753839187ba0..79b0e4cdb814 100644
--- a/include/linux/platform_data/st_sensors_pdata.h
+++ b/include/linux/platform_data/st_sensors_pdata.h
@@ -16,9 +16,11 @@
16 * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). 16 * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2).
17 * Available only for accelerometer and pressure sensors. 17 * Available only for accelerometer and pressure sensors.
18 * Accelerometer DRDY on LSM330 available only on pin 1 (see datasheet). 18 * Accelerometer DRDY on LSM330 available only on pin 1 (see datasheet).
19 * @open_drain: set the interrupt line to be open drain if possible.
19 */ 20 */
20struct st_sensors_platform_data { 21struct st_sensors_platform_data {
21 u8 drdy_int_pin; 22 u8 drdy_int_pin;
23 bool open_drain;
22}; 24};
23 25
24#endif /* ST_SENSORS_PDATA_H */ 26#endif /* ST_SENSORS_PDATA_H */