Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * STMicroelectronics gyroscopes driver
0004  *
0005  * Copyright 2012-2013 STMicroelectronics Inc.
0006  *
0007  * Denis Ciocca <denis.ciocca@st.com>
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/mutex.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/sysfs.h>
0015 #include <linux/iio/iio.h>
0016 #include <linux/iio/sysfs.h>
0017 #include <linux/iio/trigger.h>
0018 
0019 #include <linux/iio/common/st_sensors.h>
0020 #include "st_gyro.h"
0021 
0022 #define ST_GYRO_NUMBER_DATA_CHANNELS        3
0023 
0024 /* DEFAULT VALUE FOR SENSORS */
0025 #define ST_GYRO_DEFAULT_OUT_X_L_ADDR        0x28
0026 #define ST_GYRO_DEFAULT_OUT_Y_L_ADDR        0x2a
0027 #define ST_GYRO_DEFAULT_OUT_Z_L_ADDR        0x2c
0028 
0029 /* FULLSCALE */
0030 #define ST_GYRO_FS_AVL_245DPS           245
0031 #define ST_GYRO_FS_AVL_250DPS           250
0032 #define ST_GYRO_FS_AVL_500DPS           500
0033 #define ST_GYRO_FS_AVL_2000DPS          2000
0034 
0035 static const struct iio_mount_matrix *
0036 st_gyro_get_mount_matrix(const struct iio_dev *indio_dev,
0037              const struct iio_chan_spec *chan)
0038 {
0039     struct st_sensor_data *gdata = iio_priv(indio_dev);
0040 
0041     return &gdata->mount_matrix;
0042 }
0043 
0044 static const struct iio_chan_spec_ext_info st_gyro_mount_matrix_ext_info[] = {
0045     IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_gyro_get_mount_matrix),
0046     { }
0047 };
0048 
0049 static const struct iio_chan_spec st_gyro_16bit_channels[] = {
0050     ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL,
0051             BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
0052             ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
0053             ST_GYRO_DEFAULT_OUT_X_L_ADDR,
0054             st_gyro_mount_matrix_ext_info),
0055     ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL,
0056             BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
0057             ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
0058             ST_GYRO_DEFAULT_OUT_Y_L_ADDR,
0059             st_gyro_mount_matrix_ext_info),
0060     ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL,
0061             BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
0062             ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
0063             ST_GYRO_DEFAULT_OUT_Z_L_ADDR,
0064             st_gyro_mount_matrix_ext_info),
0065     IIO_CHAN_SOFT_TIMESTAMP(3)
0066 };
0067 
0068 static const struct st_sensor_settings st_gyro_sensors_settings[] = {
0069     {
0070         .wai = 0xd3,
0071         .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
0072         .sensors_supported = {
0073             [0] = L3G4200D_GYRO_DEV_NAME,
0074             [1] = LSM330DL_GYRO_DEV_NAME,
0075         },
0076         .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
0077         .odr = {
0078             .addr = 0x20,
0079             .mask = 0xc0,
0080             .odr_avl = {
0081                 { .hz = 100, .value = 0x00, },
0082                 { .hz = 200, .value = 0x01, },
0083                 { .hz = 400, .value = 0x02, },
0084                 { .hz = 800, .value = 0x03, },
0085             },
0086         },
0087         .pw = {
0088             .addr = 0x20,
0089             .mask = 0x08,
0090             .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
0091             .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
0092         },
0093         .enable_axis = {
0094             .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
0095             .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
0096         },
0097         .fs = {
0098             .addr = 0x23,
0099             .mask = 0x30,
0100             .fs_avl = {
0101                 [0] = {
0102                     .num = ST_GYRO_FS_AVL_250DPS,
0103                     .value = 0x00,
0104                     .gain = IIO_DEGREE_TO_RAD(8750),
0105                 },
0106                 [1] = {
0107                     .num = ST_GYRO_FS_AVL_500DPS,
0108                     .value = 0x01,
0109                     .gain = IIO_DEGREE_TO_RAD(17500),
0110                 },
0111                 [2] = {
0112                     .num = ST_GYRO_FS_AVL_2000DPS,
0113                     .value = 0x02,
0114                     .gain = IIO_DEGREE_TO_RAD(70000),
0115                 },
0116             },
0117         },
0118         .bdu = {
0119             .addr = 0x23,
0120             .mask = 0x80,
0121         },
0122         .drdy_irq = {
0123             .int2 = {
0124                 .addr = 0x22,
0125                 .mask = 0x08,
0126             },
0127             /*
0128              * The sensor has IHL (active low) and open
0129              * drain settings, but only for INT1 and not
0130              * for the DRDY line on INT2.
0131              */
0132             .stat_drdy = {
0133                 .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
0134                 .mask = 0x07,
0135             },
0136         },
0137         .sim = {
0138             .addr = 0x23,
0139             .value = BIT(0),
0140         },
0141         .multi_read_bit = true,
0142         .bootime = 2,
0143     },
0144     {
0145         .wai = 0xd4,
0146         .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
0147         .sensors_supported = {
0148             [0] = L3GD20_GYRO_DEV_NAME,
0149             [1] = LSM330D_GYRO_DEV_NAME,
0150             [2] = LSM330DLC_GYRO_DEV_NAME,
0151             [3] = L3G4IS_GYRO_DEV_NAME,
0152             [4] = LSM330_GYRO_DEV_NAME,
0153         },
0154         .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
0155         .odr = {
0156             .addr = 0x20,
0157             .mask = 0xc0,
0158             .odr_avl = {
0159                 { .hz = 95, .value = 0x00, },
0160                 { .hz = 190, .value = 0x01, },
0161                 { .hz = 380, .value = 0x02, },
0162                 { .hz = 760, .value = 0x03, },
0163             },
0164         },
0165         .pw = {
0166             .addr = 0x20,
0167             .mask = 0x08,
0168             .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
0169             .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
0170         },
0171         .enable_axis = {
0172             .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
0173             .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
0174         },
0175         .fs = {
0176             .addr = 0x23,
0177             .mask = 0x30,
0178             .fs_avl = {
0179                 [0] = {
0180                     .num = ST_GYRO_FS_AVL_250DPS,
0181                     .value = 0x00,
0182                     .gain = IIO_DEGREE_TO_RAD(8750),
0183                 },
0184                 [1] = {
0185                     .num = ST_GYRO_FS_AVL_500DPS,
0186                     .value = 0x01,
0187                     .gain = IIO_DEGREE_TO_RAD(17500),
0188                 },
0189                 [2] = {
0190                     .num = ST_GYRO_FS_AVL_2000DPS,
0191                     .value = 0x02,
0192                     .gain = IIO_DEGREE_TO_RAD(70000),
0193                 },
0194             },
0195         },
0196         .bdu = {
0197             .addr = 0x23,
0198             .mask = 0x80,
0199         },
0200         .drdy_irq = {
0201             .int2 = {
0202                 .addr = 0x22,
0203                 .mask = 0x08,
0204             },
0205             /*
0206              * The sensor has IHL (active low) and open
0207              * drain settings, but only for INT1 and not
0208              * for the DRDY line on INT2.
0209              */
0210             .stat_drdy = {
0211                 .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
0212                 .mask = 0x07,
0213             },
0214         },
0215         .sim = {
0216             .addr = 0x23,
0217             .value = BIT(0),
0218         },
0219         .multi_read_bit = true,
0220         .bootime = 2,
0221     },
0222     {
0223         .wai = 0xd4,
0224         .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
0225         .sensors_supported = {
0226             [0] = LSM9DS0_GYRO_DEV_NAME,
0227         },
0228         .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
0229         .odr = {
0230             .addr = 0x20,
0231             .mask = GENMASK(7, 6),
0232             .odr_avl = {
0233                 { .hz = 95, .value = 0x00, },
0234                 { .hz = 190, .value = 0x01, },
0235                 { .hz = 380, .value = 0x02, },
0236                 { .hz = 760, .value = 0x03, },
0237             },
0238         },
0239         .pw = {
0240             .addr = 0x20,
0241             .mask = BIT(3),
0242             .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
0243             .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
0244         },
0245         .enable_axis = {
0246             .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
0247             .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
0248         },
0249         .fs = {
0250             .addr = 0x23,
0251             .mask = GENMASK(5, 4),
0252             .fs_avl = {
0253                 [0] = {
0254                     .num = ST_GYRO_FS_AVL_245DPS,
0255                     .value = 0x00,
0256                     .gain = IIO_DEGREE_TO_RAD(8750),
0257                 },
0258                 [1] = {
0259                     .num = ST_GYRO_FS_AVL_500DPS,
0260                     .value = 0x01,
0261                     .gain = IIO_DEGREE_TO_RAD(17500),
0262                 },
0263                 [2] = {
0264                     .num = ST_GYRO_FS_AVL_2000DPS,
0265                     .value = 0x02,
0266                     .gain = IIO_DEGREE_TO_RAD(70000),
0267                 },
0268             },
0269         },
0270         .bdu = {
0271             .addr = 0x23,
0272             .mask = BIT(7),
0273         },
0274         .drdy_irq = {
0275             .int2 = {
0276                 .addr = 0x22,
0277                 .mask = BIT(3),
0278             },
0279             /*
0280              * The sensor has IHL (active low) and open
0281              * drain settings, but only for INT1 and not
0282              * for the DRDY line on INT2.
0283              */
0284             .stat_drdy = {
0285                 .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
0286                 .mask = GENMASK(2, 0),
0287             },
0288         },
0289         .sim = {
0290             .addr = 0x23,
0291             .value = BIT(0),
0292         },
0293         .multi_read_bit = true,
0294         .bootime = 2,
0295     },
0296     {
0297         .wai = 0xd7,
0298         .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
0299         .sensors_supported = {
0300             [0] = L3GD20H_GYRO_DEV_NAME,
0301         },
0302         .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
0303         .odr = {
0304             .addr = 0x20,
0305             .mask = 0xc0,
0306             .odr_avl = {
0307                 { .hz = 100, .value = 0x00, },
0308                 { .hz = 200, .value = 0x01, },
0309                 { .hz = 400, .value = 0x02, },
0310                 { .hz = 800, .value = 0x03, },
0311             },
0312         },
0313         .pw = {
0314             .addr = 0x20,
0315             .mask = 0x08,
0316             .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
0317             .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
0318         },
0319         .enable_axis = {
0320             .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
0321             .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
0322         },
0323         .fs = {
0324             .addr = 0x23,
0325             .mask = 0x30,
0326             .fs_avl = {
0327                 [0] = {
0328                     .num = ST_GYRO_FS_AVL_245DPS,
0329                     .value = 0x00,
0330                     .gain = IIO_DEGREE_TO_RAD(8750),
0331                 },
0332                 [1] = {
0333                     .num = ST_GYRO_FS_AVL_500DPS,
0334                     .value = 0x01,
0335                     .gain = IIO_DEGREE_TO_RAD(17500),
0336                 },
0337                 [2] = {
0338                     .num = ST_GYRO_FS_AVL_2000DPS,
0339                     .value = 0x02,
0340                     .gain = IIO_DEGREE_TO_RAD(70000),
0341                 },
0342             },
0343         },
0344         .bdu = {
0345             .addr = 0x23,
0346             .mask = 0x80,
0347         },
0348         .drdy_irq = {
0349             .int2 = {
0350                 .addr = 0x22,
0351                 .mask = 0x08,
0352             },
0353             /*
0354              * The sensor has IHL (active low) and open
0355              * drain settings, but only for INT1 and not
0356              * for the DRDY line on INT2.
0357              */
0358             .stat_drdy = {
0359                 .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
0360                 .mask = 0x07,
0361             },
0362         },
0363         .sim = {
0364             .addr = 0x23,
0365             .value = BIT(0),
0366         },
0367         .multi_read_bit = true,
0368         .bootime = 2,
0369     },
0370 };
0371 
0372 /* DRDY on gyros is available only on INT2 pin */
0373 static const struct st_sensors_platform_data gyro_pdata = {
0374     .drdy_int_pin = 2,
0375 };
0376 
0377 static int st_gyro_read_raw(struct iio_dev *indio_dev,
0378             struct iio_chan_spec const *ch, int *val,
0379                             int *val2, long mask)
0380 {
0381     int err;
0382     struct st_sensor_data *gdata = iio_priv(indio_dev);
0383 
0384     switch (mask) {
0385     case IIO_CHAN_INFO_RAW:
0386         err = st_sensors_read_info_raw(indio_dev, ch, val);
0387         if (err < 0)
0388             goto read_error;
0389 
0390         return IIO_VAL_INT;
0391     case IIO_CHAN_INFO_SCALE:
0392         *val = 0;
0393         *val2 = gdata->current_fullscale->gain;
0394         return IIO_VAL_INT_PLUS_MICRO;
0395     case IIO_CHAN_INFO_SAMP_FREQ:
0396         *val = gdata->odr;
0397         return IIO_VAL_INT;
0398     default:
0399         return -EINVAL;
0400     }
0401 
0402 read_error:
0403     return err;
0404 }
0405 
0406 static int st_gyro_write_raw(struct iio_dev *indio_dev,
0407         struct iio_chan_spec const *chan, int val, int val2, long mask)
0408 {
0409     switch (mask) {
0410     case IIO_CHAN_INFO_SCALE:
0411         return st_sensors_set_fullscale_by_gain(indio_dev, val2);
0412     case IIO_CHAN_INFO_SAMP_FREQ:
0413         if (val2)
0414             return -EINVAL;
0415 
0416         return st_sensors_set_odr(indio_dev, val);
0417     default:
0418         return -EINVAL;
0419     }
0420 }
0421 
0422 static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
0423 static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
0424 
0425 static struct attribute *st_gyro_attributes[] = {
0426     &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
0427     &iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
0428     NULL,
0429 };
0430 
0431 static const struct attribute_group st_gyro_attribute_group = {
0432     .attrs = st_gyro_attributes,
0433 };
0434 
0435 static const struct iio_info gyro_info = {
0436     .attrs = &st_gyro_attribute_group,
0437     .read_raw = &st_gyro_read_raw,
0438     .write_raw = &st_gyro_write_raw,
0439     .debugfs_reg_access = &st_sensors_debugfs_reg_access,
0440 };
0441 
0442 #ifdef CONFIG_IIO_TRIGGER
0443 static const struct iio_trigger_ops st_gyro_trigger_ops = {
0444     .set_trigger_state = ST_GYRO_TRIGGER_SET_STATE,
0445     .validate_device = st_sensors_validate_device,
0446 };
0447 #define ST_GYRO_TRIGGER_OPS (&st_gyro_trigger_ops)
0448 #else
0449 #define ST_GYRO_TRIGGER_OPS NULL
0450 #endif
0451 
0452 /*
0453  * st_gyro_get_settings() - get sensor settings from device name
0454  * @name: device name buffer reference.
0455  *
0456  * Return: valid reference on success, NULL otherwise.
0457  */
0458 const struct st_sensor_settings *st_gyro_get_settings(const char *name)
0459 {
0460     int index = st_sensors_get_settings_index(name,
0461                     st_gyro_sensors_settings,
0462                     ARRAY_SIZE(st_gyro_sensors_settings));
0463     if (index < 0)
0464         return NULL;
0465 
0466     return &st_gyro_sensors_settings[index];
0467 }
0468 EXPORT_SYMBOL_NS(st_gyro_get_settings, IIO_ST_SENSORS);
0469 
0470 int st_gyro_common_probe(struct iio_dev *indio_dev)
0471 {
0472     struct st_sensor_data *gdata = iio_priv(indio_dev);
0473     struct st_sensors_platform_data *pdata;
0474     struct device *parent = indio_dev->dev.parent;
0475     int err;
0476 
0477     indio_dev->modes = INDIO_DIRECT_MODE;
0478     indio_dev->info = &gyro_info;
0479 
0480     err = st_sensors_verify_id(indio_dev);
0481     if (err < 0)
0482         return err;
0483 
0484     gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS;
0485     indio_dev->channels = gdata->sensor_settings->ch;
0486     indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
0487 
0488     err = iio_read_mount_matrix(parent, &gdata->mount_matrix);
0489     if (err)
0490         return err;
0491 
0492     gdata->current_fullscale = &gdata->sensor_settings->fs.fs_avl[0];
0493     gdata->odr = gdata->sensor_settings->odr.odr_avl[0].hz;
0494 
0495     pdata = (struct st_sensors_platform_data *)&gyro_pdata;
0496 
0497     err = st_sensors_init_sensor(indio_dev, pdata);
0498     if (err < 0)
0499         return err;
0500 
0501     err = st_gyro_allocate_ring(indio_dev);
0502     if (err < 0)
0503         return err;
0504 
0505     if (gdata->irq > 0) {
0506         err = st_sensors_allocate_trigger(indio_dev,
0507                           ST_GYRO_TRIGGER_OPS);
0508         if (err < 0)
0509             return err;
0510     }
0511 
0512     return devm_iio_device_register(parent, indio_dev);
0513 }
0514 EXPORT_SYMBOL_NS(st_gyro_common_probe, IIO_ST_SENSORS);
0515 
0516 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
0517 MODULE_DESCRIPTION("STMicroelectronics gyroscopes driver");
0518 MODULE_LICENSE("GPL v2");
0519 MODULE_IMPORT_NS(IIO_ST_SENSORS);