Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ADXL355 3-Axis Digital Accelerometer IIO core driver
0004  *
0005  * Copyright (c) 2021 Puranjay Mohan <puranjay12@gmail.com>
0006  *
0007  * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/adxl354_adxl355.pdf
0008  */
0009 
0010 #include <linux/bits.h>
0011 #include <linux/bitfield.h>
0012 #include <linux/iio/buffer.h>
0013 #include <linux/iio/iio.h>
0014 #include <linux/iio/trigger.h>
0015 #include <linux/iio/triggered_buffer.h>
0016 #include <linux/iio/trigger_consumer.h>
0017 #include <linux/limits.h>
0018 #include <linux/math64.h>
0019 #include <linux/module.h>
0020 #include <linux/mod_devicetable.h>
0021 #include <linux/property.h>
0022 #include <linux/regmap.h>
0023 #include <linux/units.h>
0024 
0025 #include <asm/unaligned.h>
0026 
0027 #include "adxl355.h"
0028 
0029 /* ADXL355 Register Definitions */
0030 #define ADXL355_DEVID_AD_REG        0x00
0031 #define ADXL355_DEVID_MST_REG       0x01
0032 #define ADXL355_PARTID_REG      0x02
0033 #define ADXL355_STATUS_REG      0x04
0034 #define ADXL355_FIFO_ENTRIES_REG    0x05
0035 #define ADXL355_TEMP2_REG       0x06
0036 #define ADXL355_XDATA3_REG      0x08
0037 #define ADXL355_YDATA3_REG      0x0B
0038 #define ADXL355_ZDATA3_REG      0x0E
0039 #define ADXL355_FIFO_DATA_REG       0x11
0040 #define ADXL355_OFFSET_X_H_REG      0x1E
0041 #define ADXL355_OFFSET_Y_H_REG      0x20
0042 #define ADXL355_OFFSET_Z_H_REG      0x22
0043 #define ADXL355_ACT_EN_REG      0x24
0044 #define ADXL355_ACT_THRESH_H_REG    0x25
0045 #define ADXL355_ACT_THRESH_L_REG    0x26
0046 #define ADXL355_ACT_COUNT_REG       0x27
0047 #define ADXL355_FILTER_REG      0x28
0048 #define  ADXL355_FILTER_ODR_MSK GENMASK(3, 0)
0049 #define  ADXL355_FILTER_HPF_MSK GENMASK(6, 4)
0050 #define ADXL355_FIFO_SAMPLES_REG    0x29
0051 #define ADXL355_INT_MAP_REG     0x2A
0052 #define ADXL355_SYNC_REG        0x2B
0053 #define ADXL355_RANGE_REG       0x2C
0054 #define ADXL355_POWER_CTL_REG       0x2D
0055 #define  ADXL355_POWER_CTL_MODE_MSK GENMASK(1, 0)
0056 #define  ADXL355_POWER_CTL_DRDY_MSK BIT(2)
0057 #define ADXL355_SELF_TEST_REG       0x2E
0058 #define ADXL355_RESET_REG       0x2F
0059 
0060 #define ADXL355_DEVID_AD_VAL        0xAD
0061 #define ADXL355_DEVID_MST_VAL       0x1D
0062 #define ADXL355_PARTID_VAL      0xED
0063 #define ADXL355_RESET_CODE      0x52
0064 
0065 static const struct regmap_range adxl355_read_reg_range[] = {
0066     regmap_reg_range(ADXL355_DEVID_AD_REG, ADXL355_FIFO_DATA_REG),
0067     regmap_reg_range(ADXL355_OFFSET_X_H_REG, ADXL355_SELF_TEST_REG),
0068 };
0069 
0070 const struct regmap_access_table adxl355_readable_regs_tbl = {
0071     .yes_ranges = adxl355_read_reg_range,
0072     .n_yes_ranges = ARRAY_SIZE(adxl355_read_reg_range),
0073 };
0074 EXPORT_SYMBOL_NS_GPL(adxl355_readable_regs_tbl, IIO_ADXL355);
0075 
0076 static const struct regmap_range adxl355_write_reg_range[] = {
0077     regmap_reg_range(ADXL355_OFFSET_X_H_REG, ADXL355_RESET_REG),
0078 };
0079 
0080 const struct regmap_access_table adxl355_writeable_regs_tbl = {
0081     .yes_ranges = adxl355_write_reg_range,
0082     .n_yes_ranges = ARRAY_SIZE(adxl355_write_reg_range),
0083 };
0084 EXPORT_SYMBOL_NS_GPL(adxl355_writeable_regs_tbl, IIO_ADXL355);
0085 
0086 enum adxl355_op_mode {
0087     ADXL355_MEASUREMENT,
0088     ADXL355_STANDBY,
0089     ADXL355_TEMP_OFF,
0090 };
0091 
0092 enum adxl355_odr {
0093     ADXL355_ODR_4000HZ,
0094     ADXL355_ODR_2000HZ,
0095     ADXL355_ODR_1000HZ,
0096     ADXL355_ODR_500HZ,
0097     ADXL355_ODR_250HZ,
0098     ADXL355_ODR_125HZ,
0099     ADXL355_ODR_62_5HZ,
0100     ADXL355_ODR_31_25HZ,
0101     ADXL355_ODR_15_625HZ,
0102     ADXL355_ODR_7_813HZ,
0103     ADXL355_ODR_3_906HZ,
0104 };
0105 
0106 enum adxl355_hpf_3db {
0107     ADXL355_HPF_OFF,
0108     ADXL355_HPF_24_7,
0109     ADXL355_HPF_6_2084,
0110     ADXL355_HPF_1_5545,
0111     ADXL355_HPF_0_3862,
0112     ADXL355_HPF_0_0954,
0113     ADXL355_HPF_0_0238,
0114 };
0115 
0116 static const int adxl355_odr_table[][2] = {
0117     [0] = {4000, 0},
0118     [1] = {2000, 0},
0119     [2] = {1000, 0},
0120     [3] = {500, 0},
0121     [4] = {250, 0},
0122     [5] = {125, 0},
0123     [6] = {62, 500000},
0124     [7] = {31, 250000},
0125     [8] = {15, 625000},
0126     [9] = {7, 813000},
0127     [10] = {3, 906000},
0128 };
0129 
0130 static const int adxl355_hpf_3db_multipliers[] = {
0131     0,
0132     247000,
0133     62084,
0134     15545,
0135     3862,
0136     954,
0137     238,
0138 };
0139 
0140 enum adxl355_chans {
0141     chan_x, chan_y, chan_z,
0142 };
0143 
0144 struct adxl355_chan_info {
0145     u8 data_reg;
0146     u8 offset_reg;
0147 };
0148 
0149 static const struct adxl355_chan_info adxl355_chans[] = {
0150     [chan_x] = {
0151         .data_reg = ADXL355_XDATA3_REG,
0152         .offset_reg = ADXL355_OFFSET_X_H_REG
0153     },
0154     [chan_y] = {
0155         .data_reg = ADXL355_YDATA3_REG,
0156         .offset_reg = ADXL355_OFFSET_Y_H_REG
0157     },
0158     [chan_z] = {
0159         .data_reg = ADXL355_ZDATA3_REG,
0160         .offset_reg = ADXL355_OFFSET_Z_H_REG
0161     },
0162 };
0163 
0164 struct adxl355_data {
0165     struct regmap *regmap;
0166     struct device *dev;
0167     struct mutex lock; /* lock to protect op_mode */
0168     enum adxl355_op_mode op_mode;
0169     enum adxl355_odr odr;
0170     enum adxl355_hpf_3db hpf_3db;
0171     int calibbias[3];
0172     int adxl355_hpf_3db_table[7][2];
0173     struct iio_trigger *dready_trig;
0174     union {
0175         u8 transf_buf[3];
0176         struct {
0177             u8 buf[14];
0178             s64 ts;
0179         } buffer;
0180     } __aligned(IIO_DMA_MINALIGN);
0181 };
0182 
0183 static int adxl355_set_op_mode(struct adxl355_data *data,
0184                    enum adxl355_op_mode op_mode)
0185 {
0186     int ret;
0187 
0188     if (data->op_mode == op_mode)
0189         return 0;
0190 
0191     ret = regmap_update_bits(data->regmap, ADXL355_POWER_CTL_REG,
0192                  ADXL355_POWER_CTL_MODE_MSK, op_mode);
0193     if (ret)
0194         return ret;
0195 
0196     data->op_mode = op_mode;
0197 
0198     return ret;
0199 }
0200 
0201 static int adxl355_data_rdy_trigger_set_state(struct iio_trigger *trig,
0202                           bool state)
0203 {
0204     struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
0205     struct adxl355_data *data = iio_priv(indio_dev);
0206     int ret;
0207 
0208     mutex_lock(&data->lock);
0209     ret = regmap_update_bits(data->regmap, ADXL355_POWER_CTL_REG,
0210                  ADXL355_POWER_CTL_DRDY_MSK,
0211                  FIELD_PREP(ADXL355_POWER_CTL_DRDY_MSK,
0212                         state ? 0 : 1));
0213     mutex_unlock(&data->lock);
0214 
0215     return ret;
0216 }
0217 
0218 static void adxl355_fill_3db_frequency_table(struct adxl355_data *data)
0219 {
0220     u32 multiplier;
0221     u64 div, rem;
0222     u64 odr;
0223     int i;
0224 
0225     odr = mul_u64_u32_shr(adxl355_odr_table[data->odr][0], MEGA, 0) +
0226                   adxl355_odr_table[data->odr][1];
0227 
0228     for (i = 0; i < ARRAY_SIZE(adxl355_hpf_3db_multipliers); i++) {
0229         multiplier = adxl355_hpf_3db_multipliers[i];
0230         div = div64_u64_rem(mul_u64_u32_shr(odr, multiplier, 0),
0231                     TERA * 100, &rem);
0232 
0233         data->adxl355_hpf_3db_table[i][0] = div;
0234         data->adxl355_hpf_3db_table[i][1] = div_u64(rem, MEGA * 100);
0235     }
0236 }
0237 
0238 static int adxl355_setup(struct adxl355_data *data)
0239 {
0240     unsigned int regval;
0241     int ret;
0242 
0243     ret = regmap_read(data->regmap, ADXL355_DEVID_AD_REG, &regval);
0244     if (ret)
0245         return ret;
0246 
0247     if (regval != ADXL355_DEVID_AD_VAL) {
0248         dev_err(data->dev, "Invalid ADI ID 0x%02x\n", regval);
0249         return -ENODEV;
0250     }
0251 
0252     ret = regmap_read(data->regmap, ADXL355_DEVID_MST_REG, &regval);
0253     if (ret)
0254         return ret;
0255 
0256     if (regval != ADXL355_DEVID_MST_VAL) {
0257         dev_err(data->dev, "Invalid MEMS ID 0x%02x\n", regval);
0258         return -ENODEV;
0259     }
0260 
0261     ret = regmap_read(data->regmap, ADXL355_PARTID_REG, &regval);
0262     if (ret)
0263         return ret;
0264 
0265     if (regval != ADXL355_PARTID_VAL) {
0266         dev_err(data->dev, "Invalid DEV ID 0x%02x\n", regval);
0267         return -ENODEV;
0268     }
0269 
0270     /*
0271      * Perform a software reset to make sure the device is in a consistent
0272      * state after start-up.
0273      */
0274     ret = regmap_write(data->regmap, ADXL355_RESET_REG, ADXL355_RESET_CODE);
0275     if (ret)
0276         return ret;
0277 
0278     ret = regmap_update_bits(data->regmap, ADXL355_POWER_CTL_REG,
0279                  ADXL355_POWER_CTL_DRDY_MSK,
0280                  FIELD_PREP(ADXL355_POWER_CTL_DRDY_MSK, 1));
0281     if (ret)
0282         return ret;
0283 
0284     adxl355_fill_3db_frequency_table(data);
0285 
0286     return adxl355_set_op_mode(data, ADXL355_MEASUREMENT);
0287 }
0288 
0289 static int adxl355_get_temp_data(struct adxl355_data *data, u8 addr)
0290 {
0291     return regmap_bulk_read(data->regmap, addr, data->transf_buf, 2);
0292 }
0293 
0294 static int adxl355_read_axis(struct adxl355_data *data, u8 addr)
0295 {
0296     int ret;
0297 
0298     ret = regmap_bulk_read(data->regmap, addr, data->transf_buf,
0299                    ARRAY_SIZE(data->transf_buf));
0300     if (ret)
0301         return ret;
0302 
0303     return get_unaligned_be24(data->transf_buf);
0304 }
0305 
0306 static int adxl355_find_match(const int (*freq_tbl)[2], const int n,
0307                   const int val, const int val2)
0308 {
0309     int i;
0310 
0311     for (i = 0; i < n; i++) {
0312         if (freq_tbl[i][0] == val && freq_tbl[i][1] == val2)
0313             return i;
0314     }
0315 
0316     return -EINVAL;
0317 }
0318 
0319 static int adxl355_set_odr(struct adxl355_data *data,
0320                enum adxl355_odr odr)
0321 {
0322     int ret;
0323 
0324     mutex_lock(&data->lock);
0325 
0326     if (data->odr == odr) {
0327         mutex_unlock(&data->lock);
0328         return 0;
0329     }
0330 
0331     ret = adxl355_set_op_mode(data, ADXL355_STANDBY);
0332     if (ret)
0333         goto err_unlock;
0334 
0335     ret = regmap_update_bits(data->regmap, ADXL355_FILTER_REG,
0336                  ADXL355_FILTER_ODR_MSK,
0337                  FIELD_PREP(ADXL355_FILTER_ODR_MSK, odr));
0338     if (ret)
0339         goto err_set_opmode;
0340 
0341     data->odr = odr;
0342     adxl355_fill_3db_frequency_table(data);
0343 
0344     ret = adxl355_set_op_mode(data, ADXL355_MEASUREMENT);
0345     if (ret)
0346         goto err_set_opmode;
0347 
0348     mutex_unlock(&data->lock);
0349     return 0;
0350 
0351 err_set_opmode:
0352     adxl355_set_op_mode(data, ADXL355_MEASUREMENT);
0353 err_unlock:
0354     mutex_unlock(&data->lock);
0355     return ret;
0356 }
0357 
0358 static int adxl355_set_hpf_3db(struct adxl355_data *data,
0359                    enum adxl355_hpf_3db hpf)
0360 {
0361     int ret;
0362 
0363     mutex_lock(&data->lock);
0364 
0365     if (data->hpf_3db == hpf) {
0366         mutex_unlock(&data->lock);
0367         return 0;
0368     }
0369 
0370     ret = adxl355_set_op_mode(data, ADXL355_STANDBY);
0371     if (ret)
0372         goto err_unlock;
0373 
0374     ret = regmap_update_bits(data->regmap, ADXL355_FILTER_REG,
0375                  ADXL355_FILTER_HPF_MSK,
0376                  FIELD_PREP(ADXL355_FILTER_HPF_MSK, hpf));
0377     if (ret)
0378         goto err_set_opmode;
0379 
0380     data->hpf_3db = hpf;
0381 
0382     ret = adxl355_set_op_mode(data, ADXL355_MEASUREMENT);
0383     if (ret)
0384         goto err_set_opmode;
0385 
0386     mutex_unlock(&data->lock);
0387     return 0;
0388 
0389 err_set_opmode:
0390     adxl355_set_op_mode(data, ADXL355_MEASUREMENT);
0391 err_unlock:
0392     mutex_unlock(&data->lock);
0393     return ret;
0394 }
0395 
0396 static int adxl355_set_calibbias(struct adxl355_data *data,
0397                  enum adxl355_chans chan, int calibbias)
0398 {
0399     int ret;
0400 
0401     mutex_lock(&data->lock);
0402 
0403     ret = adxl355_set_op_mode(data, ADXL355_STANDBY);
0404     if (ret)
0405         goto err_unlock;
0406 
0407     put_unaligned_be16(calibbias, data->transf_buf);
0408     ret = regmap_bulk_write(data->regmap,
0409                 adxl355_chans[chan].offset_reg,
0410                 data->transf_buf, 2);
0411     if (ret)
0412         goto err_set_opmode;
0413 
0414     data->calibbias[chan] = calibbias;
0415 
0416     ret = adxl355_set_op_mode(data, ADXL355_MEASUREMENT);
0417     if (ret)
0418         goto err_set_opmode;
0419 
0420     mutex_unlock(&data->lock);
0421     return 0;
0422 
0423 err_set_opmode:
0424     adxl355_set_op_mode(data, ADXL355_MEASUREMENT);
0425 err_unlock:
0426     mutex_unlock(&data->lock);
0427     return ret;
0428 }
0429 
0430 static int adxl355_read_raw(struct iio_dev *indio_dev,
0431                 struct iio_chan_spec const *chan,
0432                 int *val, int *val2, long mask)
0433 {
0434     struct adxl355_data *data = iio_priv(indio_dev);
0435     int ret;
0436 
0437     switch (mask) {
0438     case IIO_CHAN_INFO_RAW:
0439         switch (chan->type) {
0440         case IIO_TEMP:
0441             ret = adxl355_get_temp_data(data, chan->address);
0442             if (ret < 0)
0443                 return ret;
0444             *val = get_unaligned_be16(data->transf_buf);
0445 
0446             return IIO_VAL_INT;
0447         case IIO_ACCEL:
0448             ret = adxl355_read_axis(data, adxl355_chans[
0449                         chan->address].data_reg);
0450             if (ret < 0)
0451                 return ret;
0452             *val = sign_extend32(ret >> chan->scan_type.shift,
0453                          chan->scan_type.realbits - 1);
0454             return IIO_VAL_INT;
0455         default:
0456             return -EINVAL;
0457         }
0458 
0459     case IIO_CHAN_INFO_SCALE:
0460         switch (chan->type) {
0461         /*
0462          * The datasheet defines an intercept of 1885 LSB at 25 degC
0463          * and a slope of -9.05 LSB/C. The following formula can be used
0464          * to find the temperature:
0465          * Temp = ((RAW - 1885)/(-9.05)) + 25 but this doesn't follow
0466          * the format of the IIO which is Temp = (RAW + OFFSET) * SCALE.
0467          * Hence using some rearranging we get the scale as -110.497238
0468          * and offset as -2111.25.
0469          */
0470         case IIO_TEMP:
0471             *val = -110;
0472             *val2 = 497238;
0473             return IIO_VAL_INT_PLUS_MICRO;
0474         /*
0475          * At +/- 2g with 20-bit resolution, scale is given in datasheet
0476          * as 3.9ug/LSB = 0.0000039 * 9.80665 = 0.00003824593 m/s^2.
0477          */
0478         case IIO_ACCEL:
0479             *val = 0;
0480             *val2 = 38245;
0481             return IIO_VAL_INT_PLUS_NANO;
0482         default:
0483             return -EINVAL;
0484         }
0485     case IIO_CHAN_INFO_OFFSET:
0486         *val = -2111;
0487         *val2 = 250000;
0488         return IIO_VAL_INT_PLUS_MICRO;
0489     case IIO_CHAN_INFO_CALIBBIAS:
0490         *val = sign_extend32(data->calibbias[chan->address], 15);
0491         return IIO_VAL_INT;
0492     case IIO_CHAN_INFO_SAMP_FREQ:
0493         *val = adxl355_odr_table[data->odr][0];
0494         *val2 = adxl355_odr_table[data->odr][1];
0495         return IIO_VAL_INT_PLUS_MICRO;
0496     case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
0497         *val = data->adxl355_hpf_3db_table[data->hpf_3db][0];
0498         *val2 = data->adxl355_hpf_3db_table[data->hpf_3db][1];
0499         return IIO_VAL_INT_PLUS_MICRO;
0500     default:
0501         return -EINVAL;
0502     }
0503 }
0504 
0505 static int adxl355_write_raw(struct iio_dev *indio_dev,
0506                  struct iio_chan_spec const *chan,
0507                  int val, int val2, long mask)
0508 {
0509     struct adxl355_data *data = iio_priv(indio_dev);
0510     int odr_idx, hpf_idx, calibbias;
0511 
0512     switch (mask) {
0513     case IIO_CHAN_INFO_SAMP_FREQ:
0514         odr_idx = adxl355_find_match(adxl355_odr_table,
0515                          ARRAY_SIZE(adxl355_odr_table),
0516                          val, val2);
0517         if (odr_idx < 0)
0518             return odr_idx;
0519 
0520         return adxl355_set_odr(data, odr_idx);
0521     case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
0522         hpf_idx = adxl355_find_match(data->adxl355_hpf_3db_table,
0523                     ARRAY_SIZE(data->adxl355_hpf_3db_table),
0524                          val, val2);
0525         if (hpf_idx < 0)
0526             return hpf_idx;
0527 
0528         return adxl355_set_hpf_3db(data, hpf_idx);
0529     case IIO_CHAN_INFO_CALIBBIAS:
0530         calibbias = clamp_t(int, val, S16_MIN, S16_MAX);
0531 
0532         return adxl355_set_calibbias(data, chan->address, calibbias);
0533     default:
0534         return -EINVAL;
0535     }
0536 }
0537 
0538 static int adxl355_read_avail(struct iio_dev *indio_dev,
0539                   struct iio_chan_spec const *chan,
0540                   const int **vals, int *type, int *length,
0541                   long mask)
0542 {
0543     struct adxl355_data *data = iio_priv(indio_dev);
0544 
0545     switch (mask) {
0546     case IIO_CHAN_INFO_SAMP_FREQ:
0547         *vals = (const int *)adxl355_odr_table;
0548         *type = IIO_VAL_INT_PLUS_MICRO;
0549         /* Values are stored in a 2D matrix */
0550         *length = ARRAY_SIZE(adxl355_odr_table) * 2;
0551 
0552         return IIO_AVAIL_LIST;
0553     case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
0554         *vals = (const int *)data->adxl355_hpf_3db_table;
0555         *type = IIO_VAL_INT_PLUS_MICRO;
0556         /* Values are stored in a 2D matrix */
0557         *length = ARRAY_SIZE(data->adxl355_hpf_3db_table) * 2;
0558 
0559         return IIO_AVAIL_LIST;
0560     default:
0561         return -EINVAL;
0562     }
0563 }
0564 
0565 static const unsigned long adxl355_avail_scan_masks[] = {
0566     GENMASK(3, 0),
0567     0
0568 };
0569 
0570 static const struct iio_info adxl355_info = {
0571     .read_raw   = adxl355_read_raw,
0572     .write_raw  = adxl355_write_raw,
0573     .read_avail = &adxl355_read_avail,
0574 };
0575 
0576 static const struct iio_trigger_ops adxl355_trigger_ops = {
0577     .set_trigger_state = &adxl355_data_rdy_trigger_set_state,
0578     .validate_device = &iio_trigger_validate_own_device,
0579 };
0580 
0581 static irqreturn_t adxl355_trigger_handler(int irq, void *p)
0582 {
0583     struct iio_poll_func *pf = p;
0584     struct iio_dev *indio_dev = pf->indio_dev;
0585     struct adxl355_data *data = iio_priv(indio_dev);
0586     int ret;
0587 
0588     mutex_lock(&data->lock);
0589 
0590     /*
0591      * data->buffer is used both for triggered buffer support
0592      * and read/write_raw(), hence, it has to be zeroed here before usage.
0593      */
0594     data->buffer.buf[0] = 0;
0595 
0596     /*
0597      * The acceleration data is 24 bits and big endian. It has to be saved
0598      * in 32 bits, hence, it is saved in the 2nd byte of the 4 byte buffer.
0599      * The buf array is 14 bytes as it includes 3x4=12 bytes for
0600      * accelaration data of x, y, and z axis. It also includes 2 bytes for
0601      * temperature data.
0602      */
0603     ret = regmap_bulk_read(data->regmap, ADXL355_XDATA3_REG,
0604                    &data->buffer.buf[1], 3);
0605     if (ret)
0606         goto out_unlock_notify;
0607 
0608     ret = regmap_bulk_read(data->regmap, ADXL355_YDATA3_REG,
0609                    &data->buffer.buf[5], 3);
0610     if (ret)
0611         goto out_unlock_notify;
0612 
0613     ret = regmap_bulk_read(data->regmap, ADXL355_ZDATA3_REG,
0614                    &data->buffer.buf[9], 3);
0615     if (ret)
0616         goto out_unlock_notify;
0617 
0618     ret = regmap_bulk_read(data->regmap, ADXL355_TEMP2_REG,
0619                    &data->buffer.buf[12], 2);
0620     if (ret)
0621         goto out_unlock_notify;
0622 
0623     iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
0624                        pf->timestamp);
0625 
0626 out_unlock_notify:
0627     mutex_unlock(&data->lock);
0628     iio_trigger_notify_done(indio_dev->trig);
0629 
0630     return IRQ_HANDLED;
0631 }
0632 
0633 #define ADXL355_ACCEL_CHANNEL(index, reg, axis) {           \
0634     .type = IIO_ACCEL,                      \
0635     .address = reg,                         \
0636     .modified = 1,                          \
0637     .channel2 = IIO_MOD_##axis,                 \
0638     .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |          \
0639                   BIT(IIO_CHAN_INFO_CALIBBIAS),     \
0640     .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |      \
0641                     BIT(IIO_CHAN_INFO_SAMP_FREQ) |  \
0642         BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY),  \
0643     .info_mask_shared_by_type_available =               \
0644         BIT(IIO_CHAN_INFO_SAMP_FREQ) |              \
0645         BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY),  \
0646     .scan_index = index,                        \
0647     .scan_type = {                          \
0648         .sign = 's',                        \
0649         .realbits = 20,                     \
0650         .storagebits = 32,                  \
0651         .shift = 4,                     \
0652         .endianness = IIO_BE,                   \
0653     }                               \
0654 }
0655 
0656 static const struct iio_chan_spec adxl355_channels[] = {
0657     ADXL355_ACCEL_CHANNEL(0, chan_x, X),
0658     ADXL355_ACCEL_CHANNEL(1, chan_y, Y),
0659     ADXL355_ACCEL_CHANNEL(2, chan_z, Z),
0660     {
0661         .type = IIO_TEMP,
0662         .address = ADXL355_TEMP2_REG,
0663         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0664                       BIT(IIO_CHAN_INFO_SCALE) |
0665                       BIT(IIO_CHAN_INFO_OFFSET),
0666         .scan_index = 3,
0667         .scan_type = {
0668             .sign = 's',
0669             .realbits = 12,
0670             .storagebits = 16,
0671             .endianness = IIO_BE,
0672         },
0673     },
0674     IIO_CHAN_SOFT_TIMESTAMP(4),
0675 };
0676 
0677 static int adxl355_probe_trigger(struct iio_dev *indio_dev, int irq)
0678 {
0679     struct adxl355_data *data = iio_priv(indio_dev);
0680     int ret;
0681 
0682     data->dready_trig = devm_iio_trigger_alloc(data->dev, "%s-dev%d",
0683                            indio_dev->name,
0684                            iio_device_id(indio_dev));
0685     if (!data->dready_trig)
0686         return -ENOMEM;
0687 
0688     data->dready_trig->ops = &adxl355_trigger_ops;
0689     iio_trigger_set_drvdata(data->dready_trig, indio_dev);
0690 
0691     ret = devm_request_irq(data->dev, irq,
0692                    &iio_trigger_generic_data_rdy_poll,
0693                    IRQF_ONESHOT, "adxl355_irq", data->dready_trig);
0694     if (ret)
0695         return dev_err_probe(data->dev, ret, "request irq %d failed\n",
0696                      irq);
0697 
0698     ret = devm_iio_trigger_register(data->dev, data->dready_trig);
0699     if (ret) {
0700         dev_err(data->dev, "iio trigger register failed\n");
0701         return ret;
0702     }
0703 
0704     indio_dev->trig = iio_trigger_get(data->dready_trig);
0705 
0706     return 0;
0707 }
0708 
0709 int adxl355_core_probe(struct device *dev, struct regmap *regmap,
0710                const char *name)
0711 {
0712     struct adxl355_data *data;
0713     struct iio_dev *indio_dev;
0714     int ret;
0715     int irq;
0716 
0717     indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
0718     if (!indio_dev)
0719         return -ENOMEM;
0720 
0721     data = iio_priv(indio_dev);
0722     data->regmap = regmap;
0723     data->dev = dev;
0724     data->op_mode = ADXL355_STANDBY;
0725     mutex_init(&data->lock);
0726 
0727     indio_dev->name = name;
0728     indio_dev->info = &adxl355_info;
0729     indio_dev->modes = INDIO_DIRECT_MODE;
0730     indio_dev->channels = adxl355_channels;
0731     indio_dev->num_channels = ARRAY_SIZE(adxl355_channels);
0732     indio_dev->available_scan_masks = adxl355_avail_scan_masks;
0733 
0734     ret = adxl355_setup(data);
0735     if (ret) {
0736         dev_err(dev, "ADXL355 setup failed\n");
0737         return ret;
0738     }
0739 
0740     ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
0741                           &iio_pollfunc_store_time,
0742                           &adxl355_trigger_handler, NULL);
0743     if (ret) {
0744         dev_err(dev, "iio triggered buffer setup failed\n");
0745         return ret;
0746     }
0747 
0748     irq = fwnode_irq_get_byname(dev_fwnode(dev), "DRDY");
0749     if (irq > 0) {
0750         ret = adxl355_probe_trigger(indio_dev, irq);
0751         if (ret)
0752             return ret;
0753     }
0754 
0755     return devm_iio_device_register(dev, indio_dev);
0756 }
0757 EXPORT_SYMBOL_NS_GPL(adxl355_core_probe, IIO_ADXL355);
0758 
0759 MODULE_AUTHOR("Puranjay Mohan <puranjay12@gmail.com>");
0760 MODULE_DESCRIPTION("ADXL355 3-Axis Digital Accelerometer core driver");
0761 MODULE_LICENSE("GPL v2");