cancel
Showing results for 
Search instead for 
Did you mean: 

ISM330DLC: Interrupt on Linux

Tdo.1
Associate II

Hello,

I'm try using ISM330DLC connect to Linux OS on board IMX8MP via I2C

Linux supported driver for this device (iio/imu/st_lsm6dsx); I added to dts file as below:

&i2c5 {
	clock-frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c5>;
	pinctrl-assert-gpios = <&pca6416 2 GPIO_ACTIVE_HIGH>; /* i2c5 pin conflict with can1: default gpio low select can1, gpio high select i2c5 */
	status = "okay";
 
	ism330dlc@6b {
		compatible = "st,ism330dlc";
		reg = <0x6b>;
		st,drdy-int-pin = <1>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_ioexp_int>;
		interrupt-parent = <&gpio1>;
		interrupts = <12 IRQ_TYPE_EDGE_RISING>;
	};
};

But I didn't see any interrupt signal to Linux

# cat /proc/interrupts | grep 12
  6:      12073      10115      14187       8714  GPCv2 i.MX8MQ  47 Level     timer@306a0000
 38:        127          0          0          0  GPCv2 i.MX8MQ  76 Level     30ad0000.i2c
 46:       6787          0          0          0  GPCv2 i.MX8MQ 120 Level     30be0000.ethernet
 50:          0          0          0          0  GPCv2 i.MX8MQ 122 Level     30c90000.easrc
 56:          0          0          0          0  GPCv2 i.MX8MQ 128 Level     30cc0000.xcvr
 57:          0          0          0          0  GPCv2 i.MX8MQ 129 Level     30cc0000.xcvr
 95:          0          0          0          0  gpio-mxc  12 Edge      lsm6dsx
127:          0          0          0          0  gpio-mxc  12 Edge      30b50000.mmc cd

could you give some recommend to resolve this issue ?

Thanks in advance !

tam do

1 ACCEPTED SOLUTION

Accepted Solutions
Tdo.1
Associate II

Resolved:

In my case, I have to do more steps with this driver to resolve issue:

  • Enable pulsed data-ready mode instead of Latch mode
  • Enable master DRDY on INT1
  • Change interrupt type flag from IRQF_TRIGGER_HIGH to IRQF_TRIGGER_RISING (modification in device tree is not effect)
diff --git a/drivers/iio/imu/st_ism330dlc/st_ism330dlc_core.c b/drivers/iio/imu/st_ism330dlc/st_ism330dlc_core.c
index 998d234..d326d74 100644
--- a/drivers/iio/imu/st_ism330dlc/st_ism330dlc_core.c
+++ b/drivers/iio/imu/st_ism330dlc/st_ism330dlc_core.c
@@ -117,6 +117,14 @@
 #define ST_ISM330DLC_SELFTEST_FAIL_MS			"fail"
 #define ST_ISM330DLC_SELFTEST_PASS_MS			"pass"
 
+
+#define ST_ISM330DLC_DRDY_PULSED_ADDR		0x0b
+#define ST_ISM330DLC_DRDY_PULSED_MASK		0x80
+
+#define ST_ISM330DLC_DRDY_ON_INT1_ADDR		0x1a
+#define ST_ISM330DLC_DRDY_ON_INT1_MASK		0x80
+
+
 /* CUSTOM VALUES FOR ACCEL SENSOR */
 #define ST_ISM330DLC_ACCEL_ODR_ADDR			0x10
 #define ST_ISM330DLC_ACCEL_ODR_MASK			0xf0
@@ -1723,10 +1731,10 @@ static int st_ism330dlc_init_sensor(struct ism330dlc_data *cdata)
 	msleep(200);
 
 	/* Latch interrupts */
