Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e6f6871 authored by Linus Walleij's avatar Linus Walleij Committed by Jonathan Cameron
Browse files

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: default avatarRob Herring <rob@kernel.org>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent 97865fe4
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@ Optional properties:
- st,drdy-int-pin: the pin on the package that will be used to signal
  "data ready" (valid values: 1 or 2). This property is not configurable
  on all sensors.
- drive-open-drain: the interrupt/data ready line will be configured
  as open drain, which is useful if several sensors share the same
  interrupt line. (This binding is taken from pinctrl/pinctrl-bindings.txt)
  This is a boolean property.

Sensors may also have applicable pin control settings, those use the
standard bindings from pinctrl/pinctrl-bindings.txt.
+8 −0
Original line number Diff line number Diff line
@@ -99,6 +99,8 @@
#define ST_ACCEL_2_DRDY_IRQ_INT2_MASK		0x10
#define ST_ACCEL_2_IHL_IRQ_ADDR			0x22
#define ST_ACCEL_2_IHL_IRQ_MASK			0x80
#define ST_ACCEL_2_OD_IRQ_ADDR			0x22
#define ST_ACCEL_2_OD_IRQ_MASK			0x40
#define ST_ACCEL_2_MULTIREAD_BIT		true

/* CUSTOM VALUES FOR SENSOR 3 */
@@ -180,6 +182,8 @@
#define ST_ACCEL_5_DRDY_IRQ_INT2_MASK		0x20
#define ST_ACCEL_5_IHL_IRQ_ADDR			0x22
#define ST_ACCEL_5_IHL_IRQ_MASK			0x80
#define ST_ACCEL_5_OD_IRQ_ADDR			0x22
#define ST_ACCEL_5_OD_IRQ_MASK			0x40
#define ST_ACCEL_5_IG1_EN_ADDR			0x21
#define ST_ACCEL_5_IG1_EN_MASK			0x08
#define ST_ACCEL_5_MULTIREAD_BIT		false
@@ -398,6 +402,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
			.mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK,
			.addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR,
			.mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK,
			.addr_od = ST_ACCEL_2_OD_IRQ_ADDR,
			.mask_od = ST_ACCEL_2_OD_IRQ_MASK,
			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
		},
		.multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
@@ -587,6 +593,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
			.mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK,
			.addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR,
			.mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK,
			.addr_od = ST_ACCEL_5_OD_IRQ_ADDR,
			.mask_od = ST_ACCEL_5_OD_IRQ_MASK,
			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
		},
		.multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT,
+20 −0
Original line number Diff line number Diff line
@@ -301,6 +301,14 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
		return -EINVAL;
	}

	if (pdata->open_drain) {
		if (!sdata->sensor_settings->drdy_irq.addr_od)
			dev_err(&indio_dev->dev,
				"open drain requested but unsupported.\n");
		else
			sdata->int_pin_open_drain = true;
	}

	return 0;
}

@@ -321,6 +329,8 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
	else
		pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0;

	pdata->open_drain = of_property_read_bool(np, "drive-open-drain");

	return pdata;
}
#else
@@ -374,6 +384,16 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,
			return err;
	}

	if (sdata->int_pin_open_drain) {
		dev_info(&indio_dev->dev,
			 "set interrupt line to open drain mode\n");
		err = st_sensors_write_data_with_mask(indio_dev,
				sdata->sensor_settings->drdy_irq.addr_od,
				sdata->sensor_settings->drdy_irq.mask_od, 1);
		if (err < 0)
			return err;
	}

	err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);

	return err;
+13 −0
Original line number Diff line number Diff line
@@ -64,6 +64,19 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
			"rising edge\n", irq_trig);
		irq_trig = IRQF_TRIGGER_RISING;
	}

	/*
	 * If the interrupt pin is Open Drain, by definition this
	 * means that the interrupt line may be shared with other
	 * peripherals. But to do this we also need to have a status
	 * register and mask to figure out if this sensor was firing
	 * the IRQ or not, so we can tell the interrupt handle that
	 * it was "our" interrupt.
	 */
	if (sdata->int_pin_open_drain &&
	    sdata->sensor_settings->drdy_irq.addr_stat_drdy)
		irq_trig |= IRQF_SHARED;

	err = request_threaded_irq(irq,
			iio_trigger_generic_data_rdy_poll,
			NULL,
+8 −0
Original line number Diff line number Diff line
@@ -64,6 +64,8 @@
#define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK	0x20
#define ST_PRESS_LPS331AP_IHL_IRQ_ADDR		0x22
#define ST_PRESS_LPS331AP_IHL_IRQ_MASK		0x80
#define ST_PRESS_LPS331AP_OD_IRQ_ADDR		0x22
#define ST_PRESS_LPS331AP_OD_IRQ_MASK		0x40
#define ST_PRESS_LPS331AP_MULTIREAD_BIT		true
#define ST_PRESS_LPS331AP_TEMP_OFFSET		42500

@@ -104,6 +106,8 @@
#define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK	0x10
#define ST_PRESS_LPS25H_IHL_IRQ_ADDR		0x22
#define ST_PRESS_LPS25H_IHL_IRQ_MASK		0x80
#define ST_PRESS_LPS25H_OD_IRQ_ADDR		0x22
#define ST_PRESS_LPS25H_OD_IRQ_MASK		0x40
#define ST_PRESS_LPS25H_MULTIREAD_BIT		true
#define ST_PRESS_LPS25H_TEMP_OFFSET		42500
#define ST_PRESS_LPS25H_OUT_XL_ADDR		0x28
@@ -226,6 +230,8 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
			.mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK,
			.addr_ihl = ST_PRESS_LPS331AP_IHL_IRQ_ADDR,
			.mask_ihl = ST_PRESS_LPS331AP_IHL_IRQ_MASK,
			.addr_od = ST_PRESS_LPS331AP_OD_IRQ_ADDR,
			.mask_od = ST_PRESS_LPS331AP_OD_IRQ_MASK,
			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
		},
		.multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT,
@@ -313,6 +319,8 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
			.mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK,
			.addr_ihl = ST_PRESS_LPS25H_IHL_IRQ_ADDR,
			.mask_ihl = ST_PRESS_LPS25H_IHL_IRQ_MASK,
			.addr_od = ST_PRESS_LPS25H_OD_IRQ_ADDR,
			.mask_od = ST_PRESS_LPS25H_OD_IRQ_MASK,
			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
		},
		.multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT,
Loading