root/drivers/iio/accel/adis16209.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. adis16209_write_raw
  2. adis16209_read_raw
  3. adis16209_probe
  4. adis16209_remove

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer
   4  *
   5  * Copyright 2010 Analog Devices Inc.
   6  */
   7 
   8 #include <linux/device.h>
   9 #include <linux/kernel.h>
  10 #include <linux/list.h>
  11 #include <linux/module.h>
  12 #include <linux/spi/spi.h>
  13 #include <linux/slab.h>
  14 #include <linux/sysfs.h>
  15 
  16 #include <linux/iio/iio.h>
  17 #include <linux/iio/imu/adis.h>
  18 
  19 #define ADIS16209_STARTUP_DELAY_MS      220
  20 #define ADIS16209_FLASH_CNT_REG         0x00
  21 
  22 /* Data Output Register Definitions */
  23 #define ADIS16209_SUPPLY_OUT_REG        0x02
  24 #define ADIS16209_XACCL_OUT_REG         0x04
  25 #define ADIS16209_YACCL_OUT_REG         0x06
  26 /* Output, auxiliary ADC input */
  27 #define ADIS16209_AUX_ADC_REG           0x08
  28 /* Output, temperature */
  29 #define ADIS16209_TEMP_OUT_REG          0x0A
  30 /* Output, +/- 90 degrees X-axis inclination */
  31 #define ADIS16209_XINCL_OUT_REG         0x0C
  32 #define ADIS16209_YINCL_OUT_REG         0x0E
  33 /* Output, +/-180 vertical rotational position */
  34 #define ADIS16209_ROT_OUT_REG           0x10
  35 
  36 /*
  37  * Calibration Register Definitions.
  38  * Acceleration, inclination or rotation offset null.
  39  */
  40 #define ADIS16209_XACCL_NULL_REG        0x12
  41 #define ADIS16209_YACCL_NULL_REG        0x14
  42 #define ADIS16209_XINCL_NULL_REG        0x16
  43 #define ADIS16209_YINCL_NULL_REG        0x18
  44 #define ADIS16209_ROT_NULL_REG          0x1A
  45 
  46 /* Alarm Register Definitions */
  47 #define ADIS16209_ALM_MAG1_REG          0x20
  48 #define ADIS16209_ALM_MAG2_REG          0x22
  49 #define ADIS16209_ALM_SMPL1_REG         0x24
  50 #define ADIS16209_ALM_SMPL2_REG         0x26
  51 #define ADIS16209_ALM_CTRL_REG          0x28
  52 
  53 #define ADIS16209_AUX_DAC_REG           0x30
  54 #define ADIS16209_GPIO_CTRL_REG         0x32
  55 #define ADIS16209_SMPL_PRD_REG          0x36
  56 #define ADIS16209_AVG_CNT_REG           0x38
  57 #define ADIS16209_SLP_CNT_REG           0x3A
  58 
  59 #define ADIS16209_MSC_CTRL_REG                  0x34
  60 #define  ADIS16209_MSC_CTRL_PWRUP_SELF_TEST     BIT(10)
  61 #define  ADIS16209_MSC_CTRL_SELF_TEST_EN        BIT(8)
  62 #define  ADIS16209_MSC_CTRL_DATA_RDY_EN         BIT(2)
  63 /* Data-ready polarity: 1 = active high, 0 = active low */
  64 #define  ADIS16209_MSC_CTRL_ACTIVE_HIGH         BIT(1)
  65 #define  ADIS16209_MSC_CTRL_DATA_RDY_DIO2       BIT(0)
  66 
  67 #define ADIS16209_STAT_REG                      0x3C
  68 #define  ADIS16209_STAT_ALARM2                  BIT(9)
  69 #define  ADIS16209_STAT_ALARM1                  BIT(8)
  70 #define  ADIS16209_STAT_SELFTEST_FAIL_BIT       5
  71 #define  ADIS16209_STAT_SPI_FAIL_BIT            3
  72 #define  ADIS16209_STAT_FLASH_UPT_FAIL_BIT      2
  73 /* Power supply above 3.625 V */
  74 #define  ADIS16209_STAT_POWER_HIGH_BIT          1
  75 /* Power supply below 2.975 V */
  76 #define  ADIS16209_STAT_POWER_LOW_BIT           0
  77 
  78 #define ADIS16209_CMD_REG                       0x3E
  79 #define  ADIS16209_CMD_SW_RESET                 BIT(7)
  80 #define  ADIS16209_CMD_CLEAR_STAT               BIT(4)
  81 #define  ADIS16209_CMD_FACTORY_CAL              BIT(1)
  82 
  83 #define ADIS16209_ERROR_ACTIVE                  BIT(14)
  84 
  85 enum adis16209_scan {
  86         ADIS16209_SCAN_SUPPLY,
  87         ADIS16209_SCAN_ACC_X,
  88         ADIS16209_SCAN_ACC_Y,
  89         ADIS16209_SCAN_AUX_ADC,
  90         ADIS16209_SCAN_TEMP,
  91         ADIS16209_SCAN_INCLI_X,
  92         ADIS16209_SCAN_INCLI_Y,
  93         ADIS16209_SCAN_ROT,
  94 };
  95 
  96 static const u8 adis16209_addresses[8][1] = {
  97         [ADIS16209_SCAN_SUPPLY] = { },
  98         [ADIS16209_SCAN_AUX_ADC] = { },
  99         [ADIS16209_SCAN_ACC_X] = { ADIS16209_XACCL_NULL_REG },
 100         [ADIS16209_SCAN_ACC_Y] = { ADIS16209_YACCL_NULL_REG },
 101         [ADIS16209_SCAN_INCLI_X] = { ADIS16209_XINCL_NULL_REG },
 102         [ADIS16209_SCAN_INCLI_Y] = { ADIS16209_YINCL_NULL_REG },
 103         [ADIS16209_SCAN_ROT] = { },
 104         [ADIS16209_SCAN_TEMP] = { },
 105 };
 106 
 107 static int adis16209_write_raw(struct iio_dev *indio_dev,
 108                                struct iio_chan_spec const *chan,
 109                                int val,
 110                                int val2,
 111                                long mask)
 112 {
 113         struct adis *st = iio_priv(indio_dev);
 114         int m;
 115 
 116         if (mask != IIO_CHAN_INFO_CALIBBIAS)
 117                 return -EINVAL;
 118 
 119         switch (chan->type) {
 120         case IIO_ACCEL:
 121         case IIO_INCLI:
 122                 m = GENMASK(13, 0);
 123                 break;
 124         default:
 125                 return -EINVAL;
 126         }
 127 
 128         return adis_write_reg_16(st, adis16209_addresses[chan->scan_index][0],
 129                                  val & m);
 130 }
 131 
 132 static int adis16209_read_raw(struct iio_dev *indio_dev,
 133                               struct iio_chan_spec const *chan,
 134                               int *val, int *val2,
 135                               long mask)
 136 {
 137         struct adis *st = iio_priv(indio_dev);
 138         int ret;
 139         int bits;
 140         u8 addr;
 141         s16 val16;
 142 
 143         switch (mask) {
 144         case IIO_CHAN_INFO_RAW:
 145                 return adis_single_conversion(indio_dev, chan,
 146                         ADIS16209_ERROR_ACTIVE, val);
 147         case IIO_CHAN_INFO_SCALE:
 148                 switch (chan->type) {
 149                 case IIO_VOLTAGE:
 150                         *val = 0;
 151                         switch (chan->channel) {
 152                         case 0:
 153                                 *val2 = 305180; /* 0.30518 mV */
 154                                 break;
 155                         case 1:
 156                                 *val2 = 610500; /* 0.6105 mV */
 157                                 break;
 158                         default:
 159                                 return -EINVAL;
 160                         }
 161                         return IIO_VAL_INT_PLUS_MICRO;
 162                 case IIO_TEMP:
 163                         *val = -470;
 164                         *val2 = 0;
 165                         return IIO_VAL_INT_PLUS_MICRO;
 166                 case IIO_ACCEL:
 167                         /*
 168                          * IIO base unit for sensitivity of accelerometer
 169                          * is milli g.
 170                          * 1 LSB represents 0.244 mg.
 171                          */
 172                         *val = 0;
 173                         *val2 = IIO_G_TO_M_S_2(244140);
 174                         return IIO_VAL_INT_PLUS_NANO;
 175                 case IIO_INCLI:
 176                 case IIO_ROT:
 177                         /*
 178                          * IIO base units for rotation are degrees.
 179                          * 1 LSB represents 0.025 milli degrees.
 180                          */
 181                         *val = 0;
 182                         *val2 = 25000;
 183                         return IIO_VAL_INT_PLUS_MICRO;
 184                 default:
 185                         return -EINVAL;
 186                 }
 187                 break;
 188         case IIO_CHAN_INFO_OFFSET:
 189                 /*
 190                  * The raw ADC value is 0x4FE when the temperature
 191                  * is 45 degrees and the scale factor per milli
 192                  * degree celcius is -470.
 193                  */
 194                 *val = 25000 / -470 - 0x4FE;
 195                 return IIO_VAL_INT;
 196         case IIO_CHAN_INFO_CALIBBIAS:
 197                 switch (chan->type) {
 198                 case IIO_ACCEL:
 199                         bits = 14;
 200                         break;
 201                 default:
 202                         return -EINVAL;
 203                 }
 204                 addr = adis16209_addresses[chan->scan_index][0];
 205                 ret = adis_read_reg_16(st, addr, &val16);
 206                 if (ret)
 207                         return ret;
 208 
 209                 *val = sign_extend32(val16, bits - 1);
 210                 return IIO_VAL_INT;
 211         }
 212         return -EINVAL;
 213 }
 214 
 215 static const struct iio_chan_spec adis16209_channels[] = {
 216         ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT_REG, ADIS16209_SCAN_SUPPLY,
 217                          0, 14),
 218         ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT_REG, ADIS16209_SCAN_TEMP, 0, 12),
 219         ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT_REG, ADIS16209_SCAN_ACC_X,
 220                         BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
 221         ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT_REG, ADIS16209_SCAN_ACC_Y,
 222                         BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
 223         ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC_REG, ADIS16209_SCAN_AUX_ADC, 0, 12),
 224         ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT_REG, ADIS16209_SCAN_INCLI_X,
 225                         0, 0, 14),
 226         ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT_REG, ADIS16209_SCAN_INCLI_Y,
 227                         0, 0, 14),
 228         ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT_REG, ADIS16209_SCAN_ROT, 0, 0, 14),
 229         IIO_CHAN_SOFT_TIMESTAMP(8)
 230 };
 231 
 232 static const struct iio_info adis16209_info = {
 233         .read_raw = adis16209_read_raw,
 234         .write_raw = adis16209_write_raw,
 235         .update_scan_mode = adis_update_scan_mode,
 236 };
 237 
 238 static const char * const adis16209_status_error_msgs[] = {
 239         [ADIS16209_STAT_SELFTEST_FAIL_BIT] = "Self test failure",
 240         [ADIS16209_STAT_SPI_FAIL_BIT] = "SPI failure",
 241         [ADIS16209_STAT_FLASH_UPT_FAIL_BIT] = "Flash update failed",
 242         [ADIS16209_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
 243         [ADIS16209_STAT_POWER_LOW_BIT] = "Power supply below 2.975V",
 244 };
 245 
 246 static const struct adis_data adis16209_data = {
 247         .read_delay = 30,
 248         .msc_ctrl_reg = ADIS16209_MSC_CTRL_REG,
 249         .glob_cmd_reg = ADIS16209_CMD_REG,
 250         .diag_stat_reg = ADIS16209_STAT_REG,
 251 
 252         .self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN,
 253         .self_test_no_autoclear = true,
 254         .startup_delay = ADIS16209_STARTUP_DELAY_MS,
 255 
 256         .status_error_msgs = adis16209_status_error_msgs,
 257         .status_error_mask = BIT(ADIS16209_STAT_SELFTEST_FAIL_BIT) |
 258                 BIT(ADIS16209_STAT_SPI_FAIL_BIT) |
 259                 BIT(ADIS16209_STAT_FLASH_UPT_FAIL_BIT) |
 260                 BIT(ADIS16209_STAT_POWER_HIGH_BIT) |
 261                 BIT(ADIS16209_STAT_POWER_LOW_BIT),
 262 };
 263 
 264 static int adis16209_probe(struct spi_device *spi)
 265 {
 266         struct iio_dev *indio_dev;
 267         struct adis *st;
 268         int ret;
 269 
 270         indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 271         if (!indio_dev)
 272                 return -ENOMEM;
 273 
 274         st = iio_priv(indio_dev);
 275         spi_set_drvdata(spi, indio_dev);
 276 
 277         indio_dev->name = spi->dev.driver->name;
 278         indio_dev->dev.parent = &spi->dev;
 279         indio_dev->info = &adis16209_info;
 280         indio_dev->channels = adis16209_channels;
 281         indio_dev->num_channels = ARRAY_SIZE(adis16209_channels);
 282         indio_dev->modes = INDIO_DIRECT_MODE;
 283 
 284         ret = adis_init(st, indio_dev, spi, &adis16209_data);
 285         if (ret)
 286                 return ret;
 287 
 288         ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
 289         if (ret)
 290                 return ret;
 291 
 292         ret = adis_initial_startup(st);
 293         if (ret)
 294                 goto error_cleanup_buffer_trigger;
 295         ret = iio_device_register(indio_dev);
 296         if (ret)
 297                 goto error_cleanup_buffer_trigger;
 298 
 299         return 0;
 300 
 301 error_cleanup_buffer_trigger:
 302         adis_cleanup_buffer_and_trigger(st, indio_dev);
 303         return ret;
 304 }
 305 
 306 static int adis16209_remove(struct spi_device *spi)
 307 {
 308         struct iio_dev *indio_dev = spi_get_drvdata(spi);
 309         struct adis *st = iio_priv(indio_dev);
 310 
 311         iio_device_unregister(indio_dev);
 312         adis_cleanup_buffer_and_trigger(st, indio_dev);
 313 
 314         return 0;
 315 }
 316 
 317 static struct spi_driver adis16209_driver = {
 318         .driver = {
 319                 .name = "adis16209",
 320         },
 321         .probe = adis16209_probe,
 322         .remove = adis16209_remove,
 323 };
 324 module_spi_driver(adis16209_driver);
 325 
 326 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
 327 MODULE_DESCRIPTION("Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer");
 328 MODULE_LICENSE("GPL v2");
 329 MODULE_ALIAS("spi:adis16209");

/* [<][>][^][v][top][bottom][index][help] */