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