linux/drivers/iio/gyro/adis16260.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * ADIS16260/ADIS16265 Programmable Digital Gyroscope Sensor Driver
   4 *
   5 * Copyright 2010 Analog Devices Inc.
   6 */
   7
   8#include <linux/interrupt.h>
   9#include <linux/mutex.h>
  10#include <linux/device.h>
  11#include <linux/kernel.h>
  12#include <linux/spi/spi.h>
  13#include <linux/sysfs.h>
  14#include <linux/module.h>
  15
  16#include <linux/iio/iio.h>
  17#include <linux/iio/sysfs.h>
  18#include <linux/iio/buffer.h>
  19#include <linux/iio/imu/adis.h>
  20
  21#define ADIS16260_STARTUP_DELAY 220 /* ms */
  22
  23#define ADIS16260_FLASH_CNT  0x00 /* Flash memory write count */
  24#define ADIS16260_SUPPLY_OUT 0x02 /* Power supply measurement */
  25#define ADIS16260_GYRO_OUT   0x04 /* X-axis gyroscope output */
  26#define ADIS16260_AUX_ADC    0x0A /* analog input channel measurement */
  27#define ADIS16260_TEMP_OUT   0x0C /* internal temperature measurement */
  28#define ADIS16260_ANGL_OUT   0x0E /* angle displacement */
  29#define ADIS16260_GYRO_OFF   0x14 /* Calibration, offset/bias adjustment */
  30#define ADIS16260_GYRO_SCALE 0x16 /* Calibration, scale adjustment */
  31#define ADIS16260_ALM_MAG1   0x20 /* Alarm 1 magnitude/polarity setting */
  32#define ADIS16260_ALM_MAG2   0x22 /* Alarm 2 magnitude/polarity setting */
  33#define ADIS16260_ALM_SMPL1  0x24 /* Alarm 1 dynamic rate of change setting */
  34#define ADIS16260_ALM_SMPL2  0x26 /* Alarm 2 dynamic rate of change setting */
  35#define ADIS16260_ALM_CTRL   0x28 /* Alarm control */
  36#define ADIS16260_AUX_DAC    0x30 /* Auxiliary DAC data */
  37#define ADIS16260_GPIO_CTRL  0x32 /* Control, digital I/O line */
  38#define ADIS16260_MSC_CTRL   0x34 /* Control, data ready, self-test settings */
  39#define ADIS16260_SMPL_PRD   0x36 /* Control, internal sample rate */
  40#define ADIS16260_SENS_AVG   0x38 /* Control, dynamic range, filtering */
  41#define ADIS16260_SLP_CNT    0x3A /* Control, sleep mode initiation */
  42#define ADIS16260_DIAG_STAT  0x3C /* Diagnostic, error flags */
  43#define ADIS16260_GLOB_CMD   0x3E /* Control, global commands */
  44#define ADIS16260_LOT_ID1    0x52 /* Lot Identification Code 1 */
  45#define ADIS16260_LOT_ID2    0x54 /* Lot Identification Code 2 */
  46#define ADIS16260_PROD_ID    0x56 /* Product identifier;
  47                                   * convert to decimal = 16,265/16,260 */
  48#define ADIS16260_SERIAL_NUM 0x58 /* Serial number */
  49
  50#define ADIS16260_ERROR_ACTIVE                  (1<<14)
  51#define ADIS16260_NEW_DATA                      (1<<15)
  52
  53/* MSC_CTRL */
  54#define ADIS16260_MSC_CTRL_MEM_TEST             (1<<11)
  55/* Internal self-test enable */
  56#define ADIS16260_MSC_CTRL_INT_SELF_TEST        (1<<10)
  57#define ADIS16260_MSC_CTRL_NEG_SELF_TEST        (1<<9)
  58#define ADIS16260_MSC_CTRL_POS_SELF_TEST        (1<<8)
  59#define ADIS16260_MSC_CTRL_DATA_RDY_EN          (1<<2)
  60#define ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH    (1<<1)
  61#define ADIS16260_MSC_CTRL_DATA_RDY_DIO2        (1<<0)
  62
  63/* SMPL_PRD */
  64/* Time base (tB): 0 = 1.953 ms, 1 = 60.54 ms */
  65#define ADIS16260_SMPL_PRD_TIME_BASE    (1<<7)
  66#define ADIS16260_SMPL_PRD_DIV_MASK     0x7F
  67
  68/* SLP_CNT */
  69#define ADIS16260_SLP_CNT_POWER_OFF     0x80
  70
  71/* DIAG_STAT */
  72#define ADIS16260_DIAG_STAT_ALARM2      (1<<9)
  73#define ADIS16260_DIAG_STAT_ALARM1      (1<<8)
  74#define ADIS16260_DIAG_STAT_FLASH_CHK_BIT       6
  75#define ADIS16260_DIAG_STAT_SELF_TEST_BIT       5
  76#define ADIS16260_DIAG_STAT_OVERFLOW_BIT        4
  77#define ADIS16260_DIAG_STAT_SPI_FAIL_BIT        3
  78#define ADIS16260_DIAG_STAT_FLASH_UPT_BIT       2
  79#define ADIS16260_DIAG_STAT_POWER_HIGH_BIT      1
  80#define ADIS16260_DIAG_STAT_POWER_LOW_BIT       0
  81
  82/* GLOB_CMD */
  83#define ADIS16260_GLOB_CMD_SW_RESET     (1<<7)
  84#define ADIS16260_GLOB_CMD_FLASH_UPD    (1<<3)
  85#define ADIS16260_GLOB_CMD_DAC_LATCH    (1<<2)
  86#define ADIS16260_GLOB_CMD_FAC_CALIB    (1<<1)
  87#define ADIS16260_GLOB_CMD_AUTO_NULL    (1<<0)
  88
  89#define ADIS16260_SPI_SLOW      (u32)(300 * 1000)
  90#define ADIS16260_SPI_BURST     (u32)(1000 * 1000)
  91#define ADIS16260_SPI_FAST      (u32)(2000 * 1000)
  92
  93/* At the moment triggers are only used for ring buffer
  94 * filling. This may change!
  95 */
  96
  97#define ADIS16260_SCAN_GYRO     0
  98#define ADIS16260_SCAN_SUPPLY   1
  99#define ADIS16260_SCAN_AUX_ADC  2
 100#define ADIS16260_SCAN_TEMP     3
 101#define ADIS16260_SCAN_ANGL     4
 102
 103struct adis16260_chip_info {
 104        unsigned int gyro_max_val;
 105        unsigned int gyro_max_scale;
 106        const struct iio_chan_spec *channels;
 107        unsigned int num_channels;
 108};
 109
 110struct adis16260 {
 111        const struct adis16260_chip_info *info;
 112
 113        struct adis adis;
 114};
 115
 116enum adis16260_type {
 117        ADIS16251,
 118        ADIS16260,
 119        ADIS16266,
 120};
 121
 122static const struct iio_chan_spec adis16260_channels[] = {
 123        ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
 124                BIT(IIO_CHAN_INFO_CALIBBIAS) |
 125                BIT(IIO_CHAN_INFO_CALIBSCALE),
 126                BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
 127        ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0,
 128                BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
 129        ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
 130                BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
 131        ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
 132                BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
 133        ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
 134                BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
 135        IIO_CHAN_SOFT_TIMESTAMP(5),
 136};
 137
 138static const struct iio_chan_spec adis16266_channels[] = {
 139        ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
 140                BIT(IIO_CHAN_INFO_CALIBBIAS) |
 141                BIT(IIO_CHAN_INFO_CALIBSCALE),
 142                BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
 143        ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
 144                BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
 145        ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
 146                BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
 147        ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
 148                BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
 149        IIO_CHAN_SOFT_TIMESTAMP(4),
 150};
 151
 152static const struct adis16260_chip_info adis16260_chip_info_table[] = {
 153        [ADIS16251] = {
 154                .gyro_max_scale = 80,
 155                .gyro_max_val = IIO_RAD_TO_DEGREE(4368),
 156                .channels = adis16260_channels,
 157                .num_channels = ARRAY_SIZE(adis16260_channels),
 158        },
 159        [ADIS16260] = {
 160                .gyro_max_scale = 320,
 161                .gyro_max_val = IIO_RAD_TO_DEGREE(4368),
 162                .channels = adis16260_channels,
 163                .num_channels = ARRAY_SIZE(adis16260_channels),
 164        },
 165        [ADIS16266] = {
 166                .gyro_max_scale = 14000,
 167                .gyro_max_val = IIO_RAD_TO_DEGREE(3357),
 168                .channels = adis16266_channels,
 169                .num_channels = ARRAY_SIZE(adis16266_channels),
 170        },
 171};
 172
 173/* Power down the device */
 174static int adis16260_stop_device(struct iio_dev *indio_dev)
 175{
 176        struct adis16260 *adis16260 = iio_priv(indio_dev);
 177        int ret;
 178        u16 val = ADIS16260_SLP_CNT_POWER_OFF;
 179
 180        ret = adis_write_reg_16(&adis16260->adis, ADIS16260_SLP_CNT, val);
 181        if (ret)
 182                dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
 183
 184        return ret;
 185}
 186
 187static const u8 adis16260_addresses[][2] = {
 188        [ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
 189};
 190
 191static int adis16260_read_raw(struct iio_dev *indio_dev,
 192                              struct iio_chan_spec const *chan,
 193                              int *val, int *val2,
 194                              long mask)
 195{
 196        struct adis16260 *adis16260 = iio_priv(indio_dev);
 197        const struct adis16260_chip_info *info = adis16260->info;
 198        struct adis *adis = &adis16260->adis;
 199        int ret;
 200        u8 addr;
 201        s16 val16;
 202
 203        switch (mask) {
 204        case IIO_CHAN_INFO_RAW:
 205                return adis_single_conversion(indio_dev, chan,
 206                                ADIS16260_ERROR_ACTIVE, val);
 207        case IIO_CHAN_INFO_SCALE:
 208                switch (chan->type) {
 209                case IIO_ANGL_VEL:
 210                        *val = info->gyro_max_scale;
 211                        *val2 = info->gyro_max_val;
 212                        return IIO_VAL_FRACTIONAL;
 213                case IIO_INCLI:
 214                        *val = 0;
 215                        *val2 = IIO_DEGREE_TO_RAD(36630);
 216                        return IIO_VAL_INT_PLUS_MICRO;
 217                case IIO_VOLTAGE:
 218                        if (chan->channel == 0) {
 219                                *val = 1;
 220                                *val2 = 831500; /* 1.8315 mV */
 221                        } else {
 222                                *val = 0;
 223                                *val2 = 610500; /* 610.5 uV */
 224                        }
 225                        return IIO_VAL_INT_PLUS_MICRO;
 226                case IIO_TEMP:
 227                        *val = 145;
 228                        *val2 = 300000; /* 0.1453 C */
 229                        return IIO_VAL_INT_PLUS_MICRO;
 230                default:
 231                        return -EINVAL;
 232                }
 233        case IIO_CHAN_INFO_OFFSET:
 234                *val = 250000 / 1453; /* 25 C = 0x00 */
 235                return IIO_VAL_INT;
 236        case IIO_CHAN_INFO_CALIBBIAS:
 237                addr = adis16260_addresses[chan->scan_index][0];
 238                ret = adis_read_reg_16(adis, addr, &val16);
 239                if (ret)
 240                        return ret;
 241
 242                *val = sign_extend32(val16, 11);
 243                return IIO_VAL_INT;
 244        case IIO_CHAN_INFO_CALIBSCALE:
 245                addr = adis16260_addresses[chan->scan_index][1];
 246                ret = adis_read_reg_16(adis, addr, &val16);
 247                if (ret)
 248                        return ret;
 249
 250                *val = val16;
 251                return IIO_VAL_INT;
 252        case IIO_CHAN_INFO_SAMP_FREQ:
 253                ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &val16);
 254                if (ret)
 255                        return ret;
 256
 257                if (spi_get_device_id(adis->spi)->driver_data)
 258                /* If an adis16251 */
 259                        *val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
 260                                8 : 256;
 261                else
 262                        *val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
 263                                66 : 2048;
 264                *val /= (val16 & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
 265                return IIO_VAL_INT;
 266        }
 267        return -EINVAL;
 268}
 269
 270static int adis16260_write_raw(struct iio_dev *indio_dev,
 271                               struct iio_chan_spec const *chan,
 272                               int val,
 273                               int val2,
 274                               long mask)
 275{
 276        struct adis16260 *adis16260 = iio_priv(indio_dev);
 277        struct adis *adis = &adis16260->adis;
 278        int ret;
 279        u8 addr;
 280        u8 t;
 281
 282        switch (mask) {
 283        case IIO_CHAN_INFO_CALIBBIAS:
 284                if (val < -2048 || val >= 2048)
 285                        return -EINVAL;
 286
 287                addr = adis16260_addresses[chan->scan_index][0];
 288                return adis_write_reg_16(adis, addr, val);
 289        case IIO_CHAN_INFO_CALIBSCALE:
 290                if (val < 0 || val >= 4096)
 291                        return -EINVAL;
 292
 293                addr = adis16260_addresses[chan->scan_index][1];
 294                return adis_write_reg_16(adis, addr, val);
 295        case IIO_CHAN_INFO_SAMP_FREQ:
 296                mutex_lock(&adis->state_lock);
 297                if (spi_get_device_id(adis->spi)->driver_data)
 298                        t = 256 / val;
 299                else
 300                        t = 2048 / val;
 301
 302                if (t > ADIS16260_SMPL_PRD_DIV_MASK)
 303                        t = ADIS16260_SMPL_PRD_DIV_MASK;
 304                else if (t > 0)
 305                        t--;
 306
 307                if (t >= 0x0A)
 308                        adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
 309                else
 310                        adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
 311                ret = __adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
 312
 313                mutex_unlock(&adis->state_lock);
 314                return ret;
 315        }
 316        return -EINVAL;
 317}
 318
 319static const struct iio_info adis16260_info = {
 320        .read_raw = &adis16260_read_raw,
 321        .write_raw = &adis16260_write_raw,
 322        .update_scan_mode = adis_update_scan_mode,
 323};
 324
 325static const char * const adis1620_status_error_msgs[] = {
 326        [ADIS16260_DIAG_STAT_FLASH_CHK_BIT] = "Flash checksum error",
 327        [ADIS16260_DIAG_STAT_SELF_TEST_BIT] = "Self test error",
 328        [ADIS16260_DIAG_STAT_OVERFLOW_BIT] = "Sensor overrange",
 329        [ADIS16260_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
 330        [ADIS16260_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
 331        [ADIS16260_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 5.25",
 332        [ADIS16260_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 4.75",
 333};
 334
 335static const struct adis_timeout adis16260_timeouts = {
 336        .reset_ms = ADIS16260_STARTUP_DELAY,
 337        .sw_reset_ms = ADIS16260_STARTUP_DELAY,
 338        .self_test_ms = ADIS16260_STARTUP_DELAY,
 339};
 340
 341static const struct adis_data adis16260_data = {
 342        .write_delay = 30,
 343        .read_delay = 30,
 344        .msc_ctrl_reg = ADIS16260_MSC_CTRL,
 345        .glob_cmd_reg = ADIS16260_GLOB_CMD,
 346        .diag_stat_reg = ADIS16260_DIAG_STAT,
 347
 348        .self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST,
 349        .timeouts = &adis16260_timeouts,
 350
 351        .status_error_msgs = adis1620_status_error_msgs,
 352        .status_error_mask = BIT(ADIS16260_DIAG_STAT_FLASH_CHK_BIT) |
 353                BIT(ADIS16260_DIAG_STAT_SELF_TEST_BIT) |
 354                BIT(ADIS16260_DIAG_STAT_OVERFLOW_BIT) |
 355                BIT(ADIS16260_DIAG_STAT_SPI_FAIL_BIT) |
 356                BIT(ADIS16260_DIAG_STAT_FLASH_UPT_BIT) |
 357                BIT(ADIS16260_DIAG_STAT_POWER_HIGH_BIT) |
 358                BIT(ADIS16260_DIAG_STAT_POWER_LOW_BIT),
 359};
 360
 361static int adis16260_probe(struct spi_device *spi)
 362{
 363        const struct spi_device_id *id;
 364        struct adis16260 *adis16260;
 365        struct iio_dev *indio_dev;
 366        int ret;
 367
 368        id = spi_get_device_id(spi);
 369        if (!id)
 370                return -ENODEV;
 371
 372        /* setup the industrialio driver allocated elements */
 373        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16260));
 374        if (!indio_dev)
 375                return -ENOMEM;
 376        adis16260 = iio_priv(indio_dev);
 377        /* this is only used for removal purposes */
 378        spi_set_drvdata(spi, indio_dev);
 379
 380        adis16260->info = &adis16260_chip_info_table[id->driver_data];
 381
 382        indio_dev->name = id->name;
 383        indio_dev->dev.parent = &spi->dev;
 384        indio_dev->info = &adis16260_info;
 385        indio_dev->channels = adis16260->info->channels;
 386        indio_dev->num_channels = adis16260->info->num_channels;
 387        indio_dev->modes = INDIO_DIRECT_MODE;
 388
 389        ret = adis_init(&adis16260->adis, indio_dev, spi, &adis16260_data);
 390        if (ret)
 391                return ret;
 392
 393        ret = adis_setup_buffer_and_trigger(&adis16260->adis, indio_dev, NULL);
 394        if (ret)
 395                return ret;
 396
 397        /* Get the device into a sane initial state */
 398        ret = adis_initial_startup(&adis16260->adis);
 399        if (ret)
 400                goto error_cleanup_buffer_trigger;
 401        ret = iio_device_register(indio_dev);
 402        if (ret)
 403                goto error_cleanup_buffer_trigger;
 404
 405        return 0;
 406
 407error_cleanup_buffer_trigger:
 408        adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev);
 409        return ret;
 410}
 411
 412static int adis16260_remove(struct spi_device *spi)
 413{
 414        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 415        struct adis16260 *adis16260 = iio_priv(indio_dev);
 416
 417        iio_device_unregister(indio_dev);
 418        adis16260_stop_device(indio_dev);
 419        adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev);
 420
 421        return 0;
 422}
 423
 424/*
 425 * These parts do not need to be differentiated until someone adds
 426 * support for the on chip filtering.
 427 */
 428static const struct spi_device_id adis16260_id[] = {
 429        {"adis16260", ADIS16260},
 430        {"adis16265", ADIS16260},
 431        {"adis16266", ADIS16266},
 432        {"adis16250", ADIS16260},
 433        {"adis16255", ADIS16260},
 434        {"adis16251", ADIS16251},
 435        {}
 436};
 437MODULE_DEVICE_TABLE(spi, adis16260_id);
 438
 439static struct spi_driver adis16260_driver = {
 440        .driver = {
 441                .name = "adis16260",
 442        },
 443        .probe = adis16260_probe,
 444        .remove = adis16260_remove,
 445        .id_table = adis16260_id,
 446};
 447module_spi_driver(adis16260_driver);
 448
 449MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
 450MODULE_DESCRIPTION("Analog Devices ADIS16260/5 Digital Gyroscope Sensor");
 451MODULE_LICENSE("GPL v2");
 452