-	err = st_ism330dlc_write_data_with_mask(cdata, ST_ISM330DLC_LIR_ADDR,
-				ST_ISM330DLC_LIR_MASK, ST_ISM330DLC_EN_BIT, true);
-	if (err < 0)
-		return err;
+//	err = st_ism330dlc_write_data_with_mask(cdata, ST_ISM330DLC_LIR_ADDR,
+//				ST_ISM330DLC_LIR_MASK, ST_ISM330DLC_EN_BIT, true);
+//	if (err < 0)
+//		return err;
 
 	/* Enable BDU for sensors data */
 	err = st_ism330dlc_write_data_with_mask(cdata, ST_ISM330DLC_BDU_ADDR,
@@ -1741,6 +1749,15 @@ static int st_ism330dlc_init_sensor(struct ism330dlc_data *cdata)
 	if (err < 0)
 		return err;
 
+	/* Enable pulsed data-ready mode */
+	err = st_ism330dlc_write_data_with_mask(cdata,
+					ST_ISM330DLC_DRDY_PULSED_ADDR,
+					ST_ISM330DLC_DRDY_PULSED_MASK,
+					ST_ISM330DLC_EN_BIT, true);
+	if (err < 0)
+		return err;
+
+
 	/* Redirect INT2 on INT1, all interrupt will be available on INT1 */
 	err = st_ism330dlc_write_data_with_mask(cdata,
 					ST_ISM330DLC_INT2_ON_INT1_ADDR,
@@ -1749,6 +1766,14 @@ static int st_ism330dlc_init_sensor(struct ism330dlc_data *cdata)
 	if (err < 0)
 		return err;
 
+	/* Enable master DRDY on INT1 */
+	err = st_ism330dlc_write_data_with_mask(cdata,
+					ST_ISM330DLC_DRDY_ON_INT1_ADDR,
+					ST_ISM330DLC_DRDY_ON_INT1_MASK,
+					ST_ISM330DLC_EN_BIT, true);
+	if (err < 0)
+		return err;
+
 	return st_ism330dlc_get_drdy_reg(cdata, &cdata->drdy_reg);
 }
 
diff --git a/drivers/iio/imu/st_ism330dlc/st_ism330dlc_trigger.c b/drivers/iio/imu/st_ism330dlc/st_ism330dlc_trigger.c
index 98038b5..07e887f 100644
--- a/drivers/iio/imu/st_ism330dlc/st_ism330dlc_trigger.c
+++ b/drivers/iio/imu/st_ism330dlc/st_ism330dlc_trigger.c
@@ -132,7 +132,7 @@ int st_ism330dlc_allocate_triggers(struct ism330dlc_data *cdata,
 	}
 
 	err = request_threaded_irq(cdata->irq, NULL, ism330dlc_irq_management,
-				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
 				   cdata->name, cdata);
 	if (err)
 		goto deallocate_trigger;
 

Note: When integrating to new version of kernel as 5.x, need to change api 'get_monotonic_boottime' to 'ktime_get_ts' in a few code statements.

View solution in original post

6 REPLIES 6
Eleon BORLINI
ST Employee

Hi @Tdo.1​ ,

I'm not an expert of Linux environment, so I'm waiting for internal expert feedback.

You wrote:

>> Linux supported driver for this device (iio/imu/st_lsm6dsx); I added to dts file

Please note however that there are official linux driver at THIS link for the ISM330DLC, especially the st_ism330dlc_i2c.c and st_ism330dlc_i2c_master.c files for the I2C peripheral configuration.

Let me know if they can help you for your purpose.

-Eleon

Tdo.1
Associate II

Hi @Eleon BORLINI​ 

Thank you for reply

I integrated driver from your link to my current Linux (5.4.24), it's same result as before. I only can ONESHOT conversions by reading `/sys/bus/iio/devices/iio:device0/in_accel_y_raw`

my dts for ISM330DLC:

ism330dlc@6b {
		compatible = "st,ism330dlc";
		reg = <0x6b>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_ioexp_int>;
		interrupt-parent = <&gpio1>;
		interrupts = <12 IRQ_TYPE_LEVEL_HIGH>;
		st,drdy-int-pin = <1>;
	};

I also tested with other IMU as a reference (MPU6050). I connected MPU6050 same as ISM330DLC to board (same I2C, GPIO pin on IMX board) and MPU6050 was worked.

DTS for MPU6050:

inv-mpu6050@68 {
		compatible = "invensense,mpu6050";
		reg = <0x68>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_ioexp_int>;
		interrupt-parent = <&gpio1>;
		interrupts = <12 IRQ_TYPE_EDGE_RISING>;
		mount-matrix =  "-0.984807753012208",  /* x0 */
				"0",                   /* y0 */
				"-0.173648177666930",  /* z0 */
				"0",                   /* x1 */
				"-1",                  /* y1 */
				"0",                   /* z1 */
				"-0.173648177666930",  /* x2 */
				"0",                   /* y2 */
				"0.984807753012208";   /* z2 */
	};

I'm not sure connector between ISM330DLC and board maybe a problem or no :(

Hi @Tdo.1​ ,

can you check if the ISM330DLC INT1 or INT2 pins have been routed out on the IMX8MP?

The data ready (DRDY) signal can be for example routed on INT1 physical pin enabling the data ready setting to 1 the INT1_DRDY_XL of INT1_CTRL (0Dh) and writing the DRDY_ON_INT1 bit of MASTER_CONFIG (1Ah) register.

Just to check if it is not an hardware problem...

-Eleon

Hi @Eleon BORLINI​ ,

I connected INT1 pin to a GPIO pin on the IMX8MP.

  • After insmode module, I use oscilloscope to check signal on INT1 pin, value is always LOW (0).
  • After I enable IIO trigger mode by writing 1 to `/sys/bus/iio/devices/iio:device0/buffer/enable​`, out of INT1 almost in HIGH level (..1111110111111101111111111...) when checking value of gpio (gpio503 on Linux) that connecting to INT1 pin , and value is almost 1, sometime it's 0;
echo 503 > /sys/class/gpio/export
watch -n 1 cat /sys/class/gpio/gpio503/value
1

  • The same when reading iio buffer by: `xxd /dev/iio:device0`, value is almost HIGH.
Tdo.1
Associate II

Resolved:

In my case, I have to do more steps with this driver to resolve issue:

  • Enable pulsed data-ready mode instead of Latch mode
  • Enable master DRDY on INT1
  • Change interrupt type flag from IRQF_TRIGGER_HIGH to IRQF_TRIGGER_RISING (modification in device tree is not effect)
diff --git a/drivers/iio/imu/st_ism330dlc/st_ism330dlc_core.c b/drivers/iio/imu/st_ism330dlc/st_ism330dlc_core.c
index 998d234..d326d74 100644
--- a/drivers/iio/imu/st_ism330dlc/st_ism330dlc_core.c
+++ b/drivers/iio/imu/st_ism330dlc/st_ism330dlc_core.c
@@ -117,6 +117,14 @@
 #define ST_ISM330DLC_SELFTEST_FAIL_MS			"fail"
 #define ST_ISM330DLC_SELFTEST_PASS_MS			"pass"
 
+
+#define ST_ISM330DLC_DRDY_PULSED_ADDR		0x0b
+#define ST_ISM330DLC_DRDY_PULSED_MASK		0x80
+
+#define ST_ISM330DLC_DRDY_ON_INT1_ADDR		0x1a
+#define ST_ISM330DLC_DRDY_ON_INT1_MASK		0x80
+
+
 /* CUSTOM VALUES FOR ACCEL SENSOR */
 #define ST_ISM330DLC_ACCEL_ODR_ADDR			0x10
 #define ST_ISM330DLC_ACCEL_ODR_MASK			0xf0
@@ -1723,10 +1731,10 @@ static int st_ism330dlc_init_sensor(struct ism330dlc_data *cdata)
 	msleep(200);
 
 	/* Latch interrupts */
-	err = st_ism330dlc_write_data_with_mask(cdata, ST_ISM330DLC_LIR_ADDR,
-				ST_ISM330DLC_LIR_MASK, ST_ISM330DLC_EN_BIT, true);
-	if (err < 0)
-		return err;
+//	err = st_ism330dlc_write_data_with_mask(cdata, ST_ISM330DLC_LIR_ADDR,
+//				ST_ISM330DLC_LIR_MASK, ST_ISM330DLC_EN_BIT, true);
+//	if (err < 0)
+//		return err;
 
 	/* Enable BDU for sensors data */
 	err = st_ism330dlc_write_data_with_mask(cdata, ST_ISM330DLC_BDU_ADDR,
@@ -1741,6 +1749,15 @@ static int st_ism330dlc_init_sensor(struct ism330dlc_data *cdata)
 	if (err < 0)
 		return err;
 
+	/* Enable pulsed data-ready mode */
+	err = st_ism330dlc_write_data_with_mask(cdata,
+					ST_ISM330DLC_DRDY_PULSED_ADDR,
+					ST_ISM330DLC_DRDY_PULSED_MASK,
+					ST_ISM330DLC_EN_BIT, true);
+	if (err < 0)
+		return err;
+
+
 	/* Redirect INT2 on INT1, all interrupt will be available on INT1 */
 	err = st_ism330dlc_write_data_with_mask(cdata,
 					ST_ISM330DLC_INT2_ON_INT1_ADDR,
@@ -1749,6 +1766,14 @@ static int st_ism330dlc_init_sensor(struct ism330dlc_data *cdata)
 	if (err < 0)
 		return err;
 
+	/* Enable master DRDY on INT1 */
+	err = st_ism330dlc_write_data_with_mask(cdata,
+					ST_ISM330DLC_DRDY_ON_INT1_ADDR,
+					ST_ISM330DLC_DRDY_ON_INT1_MASK,
+					ST_ISM330DLC_EN_BIT, true);
+	if (err < 0)
+		return err;
+
 	return st_ism330dlc_get_drdy_reg(cdata, &cdata->drdy_reg);
 }
 
diff --git a/drivers/iio/imu/st_ism330dlc/st_ism330dlc_trigger.c b/drivers/iio/imu/st_ism330dlc/st_ism330dlc_trigger.c
index 98038b5..07e887f 100644
--- a/drivers/iio/imu/st_ism330dlc/st_ism330dlc_trigger.c
+++ b/drivers/iio/imu/st_ism330dlc/st_ism330dlc_trigger.c
@@ -132,7 +132,7 @@ int st_ism330dlc_allocate_triggers(struct ism330dlc_data *cdata,
 	}
 
 	err = request_threaded_irq(cdata->irq, NULL, ism330dlc_irq_management,
-				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
 				   cdata->name, cdata);
 	if (err)
 		goto deallocate_trigger;
 

Note: When integrating to new version of kernel as 5.x, need to change api 'get_monotonic_boottime' to 'ktime_get_ts' in a few code statements.

Hi @Tdo.1​ ,

thank you very much for your follow up on resolved case :smiling_face_with_smiling_eyes:

...and sorry for coming back to you late.

-Eleon