linux/drivers/iio/gyro/st_gyro_core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * STMicroelectronics gyroscopes driver
   4 *
   5 * Copyright 2012-2013 STMicroelectronics Inc.
   6 *
   7 * Denis Ciocca <denis.ciocca@st.com>
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/mutex.h>
  13#include <linux/interrupt.h>
  14#include <linux/sysfs.h>
  15#include <linux/iio/iio.h>
  16#include <linux/iio/sysfs.h>
  17#include <linux/iio/trigger.h>
  18
  19#include <linux/iio/common/st_sensors.h>
  20#include "st_gyro.h"
  21
  22#define ST_GYRO_NUMBER_DATA_CHANNELS            3
  23
  24/* DEFAULT VALUE FOR SENSORS */
  25#define ST_GYRO_DEFAULT_OUT_X_L_ADDR            0x28
  26#define ST_GYRO_DEFAULT_OUT_Y_L_ADDR            0x2a
  27#define ST_GYRO_DEFAULT_OUT_Z_L_ADDR            0x2c
  28
  29/* FULLSCALE */
  30#define ST_GYRO_FS_AVL_245DPS                   245
  31#define ST_GYRO_FS_AVL_250DPS                   250
  32#define ST_GYRO_FS_AVL_500DPS                   500
  33#define ST_GYRO_FS_AVL_2000DPS                  2000
  34
  35static const struct iio_mount_matrix *
  36st_gyro_get_mount_matrix(const struct iio_dev *indio_dev,
  37                         const struct iio_chan_spec *chan)
  38{
  39        struct st_sensor_data *gdata = iio_priv(indio_dev);
  40
  41        return &gdata->mount_matrix;
  42}
  43
  44static const struct iio_chan_spec_ext_info st_gyro_mount_matrix_ext_info[] = {
  45        IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_gyro_get_mount_matrix),
  46        { }
  47};
  48
  49static const struct iio_chan_spec st_gyro_16bit_channels[] = {
  50        ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL,
  51                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  52                        ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
  53                        ST_GYRO_DEFAULT_OUT_X_L_ADDR,
  54                        st_gyro_mount_matrix_ext_info),
  55        ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL,
  56                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  57                        ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
  58                        ST_GYRO_DEFAULT_OUT_Y_L_ADDR,
  59                        st_gyro_mount_matrix_ext_info),
  60        ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL,
  61                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  62                        ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
  63                        ST_GYRO_DEFAULT_OUT_Z_L_ADDR,
  64                        st_gyro_mount_matrix_ext_info),
  65        IIO_CHAN_SOFT_TIMESTAMP(3)
  66};
  67
  68static const struct st_sensor_settings st_gyro_sensors_settings[] = {
  69        {
  70                .wai = 0xd3,
  71                .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
  72                .sensors_supported = {
  73                        [0] = L3G4200D_GYRO_DEV_NAME,
  74                        [1] = LSM330DL_GYRO_DEV_NAME,
  75                },
  76                .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
  77                .odr = {
  78                        .addr = 0x20,
  79                        .mask = 0xc0,
  80                        .odr_avl = {
  81                                { .hz = 100, .value = 0x00, },
  82                                { .hz = 200, .value = 0x01, },
  83                                { .hz = 400, .value = 0x02, },
  84                                { .hz = 800, .value = 0x03, },
  85                        },
  86                },
  87                .pw = {
  88                        .addr = 0x20,
  89                        .mask = 0x08,
  90                        .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
  91                        .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
  92                },
  93                .enable_axis = {
  94                        .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
  95                        .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
  96                },
  97                .fs = {
  98                        .addr = 0x23,
  99                        .mask = 0x30,
 100                        .fs_avl = {
 101                                [0] = {
 102                                        .num = ST_GYRO_FS_AVL_250DPS,
 103                                        .value = 0x00,
 104                                        .gain = IIO_DEGREE_TO_RAD(8750),
 105                                },
 106                                [1] = {
 107                                        .num = ST_GYRO_FS_AVL_500DPS,
 108                                        .value = 0x01,
 109                                        .gain = IIO_DEGREE_TO_RAD(17500),
 110                                },
 111                                [2] = {
 112                                        .num = ST_GYRO_FS_AVL_2000DPS,
 113                                        .value = 0x02,
 114                                        .gain = IIO_DEGREE_TO_RAD(70000),
 115                                },
 116                        },
 117                },
 118                .bdu = {
 119                        .addr = 0x23,
 120                        .mask = 0x80,
 121                },
 122                .drdy_irq = {
 123                        .int2 = {
 124                                .addr = 0x22,
 125                                .mask = 0x08,
 126                        },
 127                        /*
 128                         * The sensor has IHL (active low) and open
 129                         * drain settings, but only for INT1 and not
 130                         * for the DRDY line on INT2.
 131                         */
 132                        .stat_drdy = {
 133                                .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
 134                                .mask = 0x07,
 135                        },
 136                },
 137                .sim = {
 138                        .addr = 0x23,
 139                        .value = BIT(0),
 140                },
 141                .multi_read_bit = true,
 142                .bootime = 2,
 143        },
 144        {
 145                .wai = 0xd4,
 146                .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 147                .sensors_supported = {
 148                        [0] = L3GD20_GYRO_DEV_NAME,
 149                        [1] = LSM330D_GYRO_DEV_NAME,
 150                        [2] = LSM330DLC_GYRO_DEV_NAME,
 151                        [3] = L3G4IS_GYRO_DEV_NAME,
 152                        [4] = LSM330_GYRO_DEV_NAME,
 153                },
 154                .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
 155                .odr = {
 156                        .addr = 0x20,
 157                        .mask = 0xc0,
 158                        .odr_avl = {
 159                                { .hz = 95, .value = 0x00, },
 160                                { .hz = 190, .value = 0x01, },
 161                                { .hz = 380, .value = 0x02, },
 162                                { .hz = 760, .value = 0x03, },
 163                        },
 164                },
 165                .pw = {
 166                        .addr = 0x20,
 167                        .mask = 0x08,
 168                        .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 169                        .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 170                },
 171                .enable_axis = {
 172                        .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
 173                        .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 174                },
 175                .fs = {
 176                        .addr = 0x23,
 177                        .mask = 0x30,
 178                        .fs_avl = {
 179                                [0] = {
 180                                        .num = ST_GYRO_FS_AVL_250DPS,
 181                                        .value = 0x00,
 182                                        .gain = IIO_DEGREE_TO_RAD(8750),
 183                                },
 184                                [1] = {
 185                                        .num = ST_GYRO_FS_AVL_500DPS,
 186                                        .value = 0x01,
 187                                        .gain = IIO_DEGREE_TO_RAD(17500),
 188                                },
 189                                [2] = {
 190                                        .num = ST_GYRO_FS_AVL_2000DPS,
 191                                        .value = 0x02,
 192                                        .gain = IIO_DEGREE_TO_RAD(70000),
 193                                },
 194                        },
 195                },
 196                .bdu = {
 197                        .addr = 0x23,
 198                        .mask = 0x80,
 199                },
 200                .drdy_irq = {
 201                        .int2 = {
 202                                .addr = 0x22,
 203                                .mask = 0x08,
 204                        },
 205                        /*
 206                         * The sensor has IHL (active low) and open
 207                         * drain settings, but only for INT1 and not
 208                         * for the DRDY line on INT2.
 209                         */
 210                        .stat_drdy = {
 211                                .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
 212                                .mask = 0x07,
 213                        },
 214                },
 215                .sim = {
 216                        .addr = 0x23,
 217                        .value = BIT(0),
 218                },
 219                .multi_read_bit = true,
 220                .bootime = 2,
 221        },
 222        {
 223                .wai = 0xd4,
 224                .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 225                .sensors_supported = {
 226                        [0] = LSM9DS0_GYRO_DEV_NAME,
 227                },
 228                .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
 229                .odr = {
 230                        .addr = 0x20,
 231                        .mask = GENMASK(7, 6),
 232                        .odr_avl = {
 233                                { .hz = 95, .value = 0x00, },
 234                                { .hz = 190, .value = 0x01, },
 235                                { .hz = 380, .value = 0x02, },
 236                                { .hz = 760, .value = 0x03, },
 237                        },
 238                },
 239                .pw = {
 240                        .addr = 0x20,
 241                        .mask = BIT(3),
 242                        .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 243                        .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 244                },
 245                .enable_axis = {
 246                        .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
 247                        .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 248                },
 249                .fs = {
 250                        .addr = 0x23,
 251                        .mask = GENMASK(5, 4),
 252                        .fs_avl = {
 253                                [0] = {
 254                                        .num = ST_GYRO_FS_AVL_245DPS,
 255                                        .value = 0x00,
 256                                        .gain = IIO_DEGREE_TO_RAD(8750),
 257                                },
 258                                [1] = {
 259                                        .num = ST_GYRO_FS_AVL_500DPS,
 260                                        .value = 0x01,
 261                                        .gain = IIO_DEGREE_TO_RAD(17500),
 262                                },
 263                                [2] = {
 264                                        .num = ST_GYRO_FS_AVL_2000DPS,
 265                                        .value = 0x02,
 266                                        .gain = IIO_DEGREE_TO_RAD(70000),
 267                                },
 268                        },
 269                },
 270                .bdu = {
 271                        .addr = 0x23,
 272                        .mask = BIT(7),
 273                },
 274                .drdy_irq = {
 275                        .int2 = {
 276                                .addr = 0x22,
 277                                .mask = BIT(3),
 278                        },
 279                        /*
 280                         * The sensor has IHL (active low) and open
 281                         * drain settings, but only for INT1 and not
 282                         * for the DRDY line on INT2.
 283                         */
 284                        .stat_drdy = {
 285                                .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
 286                                .mask = GENMASK(2, 0),
 287                        },
 288                },
 289                .sim = {
 290                        .addr = 0x23,
 291                        .value = BIT(0),
 292                },
 293                .multi_read_bit = true,
 294                .bootime = 2,
 295        },
 296        {
 297                .wai = 0xd7,
 298                .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 299                .sensors_supported = {
 300                        [0] = L3GD20H_GYRO_DEV_NAME,
 301                },
 302                .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
 303                .odr = {
 304                        .addr = 0x20,
 305                        .mask = 0xc0,
 306                        .odr_avl = {
 307                                { .hz = 100, .value = 0x00, },
 308                                { .hz = 200, .value = 0x01, },
 309                                { .hz = 400, .value = 0x02, },
 310                                { .hz = 800, .value = 0x03, },
 311                        },
 312                },
 313                .pw = {
 314                        .addr = 0x20,
 315                        .mask = 0x08,
 316                        .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 317                        .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 318                },
 319                .enable_axis = {
 320                        .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
 321                        .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 322                },
 323                .fs = {
 324                        .addr = 0x23,
 325                        .mask = 0x30,
 326                        .fs_avl = {
 327                                [0] = {
 328                                        .num = ST_GYRO_FS_AVL_245DPS,
 329                                        .value = 0x00,
 330                                        .gain = IIO_DEGREE_TO_RAD(8750),
 331                                },
 332                                [1] = {
 333                                        .num = ST_GYRO_FS_AVL_500DPS,
 334                                        .value = 0x01,
 335                                        .gain = IIO_DEGREE_TO_RAD(17500),
 336                                },
 337                                [2] = {
 338                                        .num = ST_GYRO_FS_AVL_2000DPS,
 339                                        .value = 0x02,
 340                                        .gain = IIO_DEGREE_TO_RAD(70000),
 341                                },
 342                        },
 343                },
 344                .bdu = {
 345                        .addr = 0x23,
 346                        .mask = 0x80,
 347                },
 348                .drdy_irq = {
 349                        .int2 = {
 350                                .addr = 0x22,
 351                                .mask = 0x08,
 352                        },
 353                        /*
 354                         * The sensor has IHL (active low) and open
 355                         * drain settings, but only for INT1 and not
 356                         * for the DRDY line on INT2.
 357                         */
 358                        .stat_drdy = {
 359                                .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
 360                                .mask = 0x07,
 361                        },
 362                },
 363                .sim = {
 364                        .addr = 0x23,
 365                        .value = BIT(0),
 366                },
 367                .multi_read_bit = true,
 368                .bootime = 2,
 369        },
 370};
 371
 372/* DRDY on gyros is available only on INT2 pin */
 373static const struct st_sensors_platform_data gyro_pdata = {
 374        .drdy_int_pin = 2,
 375};
 376
 377static int st_gyro_read_raw(struct iio_dev *indio_dev,
 378                        struct iio_chan_spec const *ch, int *val,
 379                                                        int *val2, long mask)
 380{
 381        int err;
 382        struct st_sensor_data *gdata = iio_priv(indio_dev);
 383
 384        switch (mask) {
 385        case IIO_CHAN_INFO_RAW:
 386                err = st_sensors_read_info_raw(indio_dev, ch, val);
 387                if (err < 0)
 388                        goto read_error;
 389
 390                return IIO_VAL_INT;
 391        case IIO_CHAN_INFO_SCALE:
 392                *val = 0;
 393                *val2 = gdata->current_fullscale->gain;
 394                return IIO_VAL_INT_PLUS_MICRO;
 395        case IIO_CHAN_INFO_SAMP_FREQ:
 396                *val = gdata->odr;
 397                return IIO_VAL_INT;
 398        default:
 399                return -EINVAL;
 400        }
 401
 402read_error:
 403        return err;
 404}
 405
 406static int st_gyro_write_raw(struct iio_dev *indio_dev,
 407                struct iio_chan_spec const *chan, int val, int val2, long mask)
 408{
 409        int err;
 410
 411        switch (mask) {
 412        case IIO_CHAN_INFO_SCALE:
 413                err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
 414                break;
 415        case IIO_CHAN_INFO_SAMP_FREQ:
 416                if (val2)
 417                        return -EINVAL;
 418                mutex_lock(&indio_dev->mlock);
 419                err = st_sensors_set_odr(indio_dev, val);
 420                mutex_unlock(&indio_dev->mlock);
 421                return err;
 422        default:
 423                err = -EINVAL;
 424        }
 425
 426        return err;
 427}
 428
 429static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
 430static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
 431
 432static struct attribute *st_gyro_attributes[] = {
 433        &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
 434        &iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
 435        NULL,
 436};
 437
 438static const struct attribute_group st_gyro_attribute_group = {
 439        .attrs = st_gyro_attributes,
 440};
 441
 442static const struct iio_info gyro_info = {
 443        .attrs = &st_gyro_attribute_group,
 444        .read_raw = &st_gyro_read_raw,
 445        .write_raw = &st_gyro_write_raw,
 446        .debugfs_reg_access = &st_sensors_debugfs_reg_access,
 447};
 448
 449#ifdef CONFIG_IIO_TRIGGER
 450static const struct iio_trigger_ops st_gyro_trigger_ops = {
 451        .set_trigger_state = ST_GYRO_TRIGGER_SET_STATE,
 452        .validate_device = st_sensors_validate_device,
 453};
 454#define ST_GYRO_TRIGGER_OPS (&st_gyro_trigger_ops)
 455#else
 456#define ST_GYRO_TRIGGER_OPS NULL
 457#endif
 458
 459/*
 460 * st_gyro_get_settings() - get sensor settings from device name
 461 * @name: device name buffer reference.
 462 *
 463 * Return: valid reference on success, NULL otherwise.
 464 */
 465const struct st_sensor_settings *st_gyro_get_settings(const char *name)
 466{
 467        int index = st_sensors_get_settings_index(name,
 468                                        st_gyro_sensors_settings,
 469                                        ARRAY_SIZE(st_gyro_sensors_settings));
 470        if (index < 0)
 471                return NULL;
 472
 473        return &st_gyro_sensors_settings[index];
 474}
 475EXPORT_SYMBOL(st_gyro_get_settings);
 476
 477int st_gyro_common_probe(struct iio_dev *indio_dev)
 478{
 479        struct st_sensor_data *gdata = iio_priv(indio_dev);
 480        struct st_sensors_platform_data *pdata;
 481        int err;
 482
 483        indio_dev->modes = INDIO_DIRECT_MODE;
 484        indio_dev->info = &gyro_info;
 485
 486        err = st_sensors_verify_id(indio_dev);
 487        if (err < 0)
 488                return err;
 489
 490        gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS;
 491        indio_dev->channels = gdata->sensor_settings->ch;
 492        indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
 493
 494        err = iio_read_mount_matrix(gdata->dev, &gdata->mount_matrix);
 495        if (err)
 496                return err;
 497
 498        gdata->current_fullscale = &gdata->sensor_settings->fs.fs_avl[0];
 499        gdata->odr = gdata->sensor_settings->odr.odr_avl[0].hz;
 500
 501        pdata = (struct st_sensors_platform_data *)&gyro_pdata;
 502
 503        err = st_sensors_init_sensor(indio_dev, pdata);
 504        if (err < 0)
 505                return err;
 506
 507        err = st_gyro_allocate_ring(indio_dev);
 508        if (err < 0)
 509                return err;
 510
 511        if (gdata->irq > 0) {
 512                err = st_sensors_allocate_trigger(indio_dev,
 513                                                  ST_GYRO_TRIGGER_OPS);
 514                if (err < 0)
 515                        return err;
 516        }
 517
 518        err = iio_device_register(indio_dev);
 519        if (err)
 520                goto st_gyro_device_register_error;
 521
 522        dev_info(&indio_dev->dev, "registered gyroscope %s\n",
 523                 indio_dev->name);
 524
 525        return 0;
 526
 527st_gyro_device_register_error:
 528        if (gdata->irq > 0)
 529                st_sensors_deallocate_trigger(indio_dev);
 530        return err;
 531}
 532EXPORT_SYMBOL(st_gyro_common_probe);
 533
 534void st_gyro_common_remove(struct iio_dev *indio_dev)
 535{
 536        struct st_sensor_data *gdata = iio_priv(indio_dev);
 537
 538        iio_device_unregister(indio_dev);
 539        if (gdata->irq > 0)
 540                st_sensors_deallocate_trigger(indio_dev);
 541}
 542EXPORT_SYMBOL(st_gyro_common_remove);
 543
 544MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
 545MODULE_DESCRIPTION("STMicroelectronics gyroscopes driver");
 546MODULE_LICENSE("GPL v2");
 547