root/drivers/iio/accel/adxl345_core.c

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

DEFINITIONS

This source file includes following definitions.
  1. adxl345_read_raw
  2. adxl345_write_raw
  3. adxl345_write_raw_get_fmt
  4. adxl345_core_probe
  5. adxl345_core_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * ADXL345 3-Axis Digital Accelerometer IIO core driver
   4  *
   5  * Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
   6  *
   7  * Datasheet: http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/regmap.h>
  12 
  13 #include <linux/iio/iio.h>
  14 #include <linux/iio/sysfs.h>
  15 
  16 #include "adxl345.h"
  17 
  18 #define ADXL345_REG_DEVID               0x00
  19 #define ADXL345_REG_OFSX                0x1e
  20 #define ADXL345_REG_OFSY                0x1f
  21 #define ADXL345_REG_OFSZ                0x20
  22 #define ADXL345_REG_OFS_AXIS(index)     (ADXL345_REG_OFSX + (index))
  23 #define ADXL345_REG_BW_RATE             0x2C
  24 #define ADXL345_REG_POWER_CTL           0x2D
  25 #define ADXL345_REG_DATA_FORMAT         0x31
  26 #define ADXL345_REG_DATAX0              0x32
  27 #define ADXL345_REG_DATAY0              0x34
  28 #define ADXL345_REG_DATAZ0              0x36
  29 #define ADXL345_REG_DATA_AXIS(index)    \
  30         (ADXL345_REG_DATAX0 + (index) * sizeof(__le16))
  31 
  32 #define ADXL345_BW_RATE                 GENMASK(3, 0)
  33 #define ADXL345_BASE_RATE_NANO_HZ       97656250LL
  34 #define NHZ_PER_HZ                      1000000000LL
  35 
  36 #define ADXL345_POWER_CTL_MEASURE       BIT(3)
  37 #define ADXL345_POWER_CTL_STANDBY       0x00
  38 
  39 #define ADXL345_DATA_FORMAT_FULL_RES    BIT(3) /* Up to 13-bits resolution */
  40 #define ADXL345_DATA_FORMAT_2G          0
  41 #define ADXL345_DATA_FORMAT_4G          1
  42 #define ADXL345_DATA_FORMAT_8G          2
  43 #define ADXL345_DATA_FORMAT_16G         3
  44 
  45 #define ADXL345_DEVID                   0xE5
  46 
  47 /*
  48  * In full-resolution mode, scale factor is maintained at ~4 mg/LSB
  49  * in all g ranges.
  50  *
  51  * At +/- 16g with 13-bit resolution, scale is computed as:
  52  * (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
  53  */
  54 static const int adxl345_uscale = 38300;
  55 
  56 /*
  57  * The Datasheet lists a resolution of Resolution is ~49 mg per LSB. That's
  58  * ~480mm/s**2 per LSB.
  59  */
  60 static const int adxl375_uscale = 480000;
  61 
  62 struct adxl345_data {
  63         struct regmap *regmap;
  64         u8 data_range;
  65         enum adxl345_device_type type;
  66 };
  67 
  68 #define ADXL345_CHANNEL(index, axis) {                                  \
  69         .type = IIO_ACCEL,                                              \
  70         .modified = 1,                                                  \
  71         .channel2 = IIO_MOD_##axis,                                     \
  72         .address = index,                                               \
  73         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |                  \
  74                 BIT(IIO_CHAN_INFO_CALIBBIAS),                           \
  75         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |          \
  76                 BIT(IIO_CHAN_INFO_SAMP_FREQ),                           \
  77 }
  78 
  79 static const struct iio_chan_spec adxl345_channels[] = {
  80         ADXL345_CHANNEL(0, X),
  81         ADXL345_CHANNEL(1, Y),
  82         ADXL345_CHANNEL(2, Z),
  83 };
  84 
  85 static int adxl345_read_raw(struct iio_dev *indio_dev,
  86                             struct iio_chan_spec const *chan,
  87                             int *val, int *val2, long mask)
  88 {
  89         struct adxl345_data *data = iio_priv(indio_dev);
  90         __le16 accel;
  91         long long samp_freq_nhz;
  92         unsigned int regval;
  93         int ret;
  94 
  95         switch (mask) {
  96         case IIO_CHAN_INFO_RAW:
  97                 /*
  98                  * Data is stored in adjacent registers:
  99                  * ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte
 100                  * and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte
 101                  */
 102                 ret = regmap_bulk_read(data->regmap,
 103                                        ADXL345_REG_DATA_AXIS(chan->address),
 104                                        &accel, sizeof(accel));
 105                 if (ret < 0)
 106                         return ret;
 107 
 108                 *val = sign_extend32(le16_to_cpu(accel), 12);
 109                 return IIO_VAL_INT;
 110         case IIO_CHAN_INFO_SCALE:
 111                 *val = 0;
 112                 switch (data->type) {
 113                 case ADXL345:
 114                         *val2 = adxl345_uscale;
 115                         break;
 116                 case ADXL375:
 117                         *val2 = adxl375_uscale;
 118                         break;
 119                 }
 120 
 121                 return IIO_VAL_INT_PLUS_MICRO;
 122         case IIO_CHAN_INFO_CALIBBIAS:
 123                 ret = regmap_read(data->regmap,
 124                                   ADXL345_REG_OFS_AXIS(chan->address), &regval);
 125                 if (ret < 0)
 126                         return ret;
 127                 /*
 128                  * 8-bit resolution at +/- 2g, that is 4x accel data scale
 129                  * factor
 130                  */
 131                 *val = sign_extend32(regval, 7) * 4;
 132 
 133                 return IIO_VAL_INT;
 134         case IIO_CHAN_INFO_SAMP_FREQ:
 135                 ret = regmap_read(data->regmap, ADXL345_REG_BW_RATE, &regval);
 136                 if (ret < 0)
 137                         return ret;
 138 
 139                 samp_freq_nhz = ADXL345_BASE_RATE_NANO_HZ <<
 140                                 (regval & ADXL345_BW_RATE);
 141                 *val = div_s64_rem(samp_freq_nhz, NHZ_PER_HZ, val2);
 142 
 143                 return IIO_VAL_INT_PLUS_NANO;
 144         }
 145 
 146         return -EINVAL;
 147 }
 148 
 149 static int adxl345_write_raw(struct iio_dev *indio_dev,
 150                              struct iio_chan_spec const *chan,
 151                              int val, int val2, long mask)
 152 {
 153         struct adxl345_data *data = iio_priv(indio_dev);
 154         s64 n;
 155 
 156         switch (mask) {
 157         case IIO_CHAN_INFO_CALIBBIAS:
 158                 /*
 159                  * 8-bit resolution at +/- 2g, that is 4x accel data scale
 160                  * factor
 161                  */
 162                 return regmap_write(data->regmap,
 163                                     ADXL345_REG_OFS_AXIS(chan->address),
 164                                     val / 4);
 165         case IIO_CHAN_INFO_SAMP_FREQ:
 166                 n = div_s64(val * NHZ_PER_HZ + val2, ADXL345_BASE_RATE_NANO_HZ);
 167 
 168                 return regmap_update_bits(data->regmap, ADXL345_REG_BW_RATE,
 169                                           ADXL345_BW_RATE,
 170                                           clamp_val(ilog2(n), 0,
 171                                                     ADXL345_BW_RATE));
 172         }
 173 
 174         return -EINVAL;
 175 }
 176 
 177 static int adxl345_write_raw_get_fmt(struct iio_dev *indio_dev,
 178                                      struct iio_chan_spec const *chan,
 179                                      long mask)
 180 {
 181         switch (mask) {
 182         case IIO_CHAN_INFO_CALIBBIAS:
 183                 return IIO_VAL_INT;
 184         case IIO_CHAN_INFO_SAMP_FREQ:
 185                 return IIO_VAL_INT_PLUS_NANO;
 186         default:
 187                 return -EINVAL;
 188         }
 189 }
 190 
 191 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
 192 "0.09765625 0.1953125 0.390625 0.78125 1.5625 3.125 6.25 12.5 25 50 100 200 400 800 1600 3200"
 193 );
 194 
 195 static struct attribute *adxl345_attrs[] = {
 196         &iio_const_attr_sampling_frequency_available.dev_attr.attr,
 197         NULL,
 198 };
 199 
 200 static const struct attribute_group adxl345_attrs_group = {
 201         .attrs = adxl345_attrs,
 202 };
 203 
 204 static const struct iio_info adxl345_info = {
 205         .attrs          = &adxl345_attrs_group,
 206         .read_raw       = adxl345_read_raw,
 207         .write_raw      = adxl345_write_raw,
 208         .write_raw_get_fmt      = adxl345_write_raw_get_fmt,
 209 };
 210 
 211 int adxl345_core_probe(struct device *dev, struct regmap *regmap,
 212                        enum adxl345_device_type type, const char *name)
 213 {
 214         struct adxl345_data *data;
 215         struct iio_dev *indio_dev;
 216         u32 regval;
 217         int ret;
 218 
 219         ret = regmap_read(regmap, ADXL345_REG_DEVID, &regval);
 220         if (ret < 0) {
 221                 dev_err(dev, "Error reading device ID: %d\n", ret);
 222                 return ret;
 223         }
 224 
 225         if (regval != ADXL345_DEVID) {
 226                 dev_err(dev, "Invalid device ID: %x, expected %x\n",
 227                         regval, ADXL345_DEVID);
 228                 return -ENODEV;
 229         }
 230 
 231         indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
 232         if (!indio_dev)
 233                 return -ENOMEM;
 234 
 235         data = iio_priv(indio_dev);
 236         dev_set_drvdata(dev, indio_dev);
 237         data->regmap = regmap;
 238         data->type = type;
 239         /* Enable full-resolution mode */
 240         data->data_range = ADXL345_DATA_FORMAT_FULL_RES;
 241 
 242         ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT,
 243                            data->data_range);
 244         if (ret < 0) {
 245                 dev_err(dev, "Failed to set data range: %d\n", ret);
 246                 return ret;
 247         }
 248 
 249         indio_dev->dev.parent = dev;
 250         indio_dev->name = name;
 251         indio_dev->info = &adxl345_info;
 252         indio_dev->modes = INDIO_DIRECT_MODE;
 253         indio_dev->channels = adxl345_channels;
 254         indio_dev->num_channels = ARRAY_SIZE(adxl345_channels);
 255 
 256         /* Enable measurement mode */
 257         ret = regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
 258                            ADXL345_POWER_CTL_MEASURE);
 259         if (ret < 0) {
 260                 dev_err(dev, "Failed to enable measurement mode: %d\n", ret);
 261                 return ret;
 262         }
 263 
 264         ret = iio_device_register(indio_dev);
 265         if (ret < 0) {
 266                 dev_err(dev, "iio_device_register failed: %d\n", ret);
 267                 regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
 268                              ADXL345_POWER_CTL_STANDBY);
 269         }
 270 
 271         return ret;
 272 }
 273 EXPORT_SYMBOL_GPL(adxl345_core_probe);
 274 
 275 int adxl345_core_remove(struct device *dev)
 276 {
 277         struct iio_dev *indio_dev = dev_get_drvdata(dev);
 278         struct adxl345_data *data = iio_priv(indio_dev);
 279 
 280         iio_device_unregister(indio_dev);
 281 
 282         return regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
 283                             ADXL345_POWER_CTL_STANDBY);
 284 }
 285 EXPORT_SYMBOL_GPL(adxl345_core_remove);
 286 
 287 MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
 288 MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer core driver");
 289 MODULE_LICENSE("GPL v2");

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