Re: Use LIS3MDL with LSM6DSM sensor-hub

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2020-03-19 18:40, Lorenzo Bianconi wrote:
On 2020-03-14 13:43, Lorenzo Bianconi wrote:
On Mar 11, Jimmy Assarsson wrote:
Hi,

We are working on a project where we want to connect LS6DSM (via SPI), and
connect LIS3MDL via the sensor hub, as I2C slave device.

We would like to add settings/configuration for LIS3MDL, to the shub
source, since currently only LIS2MDL is supported. We've made an attempt,
see diff at end of this mail.

1. LIS2MDL only got a single full scale setting, hence it is not possible
     to change. While LIS3MDL got four possible settings. Is it enough to add
     a corresponding function like st_lsm6dsx_shub_set_fs_val() and call it
     from st_lsm6dsx_shub_write_raw(), when mask == IIO_CHAN_INFO_SCALE?
2. LIS3MDL got 8 possible ODR settings, however ST_LSM6DSX_ODR_LIST_SIZE is
     defined to 6 (st_lsm6dsx.h). Is it fine to increase
     ST_LSM6DSX_ODR_LIST_SIZE to 8? This will also affect odr_table in
     struct st_lsm6dsx_settings.
3. In the patch, we've tried to copy the correct registers and values from
     magnetometer/st_magn_core.c, does it look ok?

The IIO subsystem is new to use, we possibly miss fundamental knowledge.

Regards,
jimmy

Hi Jimmy,

in order to set the full scale on LIS3MDL you can try the following patch (just
compiled, not tested)

Regards,
Lorenzo

Hi Lorenzo,

Sorry for the late response and thanks for the patch!

Hi Jimmy,

ok, I will post the patch, thx for testing.

Great, you can add
Tested-by: Jimmy Assarsson <jimmyassarsson@xxxxxxxxx>

The patches seems to work.
Are there any specific tests that we should carry out?
Via the sysfs interface, we've tested reading raw values of each channel and
configuring ODR and full scale.

you can try to enable batching in the hw FIFO doing something like:

$echo 1 > /sys/bus/iio/devices/<iio-magn>/scan_elements/in_magn_x_en
$echo 1 > /sys/bus/iio/devices/<iio-magn>/scan_elements/in_magn_y_en
$echo 1 > /sys/bus/iio/devices/<iio-magn>/scan_elements/in_magn_z_en
$echo 1 > /sys/bus/iio/devices/<iio-magn>/scan_elements/in_timestamp_en

$watermark=64
$echo $((2*watermark)) > /sys/bus/iio/devices/<iio-magn>/buffer/length
$echo $watermark > /sys/bus/iio/devices/<iio-magn>/buffer/watermark

$generic_buffer -gn lsm6dsm_magn -c <# of samples>

Ok. I don't got any scan_elements nor buffer directory, for any of the devices.
I guess it is not possible to use the FIFO without configuring any interrupt?
We got the following dts:
&spi1 {
	#address-cells = <1>;
	#size-cells = <0>;
	lsm6dsm@0 {
		compatible = "st,lsm6dsm";
		reg = <0x0>;

		spi-max-frequency = <500000>;
		st,pullups = "true";
	};
};

I'll look into this tomorrow or in the beginning of next week, thanks for the help.

Regards,
jimmy


Regards,
Lorenzo


Regards,
jimmy

diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
index 64ef07a30726..fec1dbd5f00d 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
@@ -518,6 +518,36 @@ st_lsm6dsx_shub_read_raw(struct iio_dev *iio_dev,
   	return ret;
   }
+static int
+st_lsm6dsx_shub_set_full_scale(struct st_lsm6dsx_sensor *sensor,
+			       u32 gain)
+{
+	const struct st_lsm6dsx_fs_table_entry *fs_table;
+	int i, err;
+
+	fs_table = &sensor->ext_info.settings->fs_table;
+	if (!fs_table->reg.addr)
+		return -ENOTSUPP;
+
+	for (i = 0; i < fs_table->fs_len; i++) {
+		if (fs_table->fs_avl[i].gain == gain)
+			break;
+	}
+
+	if (i == fs_table->fs_len)
+		return -EINVAL;
+
+	err = st_lsm6dsx_shub_write_with_mask(sensor, fs_table->reg.addr,
+					      fs_table->reg.mask,
+					      fs_table->fs_avl[i].val);
+	if (err < 0)
+		return err;
+
+	sensor->gain = gain;
+
+	return 0;
+}
+
   static int
   st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev,
   			  struct iio_chan_spec const *chan,
@@ -552,6 +582,9 @@ st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev,
   		}
   		break;
   	}
+	case IIO_CHAN_INFO_SCALE:
+		err = st_lsm6dsx_shub_set_full_scale(sensor, val2);
+		break;
   	default:
   		err = -EINVAL;
   		break;


---
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
index eea5556..8621dba 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
@@ -88,6 +88,69 @@ static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = {
   			.len = 6,
   		},
   	},
+	/* LIS3MDL */
+	{
+		.i2c_addr = { 0x1e },
+		.wai = {
+			.addr = 0x0f,
+			.val = 0x3d,
+		},
+		.id = ST_LSM6DSX_ID_MAGN,
+		.odr_table = {
+			.reg = {
+				.addr = 0x20,
+				.mask = GENMASK(4, 2),
+			},
+			.odr_avl[0] = {  1000, 0x0 },
+			.odr_avl[1] = {  2000, 0x1 },
+			.odr_avl[2] = {  3000, 0x2 },
+			.odr_avl[3] = {  5000, 0x3 },
+			.odr_avl[4] = { 10000, 0x4 },
+			.odr_avl[5] = { 20000, 0x5 },
+			.odr_avl[6] = { 40000, 0x6 },
+			.odr_avl[7] = { 80000, 0x7 },
+			.odr_len = 8,
+		},
+		.fs_table = {
+			.reg = {
+				.addr = 0x21,
+				.mask = GENMASK(6, 5),
+			},
+			.fs_avl[0] = {
+				.gain = 146,
+				.val = 0x00,
+			}, /* 4000 uG/LSB */
+			.fs_avl[1] = {
+				.gain = 292,
+				.val = 0x01,
+			}, /* 8000 uG/LSB */
+			.fs_avl[2] = {
+				.gain = 438,
+				.val = 0x02,
+			}, /* 12000 uG/LSB */
+			.fs_avl[3] = {
+				.gain = 584,
+				.val = 0x03,
+			}, /* 16000 uG/LSB */
+			.fs_len = 4,
+		},
+		.pwr_table = {
+			.reg = {
+				.addr = 0x22,
+				.mask = GENMASK(1, 0),
+			},
+			.off_val = 0x2,
+			.on_val = 0x0,
+		},
+		.bdu = {
+			.addr = 0x24,
+			.mask = BIT(6),
+		},
+		.out = {
+			.addr = 0x28,
+			.len = 6,
+		},
+	},
   };



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux