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