On 15.07.19 23:49, Lorenzo Bianconi wrote: >> The LSM9DS1's accelerometer / gyroscope unit and it's magnetometer (separately >> supported in iio/magnetometer/st_magn*) are located on a separate i2c addresses >> on the bus. >> >> For the datasheet, see https://www.st.com/resource/en/datasheet/lsm9ds1.pdf >> >> Treat it just like the LSM6* devices and, despite it's name, hook it up >> to the st_lsm6dsx driver, using it's basic functionality. >> >> Signed-off-by: Martin Kepplinger <martin.kepplinger@xxxxxxx> >> --- >> >> What do you think about an addition like this? How confusing is it to support >> an LSM9 module by the lsm6 driver, despite it's name? It requires almost no >> code, so why not think about it, right? > > I am fine with (it was on my ToDo list, so thanks for working on this). > I have just posted the following series that will help you adding support for > LSM9DS1 > https://patchwork.kernel.org/cover/11045061/ > I think you just need to take care of gyro channels allocating iio devices (you > probably need to pass hw_id to st_lsm6dsx_alloc_iiodev()) yes. I'll look over allocation once more. > >> >> Oh, I'm not 100% convinced by my new "if" in probe(), but even that is >> not too confusing I guess. >> >> thanks, >> >> martin >> >> p.s.: todos: >> * hook up the fifo / buffer / trigger functionality, >> * (off-topic a bit) move the (currently strange) gyro-only support >> for lsm9ds0 to this driver as well. > > Regarding FIFO I guess it is enough to set decimator factor to 1 for both accel > and gyro. > > Regards, > Lorenzo > >> >> >> >> drivers/iio/imu/st_lsm6dsx/Kconfig | 3 +- >> drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 4 + >> drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 105 ++++++++++++++++++- >> drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c | 5 + >> drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c | 5 + >> 5 files changed, 117 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig >> index 002a423eae52..0b5a568e4c16 100644 >> --- a/drivers/iio/imu/st_lsm6dsx/Kconfig >> +++ b/drivers/iio/imu/st_lsm6dsx/Kconfig >> @@ -10,7 +10,8 @@ config IIO_ST_LSM6DSX >> help >> Say yes here to build support for STMicroelectronics LSM6DSx imu >> sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm, >> - ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr >> + ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr and the >> + accelerometer/gyroscope of lsm9ds1. >> >> To compile this driver as a module, choose M here: the module >> will be called st_lsm6dsx. >> diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h >> index f072ac14f213..8af9641260fa 100644 >> --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h >> +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h >> @@ -22,6 +22,7 @@ >> #define ST_ASM330LHH_DEV_NAME "asm330lhh" >> #define ST_LSM6DSOX_DEV_NAME "lsm6dsox" >> #define ST_LSM6DSR_DEV_NAME "lsm6dsr" >> +#define ST_LSM9DS1_DEV_NAME "lsm9ds1" >> >> enum st_lsm6dsx_hw_id { >> ST_LSM6DS3_ID, >> @@ -33,6 +34,7 @@ enum st_lsm6dsx_hw_id { >> ST_ASM330LHH_ID, >> ST_LSM6DSOX_ID, >> ST_LSM6DSR_ID, >> + ST_LSM9DS1_ID, >> ST_LSM6DSX_MAX_ID, >> }; >> >> @@ -230,6 +232,8 @@ enum st_lsm6dsx_sensor_id { >> ST_LSM6DSX_ID_EXT0, >> ST_LSM6DSX_ID_EXT1, >> ST_LSM6DSX_ID_EXT2, >> + ST_LSM9DSX_ID_GYRO, >> + ST_LSM9DSX_ID_ACC, >> ST_LSM6DSX_ID_MAX, >> }; >> >> diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c >> index 7a4fe70a8f20..6acfe63073de 100644 >> --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c >> +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c >> @@ -10,6 +10,8 @@ >> * +-125/+-245/+-500/+-1000/+-2000 dps >> * LSM6DSx series has an integrated First-In-First-Out (FIFO) buffer >> * allowing dynamic batching of sensor data. >> + * LSM9DSx series is similar but includes an additional magnetometer, handled >> + * by a different driver. >> * >> * Supported sensors: >> * - LSM6DS3: >> @@ -30,6 +32,13 @@ >> * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 >> * - FIFO size: 3KB >> * >> + * - LSM9DS1: >> + * - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 952 >> + * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 >> + * - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 952 >> + * - Gyroscope supported full-scale [dps]: +-245/+-500/+-2000 >> + * - FIFO size: 32 >> + * >> * Copyright 2016 STMicroelectronics Inc. >> * >> * Lorenzo Bianconi <lorenzo.bianconi@xxxxxx> >> @@ -64,6 +73,10 @@ >> #define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24 >> #define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR 0x26 >> >> +#define ST_LSM9DSX_REG_GYRO_OUT_X_L_ADDR 0x18 >> +#define ST_LSM9DSX_REG_GYRO_OUT_Y_L_ADDR 0x1a >> +#define ST_LSM9DSX_REG_GYRO_OUT_Z_L_ADDR 0x1c >> + >> static const struct st_lsm6dsx_odr_table_entry st_lsm6dsx_odr_table[] = { >> [ST_LSM6DSX_ID_ACC] = { >> .reg = { >> @@ -88,6 +101,30 @@ static const struct st_lsm6dsx_odr_table_entry st_lsm6dsx_odr_table[] = { >> .odr_avl[3] = { 104, 0x04 }, >> .odr_avl[4] = { 208, 0x05 }, >> .odr_avl[5] = { 416, 0x06 }, >> + }, >> + [ST_LSM9DSX_ID_ACC] = { >> + .reg = { >> + .addr = 0x20, >> + .mask = GENMASK(7, 5), >> + }, >> + .odr_avl[0] = { 10, 0x01 }, >> + .odr_avl[1] = { 50, 0x02 }, >> + .odr_avl[2] = { 119, 0x03 }, >> + .odr_avl[3] = { 238, 0x04 }, >> + .odr_avl[4] = { 476, 0x05 }, >> + .odr_avl[5] = { 952, 0x06 }, >> + }, >> + [ST_LSM9DSX_ID_GYRO] = { >> + .reg = { >> + .addr = 0x10, >> + .mask = GENMASK(7, 5), >> + }, >> + .odr_avl[0] = { 15, 0x01 }, >> + .odr_avl[1] = { 60, 0x02 }, >> + .odr_avl[2] = { 119, 0x03 }, >> + .odr_avl[3] = { 238, 0x04 }, >> + .odr_avl[4] = { 476, 0x05 }, >> + .odr_avl[5] = { 952, 0x06 }, >> } >> }; >> >> @@ -111,10 +148,43 @@ static const struct st_lsm6dsx_fs_table_entry st_lsm6dsx_fs_table[] = { >> .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, >> .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, >> .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, >> + }, >> + [ST_LSM9DSX_ID_ACC] = { >> + .reg = { >> + .addr = 0x20, >> + .mask = GENMASK(4, 3), >> + }, >> + .fs_avl[0] = { 599, 0x0 }, >> + .fs_avl[1] = { 1197, 0x2 }, >> + .fs_avl[2] = { 2394, 0x3 }, >> + .fs_avl[3] = { 4788, 0x1 }, >> + }, >> + [ST_LSM9DSX_ID_GYRO] = { >> + .reg = { >> + .addr = 0x10, >> + .mask = GENMASK(4, 3), >> + }, >> + .fs_avl[0] = { IIO_DEGREE_TO_RAD(245), 0x0 }, >> + .fs_avl[1] = { IIO_DEGREE_TO_RAD(500), 0x1 }, >> + .fs_avl[2] = { IIO_DEGREE_TO_RAD(0), 0x2 }, >> + .fs_avl[3] = { IIO_DEGREE_TO_RAD(2000), 0x3 }, >> } >> }; >> >> static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { >> + { >> + .wai = 0x68, >> + .reg_int1_addr = 0x0c, >> + .reg_int2_addr = 0x0d, >> + .reg_reset_addr = 0x22, >> + .max_fifo_size = 32, >> + .id = { >> + { >> + .hw_id = ST_LSM9DS1_ID, >> + .name = ST_LSM9DS1_DEV_NAME, >> + }, >> + }, >> + }, >> { >> .wai = 0x69, >> .reg_int1_addr = 0x0d, >> @@ -492,6 +562,16 @@ static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { >> IIO_CHAN_SOFT_TIMESTAMP(3), >> }; >> >> +static const struct iio_chan_spec st_lsm9dsx_gyro_channels[] = { >> + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM9DSX_REG_GYRO_OUT_X_L_ADDR, >> + IIO_MOD_X, 0), >> + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM9DSX_REG_GYRO_OUT_Y_L_ADDR, >> + IIO_MOD_Y, 1), >> + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM9DSX_REG_GYRO_OUT_Z_L_ADDR, >> + IIO_MOD_Z, 2), >> + IIO_CHAN_SOFT_TIMESTAMP(3), >> +}; >> + >> int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable) >> { >> const struct st_lsm6dsx_shub_settings *hub_settings; >> @@ -1056,6 +1136,7 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, >> >> switch (id) { >> case ST_LSM6DSX_ID_ACC: >> + case ST_LSM9DSX_ID_ACC: >> iio_dev->channels = st_lsm6dsx_acc_channels; >> iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_acc_channels); >> iio_dev->info = &st_lsm6dsx_acc_info; >> @@ -1068,6 +1149,14 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, >> iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_gyro_channels); >> iio_dev->info = &st_lsm6dsx_gyro_info; >> >> + scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro", >> + name); >> + break; >> + case ST_LSM9DSX_ID_GYRO: >> + iio_dev->channels = st_lsm9dsx_gyro_channels; >> + iio_dev->num_channels = ARRAY_SIZE(st_lsm9dsx_gyro_channels); >> + iio_dev->info = &st_lsm6dsx_gyro_info; >> + >> scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro", >> name); >> break; >> @@ -1109,10 +1198,18 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, >> if (err < 0) >> return err; >> >> - for (i = 0; i < ST_LSM6DSX_ID_EXT0; i++) { >> - hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name); >> - if (!hw->iio_devs[i]) >> - return -ENOMEM; >> + if (hw_id == ST_LSM9DS1_ID) { >> + for (i = ST_LSM9DSX_ID_GYRO; i <= ST_LSM9DSX_ID_ACC; i++) { >> + hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name); >> + if (!hw->iio_devs[i]) >> + return -ENOMEM; >> + } >> + } else { >> + for (i = 0; i < ST_LSM6DSX_ID_EXT0; i++) { >> + hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name); >> + if (!hw->iio_devs[i]) >> + return -ENOMEM; >> + } >> } >> >> err = st_lsm6dsx_init_device(hw); >> diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c >> index b3211e0ac07b..a684e7db1299 100644 >> --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c >> +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c >> @@ -75,6 +75,10 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { >> .compatible = "st,lsm6dsr", >> .data = (void *)ST_LSM6DSR_ID, >> }, >> + { >> + .compatible = "st,lsm9ds1", >> + .data = (void *)ST_LSM9DS1_ID, >> + }, >> {}, >> }; >> MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); >> @@ -89,6 +93,7 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { >> { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, >> { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, >> { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, >> + { ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID }, >> {}, >> }; >> MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); >> diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c >> index c9d3c4711018..709769177e91 100644 >> --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c >> +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c >> @@ -75,6 +75,10 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = { >> .compatible = "st,lsm6dsr", >> .data = (void *)ST_LSM6DSR_ID, >> }, >> + { >> + .compatible = "st,lsm9ds1", >> + .data = (void *)ST_LSM9DS1_ID, >> + }, >> {}, >> }; >> MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match); >> @@ -89,6 +93,7 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = { >> { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, >> { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, >> { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, >> + { ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID }, >> {}, >> }; >> MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table); >> -- >> 2.20.1 >>