Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ADXL313 3-Axis Digital Accelerometer
0004  *
0005  * Copyright (c) 2021 Lucas Stankus <lucas.p.stankus@gmail.com>
0006  *
0007  * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL313.pdf
0008  */
0009 
0010 #include <linux/bitfield.h>
0011 #include <linux/iio/iio.h>
0012 #include <linux/module.h>
0013 #include <linux/regmap.h>
0014 
0015 #include "adxl313.h"
0016 
0017 static const struct regmap_range adxl313_readable_reg_range[] = {
0018     regmap_reg_range(ADXL313_REG_DEVID0, ADXL313_REG_XID),
0019     regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET),
0020     regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
0021     regmap_reg_range(ADXL313_REG_THRESH_ACT, ADXL313_REG_ACT_INACT_CTL),
0022     regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_FIFO_STATUS),
0023 };
0024 
0025 const struct regmap_access_table adxl313_readable_regs_table = {
0026     .yes_ranges = adxl313_readable_reg_range,
0027     .n_yes_ranges = ARRAY_SIZE(adxl313_readable_reg_range),
0028 };
0029 EXPORT_SYMBOL_NS_GPL(adxl313_readable_regs_table, IIO_ADXL313);
0030 
0031 static const struct regmap_range adxl313_writable_reg_range[] = {
0032     regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET),
0033     regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
0034     regmap_reg_range(ADXL313_REG_THRESH_ACT, ADXL313_REG_ACT_INACT_CTL),
0035     regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_INT_MAP),
0036     regmap_reg_range(ADXL313_REG_DATA_FORMAT, ADXL313_REG_DATA_FORMAT),
0037     regmap_reg_range(ADXL313_REG_FIFO_CTL, ADXL313_REG_FIFO_CTL),
0038 };
0039 
0040 const struct regmap_access_table adxl313_writable_regs_table = {
0041     .yes_ranges = adxl313_writable_reg_range,
0042     .n_yes_ranges = ARRAY_SIZE(adxl313_writable_reg_range),
0043 };
0044 EXPORT_SYMBOL_NS_GPL(adxl313_writable_regs_table, IIO_ADXL313);
0045 
0046 struct adxl313_data {
0047     struct regmap   *regmap;
0048     struct mutex    lock; /* lock to protect transf_buf */
0049     __le16      transf_buf __aligned(IIO_DMA_MINALIGN);
0050 };
0051 
0052 static const int adxl313_odr_freqs[][2] = {
0053     [0] = { 6, 250000 },
0054     [1] = { 12, 500000 },
0055     [2] = { 25, 0 },
0056     [3] = { 50, 0 },
0057     [4] = { 100, 0 },
0058     [5] = { 200, 0 },
0059     [6] = { 400, 0 },
0060     [7] = { 800, 0 },
0061     [8] = { 1600, 0 },
0062     [9] = { 3200, 0 },
0063 };
0064 
0065 #define ADXL313_ACCEL_CHANNEL(index, axis) {                \
0066     .type = IIO_ACCEL,                      \
0067     .address = index,                       \
0068     .modified = 1,                          \
0069     .channel2 = IIO_MOD_##axis,                 \
0070     .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |          \
0071                   BIT(IIO_CHAN_INFO_CALIBBIAS),     \
0072     .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |      \
0073                     BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
0074     .info_mask_shared_by_type_available =               \
0075         BIT(IIO_CHAN_INFO_SAMP_FREQ),               \
0076     .scan_type = {                          \
0077         .realbits = 13,                     \
0078     },                              \
0079 }
0080 
0081 static const struct iio_chan_spec adxl313_channels[] = {
0082     ADXL313_ACCEL_CHANNEL(0, X),
0083     ADXL313_ACCEL_CHANNEL(1, Y),
0084     ADXL313_ACCEL_CHANNEL(2, Z),
0085 };
0086 
0087 static int adxl313_set_odr(struct adxl313_data *data,
0088                unsigned int freq1, unsigned int freq2)
0089 {
0090     unsigned int i;
0091 
0092     for (i = 0; i < ARRAY_SIZE(adxl313_odr_freqs); i++) {
0093         if (adxl313_odr_freqs[i][0] == freq1 &&
0094             adxl313_odr_freqs[i][1] == freq2)
0095             break;
0096     }
0097 
0098     if (i == ARRAY_SIZE(adxl313_odr_freqs))
0099         return -EINVAL;
0100 
0101     return regmap_update_bits(data->regmap, ADXL313_REG_BW_RATE,
0102                   ADXL313_RATE_MSK,
0103                   FIELD_PREP(ADXL313_RATE_MSK, ADXL313_RATE_BASE + i));
0104 }
0105 
0106 static int adxl313_read_axis(struct adxl313_data *data,
0107                  struct iio_chan_spec const *chan)
0108 {
0109     int ret;
0110 
0111     mutex_lock(&data->lock);
0112 
0113     ret = regmap_bulk_read(data->regmap,
0114                    ADXL313_REG_DATA_AXIS(chan->address),
0115                    &data->transf_buf, sizeof(data->transf_buf));
0116     if (ret)
0117         goto unlock_ret;
0118 
0119     ret = le16_to_cpu(data->transf_buf);
0120 
0121 unlock_ret:
0122     mutex_unlock(&data->lock);
0123     return ret;
0124 }
0125 
0126 static int adxl313_read_freq_avail(struct iio_dev *indio_dev,
0127                    struct iio_chan_spec const *chan,
0128                    const int **vals, int *type, int *length,
0129                    long mask)
0130 {
0131     switch (mask) {
0132     case IIO_CHAN_INFO_SAMP_FREQ:
0133         *vals = (const int *)adxl313_odr_freqs;
0134         *length = ARRAY_SIZE(adxl313_odr_freqs) * 2;
0135         *type = IIO_VAL_INT_PLUS_MICRO;
0136         return IIO_AVAIL_LIST;
0137     default:
0138         return -EINVAL;
0139     }
0140 }
0141 
0142 static int adxl313_read_raw(struct iio_dev *indio_dev,
0143                 struct iio_chan_spec const *chan,
0144                 int *val, int *val2, long mask)
0145 {
0146     struct adxl313_data *data = iio_priv(indio_dev);
0147     unsigned int regval;
0148     int ret;
0149 
0150     switch (mask) {
0151     case IIO_CHAN_INFO_RAW:
0152         ret = adxl313_read_axis(data, chan);
0153         if (ret < 0)
0154             return ret;
0155 
0156         *val = sign_extend32(ret, chan->scan_type.realbits - 1);
0157         return IIO_VAL_INT;
0158     case IIO_CHAN_INFO_SCALE:
0159         /*
0160          * Scale for any g range is given in datasheet as
0161          * 1024 LSB/g = 0.0009765625 * 9.80665 = 0.009576806640625 m/s^2
0162          */
0163         *val = 0;
0164         *val2 = 9576806;
0165         return IIO_VAL_INT_PLUS_NANO;
0166     case IIO_CHAN_INFO_CALIBBIAS:
0167         ret = regmap_read(data->regmap,
0168                   ADXL313_REG_OFS_AXIS(chan->address), &regval);
0169         if (ret)
0170             return ret;
0171 
0172         /*
0173          * 8-bit resolution at +/- 0.5g, that is 4x accel data scale
0174          * factor at full resolution
0175          */
0176         *val = sign_extend32(regval, 7) * 4;
0177         return IIO_VAL_INT;
0178     case IIO_CHAN_INFO_SAMP_FREQ:
0179         ret = regmap_read(data->regmap, ADXL313_REG_BW_RATE, &regval);
0180         if (ret)
0181             return ret;
0182 
0183         ret = FIELD_GET(ADXL313_RATE_MSK, regval) - ADXL313_RATE_BASE;
0184         *val = adxl313_odr_freqs[ret][0];
0185         *val2 = adxl313_odr_freqs[ret][1];
0186         return IIO_VAL_INT_PLUS_MICRO;
0187     default:
0188         return -EINVAL;
0189     }
0190 }
0191 
0192 static int adxl313_write_raw(struct iio_dev *indio_dev,
0193                  struct iio_chan_spec const *chan,
0194                  int val, int val2, long mask)
0195 {
0196     struct adxl313_data *data = iio_priv(indio_dev);
0197 
0198     switch (mask) {
0199     case IIO_CHAN_INFO_CALIBBIAS:
0200         /*
0201          * 8-bit resolution at +/- 0.5g, that is 4x accel data scale
0202          * factor at full resolution
0203          */
0204         if (clamp_val(val, -128 * 4, 127 * 4) != val)
0205             return -EINVAL;
0206 
0207         return regmap_write(data->regmap,
0208                     ADXL313_REG_OFS_AXIS(chan->address),
0209                     val / 4);
0210     case IIO_CHAN_INFO_SAMP_FREQ:
0211         return adxl313_set_odr(data, val, val2);
0212     default:
0213         return -EINVAL;
0214     }
0215 }
0216 
0217 static const struct iio_info adxl313_info = {
0218     .read_raw   = adxl313_read_raw,
0219     .write_raw  = adxl313_write_raw,
0220     .read_avail = adxl313_read_freq_avail,
0221 };
0222 
0223 static int adxl313_setup(struct device *dev, struct adxl313_data *data,
0224              int (*setup)(struct device *, struct regmap *))
0225 {
0226     unsigned int regval;
0227     int ret;
0228 
0229     /* Ensures the device is in a consistent state after start up */
0230     ret = regmap_write(data->regmap, ADXL313_REG_SOFT_RESET,
0231                ADXL313_SOFT_RESET);
0232     if (ret)
0233         return ret;
0234 
0235     if (setup) {
0236         ret = setup(dev, data->regmap);
0237         if (ret)
0238             return ret;
0239     }
0240 
0241     ret = regmap_read(data->regmap, ADXL313_REG_DEVID0, &regval);
0242     if (ret)
0243         return ret;
0244 
0245     if (regval != ADXL313_DEVID0) {
0246         dev_err(dev, "Invalid manufacturer ID: 0x%02x\n", regval);
0247         return -ENODEV;
0248     }
0249 
0250     ret = regmap_read(data->regmap, ADXL313_REG_DEVID1, &regval);
0251     if (ret)
0252         return ret;
0253 
0254     if (regval != ADXL313_DEVID1) {
0255         dev_err(dev, "Invalid mems ID: 0x%02x\n", regval);
0256         return -ENODEV;
0257     }
0258 
0259     ret = regmap_read(data->regmap, ADXL313_REG_PARTID, &regval);
0260     if (ret)
0261         return ret;
0262 
0263     if (regval != ADXL313_PARTID) {
0264         dev_err(dev, "Invalid device ID: 0x%02x\n", regval);
0265         return -ENODEV;
0266     }
0267 
0268     /* Sets the range to +/- 4g */
0269     ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
0270                  ADXL313_RANGE_MSK,
0271                  FIELD_PREP(ADXL313_RANGE_MSK, ADXL313_RANGE_4G));
0272     if (ret)
0273         return ret;
0274 
0275     /* Enables full resolution */
0276     ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
0277                  ADXL313_FULL_RES, ADXL313_FULL_RES);
0278     if (ret)
0279         return ret;
0280 
0281     /* Enables measurement mode */
0282     return regmap_update_bits(data->regmap, ADXL313_REG_POWER_CTL,
0283                   ADXL313_POWER_CTL_MSK,
0284                   ADXL313_MEASUREMENT_MODE);
0285 }
0286 
0287 /**
0288  * adxl313_core_probe() - probe and setup for adxl313 accelerometer
0289  * @dev:    Driver model representation of the device
0290  * @regmap: Register map of the device
0291  * @name:   Device name buffer reference
0292  * @setup:  Setup routine to be executed right before the standard device
0293  *      setup, can also be set to NULL if not required
0294  *
0295  * Return: 0 on success, negative errno on error cases
0296  */
0297 int adxl313_core_probe(struct device *dev,
0298                struct regmap *regmap,
0299                const char *name,
0300                int (*setup)(struct device *, struct regmap *))
0301 {
0302     struct adxl313_data *data;
0303     struct iio_dev *indio_dev;
0304     int ret;
0305 
0306     indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
0307     if (!indio_dev)
0308         return -ENOMEM;
0309 
0310     data = iio_priv(indio_dev);
0311     data->regmap = regmap;
0312     mutex_init(&data->lock);
0313 
0314     indio_dev->name = name;
0315     indio_dev->info = &adxl313_info;
0316     indio_dev->modes = INDIO_DIRECT_MODE;
0317     indio_dev->channels = adxl313_channels;
0318     indio_dev->num_channels = ARRAY_SIZE(adxl313_channels);
0319 
0320     ret = adxl313_setup(dev, data, setup);
0321     if (ret) {
0322         dev_err(dev, "ADXL313 setup failed\n");
0323         return ret;
0324     }
0325 
0326     return devm_iio_device_register(dev, indio_dev);
0327 }
0328 EXPORT_SYMBOL_NS_GPL(adxl313_core_probe, IIO_ADXL313);
0329 
0330 MODULE_AUTHOR("Lucas Stankus <lucas.p.stankus@gmail.com>");
0331 MODULE_DESCRIPTION("ADXL313 3-Axis Digital Accelerometer core driver");
0332 MODULE_LICENSE("GPL v2");