Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ADXL345 3-Axis Digital Accelerometer IIO core driver
0004  *
0005  * Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
0006  *
0007  * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/property.h>
0012 #include <linux/regmap.h>
0013 
0014 #include <linux/iio/iio.h>
0015 #include <linux/iio/sysfs.h>
0016 
0017 #include "adxl345.h"
0018 
0019 #define ADXL345_REG_DEVID       0x00
0020 #define ADXL345_REG_OFSX        0x1e
0021 #define ADXL345_REG_OFSY        0x1f
0022 #define ADXL345_REG_OFSZ        0x20
0023 #define ADXL345_REG_OFS_AXIS(index) (ADXL345_REG_OFSX + (index))
0024 #define ADXL345_REG_BW_RATE     0x2C
0025 #define ADXL345_REG_POWER_CTL       0x2D
0026 #define ADXL345_REG_DATA_FORMAT     0x31
0027 #define ADXL345_REG_DATAX0      0x32
0028 #define ADXL345_REG_DATAY0      0x34
0029 #define ADXL345_REG_DATAZ0      0x36
0030 #define ADXL345_REG_DATA_AXIS(index)    \
0031     (ADXL345_REG_DATAX0 + (index) * sizeof(__le16))
0032 
0033 #define ADXL345_BW_RATE         GENMASK(3, 0)
0034 #define ADXL345_BASE_RATE_NANO_HZ   97656250LL
0035 #define NHZ_PER_HZ          1000000000LL
0036 
0037 #define ADXL345_POWER_CTL_MEASURE   BIT(3)
0038 #define ADXL345_POWER_CTL_STANDBY   0x00
0039 
0040 #define ADXL345_DATA_FORMAT_FULL_RES    BIT(3) /* Up to 13-bits resolution */
0041 #define ADXL345_DATA_FORMAT_2G      0
0042 #define ADXL345_DATA_FORMAT_4G      1
0043 #define ADXL345_DATA_FORMAT_8G      2
0044 #define ADXL345_DATA_FORMAT_16G     3
0045 
0046 #define ADXL345_DEVID           0xE5
0047 
0048 /*
0049  * In full-resolution mode, scale factor is maintained at ~4 mg/LSB
0050  * in all g ranges.
0051  *
0052  * At +/- 16g with 13-bit resolution, scale is computed as:
0053  * (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
0054  */
0055 static const int adxl345_uscale = 38300;
0056 
0057 /*
0058  * The Datasheet lists a resolution of Resolution is ~49 mg per LSB. That's
0059  * ~480mm/s**2 per LSB.
0060  */
0061 static const int adxl375_uscale = 480000;
0062 
0063 struct adxl345_data {
0064     struct regmap *regmap;
0065     u8 data_range;
0066     enum adxl345_device_type type;
0067 };
0068 
0069 #define ADXL345_CHANNEL(index, axis) {                  \
0070     .type = IIO_ACCEL,                      \
0071     .modified = 1,                          \
0072     .channel2 = IIO_MOD_##axis,                 \
0073     .address = index,                       \
0074     .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |          \
0075         BIT(IIO_CHAN_INFO_CALIBBIAS),               \
0076     .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |      \
0077         BIT(IIO_CHAN_INFO_SAMP_FREQ),               \
0078 }
0079 
0080 static const struct iio_chan_spec adxl345_channels[] = {
0081     ADXL345_CHANNEL(0, X),
0082     ADXL345_CHANNEL(1, Y),
0083     ADXL345_CHANNEL(2, Z),
0084 };
0085 
0086 static int adxl345_read_raw(struct iio_dev *indio_dev,
0087                 struct iio_chan_spec const *chan,
0088                 int *val, int *val2, long mask)
0089 {
0090     struct adxl345_data *data = iio_priv(indio_dev);
0091     __le16 accel;
0092     long long samp_freq_nhz;
0093     unsigned int regval;
0094     int ret;
0095 
0096     switch (mask) {
0097     case IIO_CHAN_INFO_RAW:
0098         /*
0099          * Data is stored in adjacent registers:
0100          * ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte
0101          * and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte
0102          */
0103         ret = regmap_bulk_read(data->regmap,
0104                        ADXL345_REG_DATA_AXIS(chan->address),
0105                        &accel, sizeof(accel));
0106         if (ret < 0)
0107             return ret;
0108 
0109         *val = sign_extend32(le16_to_cpu(accel), 12);
0110         return IIO_VAL_INT;
0111     case IIO_CHAN_INFO_SCALE:
0112         *val = 0;
0113         switch (data->type) {
0114         case ADXL345:
0115             *val2 = adxl345_uscale;
0116             break;
0117         case ADXL375:
0118             *val2 = adxl375_uscale;
0119             break;
0120         }
0121 
0122         return IIO_VAL_INT_PLUS_MICRO;
0123     case IIO_CHAN_INFO_CALIBBIAS:
0124         ret = regmap_read(data->regmap,
0125                   ADXL345_REG_OFS_AXIS(chan->address), &regval);
0126         if (ret < 0)
0127             return ret;
0128         /*
0129          * 8-bit resolution at +/- 2g, that is 4x accel data scale
0130          * factor
0131          */
0132         *val = sign_extend32(regval, 7) * 4;
0133 
0134         return IIO_VAL_INT;
0135     case IIO_CHAN_INFO_SAMP_FREQ:
0136         ret = regmap_read(data->regmap, ADXL345_REG_BW_RATE, &regval);
0137         if (ret < 0)
0138             return ret;
0139 
0140         samp_freq_nhz = ADXL345_BASE_RATE_NANO_HZ <<
0141                 (regval & ADXL345_BW_RATE);
0142         *val = div_s64_rem(samp_freq_nhz, NHZ_PER_HZ, val2);
0143 
0144         return IIO_VAL_INT_PLUS_NANO;
0145     }
0146 
0147     return -EINVAL;
0148 }
0149 
0150 static int adxl345_write_raw(struct iio_dev *indio_dev,
0151                  struct iio_chan_spec const *chan,
0152                  int val, int val2, long mask)
0153 {
0154     struct adxl345_data *data = iio_priv(indio_dev);
0155     s64 n;
0156 
0157     switch (mask) {
0158     case IIO_CHAN_INFO_CALIBBIAS:
0159         /*
0160          * 8-bit resolution at +/- 2g, that is 4x accel data scale
0161          * factor
0162          */
0163         return regmap_write(data->regmap,
0164                     ADXL345_REG_OFS_AXIS(chan->address),
0165                     val / 4);
0166     case IIO_CHAN_INFO_SAMP_FREQ:
0167         n = div_s64(val * NHZ_PER_HZ + val2, ADXL345_BASE_RATE_NANO_HZ);
0168 
0169         return regmap_update_bits(data->regmap, ADXL345_REG_BW_RATE,
0170                       ADXL345_BW_RATE,
0171                       clamp_val(ilog2(n), 0,
0172                             ADXL345_BW_RATE));
0173     }
0174 
0175     return -EINVAL;
0176 }
0177 
0178 static int adxl345_write_raw_get_fmt(struct iio_dev *indio_dev,
0179                      struct iio_chan_spec const *chan,
0180                      long mask)
0181 {
0182     switch (mask) {
0183     case IIO_CHAN_INFO_CALIBBIAS:
0184         return IIO_VAL_INT;
0185     case IIO_CHAN_INFO_SAMP_FREQ:
0186         return IIO_VAL_INT_PLUS_NANO;
0187     default:
0188         return -EINVAL;
0189     }
0190 }
0191 
0192 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
0193 "0.09765625 0.1953125 0.390625 0.78125 1.5625 3.125 6.25 12.5 25 50 100 200 400 800 1600 3200"
0194 );
0195 
0196 static struct attribute *adxl345_attrs[] = {
0197     &iio_const_attr_sampling_frequency_available.dev_attr.attr,
0198     NULL
0199 };
0200 
0201 static const struct attribute_group adxl345_attrs_group = {
0202     .attrs = adxl345_attrs,
0203 };
0204 
0205 static const struct iio_info adxl345_info = {
0206     .attrs      = &adxl345_attrs_group,
0207     .read_raw   = adxl345_read_raw,
0208     .write_raw  = adxl345_write_raw,
0209     .write_raw_get_fmt  = adxl345_write_raw_get_fmt,
0210 };
0211 
0212 static int adxl345_powerup(void *regmap)
0213 {
0214     return regmap_write(regmap, ADXL345_REG_POWER_CTL, ADXL345_POWER_CTL_MEASURE);
0215 }
0216 
0217 static void adxl345_powerdown(void *regmap)
0218 {
0219     regmap_write(regmap, ADXL345_REG_POWER_CTL, ADXL345_POWER_CTL_STANDBY);
0220 }
0221 
0222 int adxl345_core_probe(struct device *dev, struct regmap *regmap)
0223 {
0224     enum adxl345_device_type type;
0225     struct adxl345_data *data;
0226     struct iio_dev *indio_dev;
0227     const char *name;
0228     u32 regval;
0229     int ret;
0230 
0231     type = (uintptr_t)device_get_match_data(dev);
0232     switch (type) {
0233     case ADXL345:
0234         name = "adxl345";
0235         break;
0236     case ADXL375:
0237         name = "adxl375";
0238         break;
0239     default:
0240         return -EINVAL;
0241     }
0242 
0243     ret = regmap_read(regmap, ADXL345_REG_DEVID, &regval);
0244     if (ret < 0)
0245         return dev_err_probe(dev, ret, "Error reading device ID\n");
0246 
0247     if (regval != ADXL345_DEVID)
0248         return dev_err_probe(dev, -ENODEV, "Invalid device ID: %x, expected %x\n",
0249                      regval, ADXL345_DEVID);
0250 
0251     indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
0252     if (!indio_dev)
0253         return -ENOMEM;
0254 
0255     data = iio_priv(indio_dev);
0256     data->regmap = regmap;
0257     data->type = type;
0258     /* Enable full-resolution mode */
0259     data->data_range = ADXL345_DATA_FORMAT_FULL_RES;
0260 
0261     ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT,
0262                data->data_range);
0263     if (ret < 0)
0264         return dev_err_probe(dev, ret, "Failed to set data range\n");
0265 
0266     indio_dev->name = name;
0267     indio_dev->info = &adxl345_info;
0268     indio_dev->modes = INDIO_DIRECT_MODE;
0269     indio_dev->channels = adxl345_channels;
0270     indio_dev->num_channels = ARRAY_SIZE(adxl345_channels);
0271 
0272     /* Enable measurement mode */
0273     ret = adxl345_powerup(data->regmap);
0274     if (ret < 0)
0275         return dev_err_probe(dev, ret, "Failed to enable measurement mode\n");
0276 
0277     ret = devm_add_action_or_reset(dev, adxl345_powerdown, data->regmap);
0278     if (ret < 0)
0279         return ret;
0280 
0281     return devm_iio_device_register(dev, indio_dev);
0282 }
0283 EXPORT_SYMBOL_NS_GPL(adxl345_core_probe, IIO_ADXL345);
0284 
0285 MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
0286 MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer core driver");
0287 MODULE_LICENSE("GPL v2");