112ed2786SPuranjay Mohan // SPDX-License-Identifier: GPL-2.0-only 212ed2786SPuranjay Mohan /* 312ed2786SPuranjay Mohan * ADXL355 3-Axis Digital Accelerometer IIO core driver 412ed2786SPuranjay Mohan * 512ed2786SPuranjay Mohan * Copyright (c) 2021 Puranjay Mohan <puranjay12@gmail.com> 612ed2786SPuranjay Mohan * 712ed2786SPuranjay Mohan * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/adxl354_adxl355.pdf 812ed2786SPuranjay Mohan */ 912ed2786SPuranjay Mohan 1012ed2786SPuranjay Mohan #include <linux/bits.h> 1112ed2786SPuranjay Mohan #include <linux/bitfield.h> 12327a0eafSPuranjay Mohan #include <linux/iio/buffer.h> 1312ed2786SPuranjay Mohan #include <linux/iio/iio.h> 14327a0eafSPuranjay Mohan #include <linux/iio/trigger.h> 15327a0eafSPuranjay Mohan #include <linux/iio/triggered_buffer.h> 16327a0eafSPuranjay Mohan #include <linux/iio/trigger_consumer.h> 1712ed2786SPuranjay Mohan #include <linux/limits.h> 1812ed2786SPuranjay Mohan #include <linux/math64.h> 1912ed2786SPuranjay Mohan #include <linux/module.h> 2012ed2786SPuranjay Mohan #include <linux/mod_devicetable.h> 21d1100dd9SPuranjay Mohan #include <linux/property.h> 2212ed2786SPuranjay Mohan #include <linux/regmap.h> 2308f5fbf0SAndy Shevchenko #include <linux/units.h> 2408f5fbf0SAndy Shevchenko 2512ed2786SPuranjay Mohan #include <asm/unaligned.h> 2612ed2786SPuranjay Mohan 2712ed2786SPuranjay Mohan #include "adxl355.h" 2812ed2786SPuranjay Mohan 2912ed2786SPuranjay Mohan /* ADXL355 Register Definitions */ 3012ed2786SPuranjay Mohan #define ADXL355_DEVID_AD_REG 0x00 3112ed2786SPuranjay Mohan #define ADXL355_DEVID_MST_REG 0x01 3212ed2786SPuranjay Mohan #define ADXL355_PARTID_REG 0x02 3312ed2786SPuranjay Mohan #define ADXL355_STATUS_REG 0x04 3412ed2786SPuranjay Mohan #define ADXL355_FIFO_ENTRIES_REG 0x05 3512ed2786SPuranjay Mohan #define ADXL355_TEMP2_REG 0x06 3612ed2786SPuranjay Mohan #define ADXL355_XDATA3_REG 0x08 3712ed2786SPuranjay Mohan #define ADXL355_YDATA3_REG 0x0B 3812ed2786SPuranjay Mohan #define ADXL355_ZDATA3_REG 0x0E 3912ed2786SPuranjay Mohan #define ADXL355_FIFO_DATA_REG 0x11 4012ed2786SPuranjay Mohan #define ADXL355_OFFSET_X_H_REG 0x1E 4112ed2786SPuranjay Mohan #define ADXL355_OFFSET_Y_H_REG 0x20 4212ed2786SPuranjay Mohan #define ADXL355_OFFSET_Z_H_REG 0x22 4312ed2786SPuranjay Mohan #define ADXL355_ACT_EN_REG 0x24 4412ed2786SPuranjay Mohan #define ADXL355_ACT_THRESH_H_REG 0x25 4512ed2786SPuranjay Mohan #define ADXL355_ACT_THRESH_L_REG 0x26 4612ed2786SPuranjay Mohan #define ADXL355_ACT_COUNT_REG 0x27 4712ed2786SPuranjay Mohan #define ADXL355_FILTER_REG 0x28 4812ed2786SPuranjay Mohan #define ADXL355_FILTER_ODR_MSK GENMASK(3, 0) 4912ed2786SPuranjay Mohan #define ADXL355_FILTER_HPF_MSK GENMASK(6, 4) 5012ed2786SPuranjay Mohan #define ADXL355_FIFO_SAMPLES_REG 0x29 5112ed2786SPuranjay Mohan #define ADXL355_INT_MAP_REG 0x2A 5212ed2786SPuranjay Mohan #define ADXL355_SYNC_REG 0x2B 5312ed2786SPuranjay Mohan #define ADXL355_RANGE_REG 0x2C 5412ed2786SPuranjay Mohan #define ADXL355_POWER_CTL_REG 0x2D 5512ed2786SPuranjay Mohan #define ADXL355_POWER_CTL_MODE_MSK GENMASK(1, 0) 56327a0eafSPuranjay Mohan #define ADXL355_POWER_CTL_DRDY_MSK BIT(2) 5712ed2786SPuranjay Mohan #define ADXL355_SELF_TEST_REG 0x2E 5812ed2786SPuranjay Mohan #define ADXL355_RESET_REG 0x2F 5912ed2786SPuranjay Mohan 6012ed2786SPuranjay Mohan #define ADXL355_DEVID_AD_VAL 0xAD 6112ed2786SPuranjay Mohan #define ADXL355_DEVID_MST_VAL 0x1D 6212ed2786SPuranjay Mohan #define ADXL355_PARTID_VAL 0xED 6312ed2786SPuranjay Mohan #define ADXL355_RESET_CODE 0x52 6412ed2786SPuranjay Mohan 6512ed2786SPuranjay Mohan static const struct regmap_range adxl355_read_reg_range[] = { 6612ed2786SPuranjay Mohan regmap_reg_range(ADXL355_DEVID_AD_REG, ADXL355_FIFO_DATA_REG), 6712ed2786SPuranjay Mohan regmap_reg_range(ADXL355_OFFSET_X_H_REG, ADXL355_SELF_TEST_REG), 6812ed2786SPuranjay Mohan }; 6912ed2786SPuranjay Mohan 7012ed2786SPuranjay Mohan const struct regmap_access_table adxl355_readable_regs_tbl = { 7112ed2786SPuranjay Mohan .yes_ranges = adxl355_read_reg_range, 7212ed2786SPuranjay Mohan .n_yes_ranges = ARRAY_SIZE(adxl355_read_reg_range), 7312ed2786SPuranjay Mohan }; 74fe2fe330SJonathan Cameron EXPORT_SYMBOL_NS_GPL(adxl355_readable_regs_tbl, IIO_ADXL355); 7512ed2786SPuranjay Mohan 7612ed2786SPuranjay Mohan static const struct regmap_range adxl355_write_reg_range[] = { 7712ed2786SPuranjay Mohan regmap_reg_range(ADXL355_OFFSET_X_H_REG, ADXL355_RESET_REG), 7812ed2786SPuranjay Mohan }; 7912ed2786SPuranjay Mohan 8012ed2786SPuranjay Mohan const struct regmap_access_table adxl355_writeable_regs_tbl = { 8112ed2786SPuranjay Mohan .yes_ranges = adxl355_write_reg_range, 8212ed2786SPuranjay Mohan .n_yes_ranges = ARRAY_SIZE(adxl355_write_reg_range), 8312ed2786SPuranjay Mohan }; 84fe2fe330SJonathan Cameron EXPORT_SYMBOL_NS_GPL(adxl355_writeable_regs_tbl, IIO_ADXL355); 8512ed2786SPuranjay Mohan 8612ed2786SPuranjay Mohan enum adxl355_op_mode { 8712ed2786SPuranjay Mohan ADXL355_MEASUREMENT, 8812ed2786SPuranjay Mohan ADXL355_STANDBY, 8912ed2786SPuranjay Mohan ADXL355_TEMP_OFF, 9012ed2786SPuranjay Mohan }; 9112ed2786SPuranjay Mohan 9212ed2786SPuranjay Mohan enum adxl355_odr { 9312ed2786SPuranjay Mohan ADXL355_ODR_4000HZ, 9412ed2786SPuranjay Mohan ADXL355_ODR_2000HZ, 9512ed2786SPuranjay Mohan ADXL355_ODR_1000HZ, 9612ed2786SPuranjay Mohan ADXL355_ODR_500HZ, 9712ed2786SPuranjay Mohan ADXL355_ODR_250HZ, 9812ed2786SPuranjay Mohan ADXL355_ODR_125HZ, 9912ed2786SPuranjay Mohan ADXL355_ODR_62_5HZ, 10012ed2786SPuranjay Mohan ADXL355_ODR_31_25HZ, 10112ed2786SPuranjay Mohan ADXL355_ODR_15_625HZ, 10212ed2786SPuranjay Mohan ADXL355_ODR_7_813HZ, 10312ed2786SPuranjay Mohan ADXL355_ODR_3_906HZ, 10412ed2786SPuranjay Mohan }; 10512ed2786SPuranjay Mohan 10612ed2786SPuranjay Mohan enum adxl355_hpf_3db { 10712ed2786SPuranjay Mohan ADXL355_HPF_OFF, 10812ed2786SPuranjay Mohan ADXL355_HPF_24_7, 10912ed2786SPuranjay Mohan ADXL355_HPF_6_2084, 11012ed2786SPuranjay Mohan ADXL355_HPF_1_5545, 11112ed2786SPuranjay Mohan ADXL355_HPF_0_3862, 11212ed2786SPuranjay Mohan ADXL355_HPF_0_0954, 11312ed2786SPuranjay Mohan ADXL355_HPF_0_0238, 11412ed2786SPuranjay Mohan }; 11512ed2786SPuranjay Mohan 11612ed2786SPuranjay Mohan static const int adxl355_odr_table[][2] = { 11712ed2786SPuranjay Mohan [0] = {4000, 0}, 11812ed2786SPuranjay Mohan [1] = {2000, 0}, 11912ed2786SPuranjay Mohan [2] = {1000, 0}, 12012ed2786SPuranjay Mohan [3] = {500, 0}, 12112ed2786SPuranjay Mohan [4] = {250, 0}, 12212ed2786SPuranjay Mohan [5] = {125, 0}, 12312ed2786SPuranjay Mohan [6] = {62, 500000}, 12412ed2786SPuranjay Mohan [7] = {31, 250000}, 12512ed2786SPuranjay Mohan [8] = {15, 625000}, 12612ed2786SPuranjay Mohan [9] = {7, 813000}, 12712ed2786SPuranjay Mohan [10] = {3, 906000}, 12812ed2786SPuranjay Mohan }; 12912ed2786SPuranjay Mohan 13012ed2786SPuranjay Mohan static const int adxl355_hpf_3db_multipliers[] = { 13112ed2786SPuranjay Mohan 0, 13212ed2786SPuranjay Mohan 247000, 13312ed2786SPuranjay Mohan 62084, 13412ed2786SPuranjay Mohan 15545, 13512ed2786SPuranjay Mohan 3862, 13612ed2786SPuranjay Mohan 954, 13712ed2786SPuranjay Mohan 238, 13812ed2786SPuranjay Mohan }; 13912ed2786SPuranjay Mohan 14012ed2786SPuranjay Mohan enum adxl355_chans { 14112ed2786SPuranjay Mohan chan_x, chan_y, chan_z, 14212ed2786SPuranjay Mohan }; 14312ed2786SPuranjay Mohan 14412ed2786SPuranjay Mohan struct adxl355_chan_info { 14512ed2786SPuranjay Mohan u8 data_reg; 14612ed2786SPuranjay Mohan u8 offset_reg; 14712ed2786SPuranjay Mohan }; 14812ed2786SPuranjay Mohan 14912ed2786SPuranjay Mohan static const struct adxl355_chan_info adxl355_chans[] = { 15012ed2786SPuranjay Mohan [chan_x] = { 15112ed2786SPuranjay Mohan .data_reg = ADXL355_XDATA3_REG, 15212ed2786SPuranjay Mohan .offset_reg = ADXL355_OFFSET_X_H_REG 15312ed2786SPuranjay Mohan }, 15412ed2786SPuranjay Mohan [chan_y] = { 15512ed2786SPuranjay Mohan .data_reg = ADXL355_YDATA3_REG, 15612ed2786SPuranjay Mohan .offset_reg = ADXL355_OFFSET_Y_H_REG 15712ed2786SPuranjay Mohan }, 15812ed2786SPuranjay Mohan [chan_z] = { 15912ed2786SPuranjay Mohan .data_reg = ADXL355_ZDATA3_REG, 16012ed2786SPuranjay Mohan .offset_reg = ADXL355_OFFSET_Z_H_REG 16112ed2786SPuranjay Mohan }, 16212ed2786SPuranjay Mohan }; 16312ed2786SPuranjay Mohan 16412ed2786SPuranjay Mohan struct adxl355_data { 16512ed2786SPuranjay Mohan struct regmap *regmap; 16612ed2786SPuranjay Mohan struct device *dev; 16712ed2786SPuranjay Mohan struct mutex lock; /* lock to protect op_mode */ 16812ed2786SPuranjay Mohan enum adxl355_op_mode op_mode; 16912ed2786SPuranjay Mohan enum adxl355_odr odr; 17012ed2786SPuranjay Mohan enum adxl355_hpf_3db hpf_3db; 17112ed2786SPuranjay Mohan int calibbias[3]; 17212ed2786SPuranjay Mohan int adxl355_hpf_3db_table[7][2]; 173327a0eafSPuranjay Mohan struct iio_trigger *dready_trig; 174327a0eafSPuranjay Mohan union { 175327a0eafSPuranjay Mohan u8 transf_buf[3]; 176327a0eafSPuranjay Mohan struct { 177327a0eafSPuranjay Mohan u8 buf[14]; 178327a0eafSPuranjay Mohan s64 ts; 179327a0eafSPuranjay Mohan } buffer; 180*46403dcfSJonathan Cameron } __aligned(IIO_DMA_MINALIGN); 18112ed2786SPuranjay Mohan }; 18212ed2786SPuranjay Mohan 18312ed2786SPuranjay Mohan static int adxl355_set_op_mode(struct adxl355_data *data, 18412ed2786SPuranjay Mohan enum adxl355_op_mode op_mode) 18512ed2786SPuranjay Mohan { 18612ed2786SPuranjay Mohan int ret; 18712ed2786SPuranjay Mohan 18812ed2786SPuranjay Mohan if (data->op_mode == op_mode) 18912ed2786SPuranjay Mohan return 0; 19012ed2786SPuranjay Mohan 19112ed2786SPuranjay Mohan ret = regmap_update_bits(data->regmap, ADXL355_POWER_CTL_REG, 19212ed2786SPuranjay Mohan ADXL355_POWER_CTL_MODE_MSK, op_mode); 19312ed2786SPuranjay Mohan if (ret) 19412ed2786SPuranjay Mohan return ret; 19512ed2786SPuranjay Mohan 19612ed2786SPuranjay Mohan data->op_mode = op_mode; 19712ed2786SPuranjay Mohan 19812ed2786SPuranjay Mohan return ret; 19912ed2786SPuranjay Mohan } 20012ed2786SPuranjay Mohan 201327a0eafSPuranjay Mohan static int adxl355_data_rdy_trigger_set_state(struct iio_trigger *trig, 202327a0eafSPuranjay Mohan bool state) 203327a0eafSPuranjay Mohan { 204327a0eafSPuranjay Mohan struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 205327a0eafSPuranjay Mohan struct adxl355_data *data = iio_priv(indio_dev); 206327a0eafSPuranjay Mohan int ret; 207327a0eafSPuranjay Mohan 208327a0eafSPuranjay Mohan mutex_lock(&data->lock); 209327a0eafSPuranjay Mohan ret = regmap_update_bits(data->regmap, ADXL355_POWER_CTL_REG, 210327a0eafSPuranjay Mohan ADXL355_POWER_CTL_DRDY_MSK, 211327a0eafSPuranjay Mohan FIELD_PREP(ADXL355_POWER_CTL_DRDY_MSK, 212327a0eafSPuranjay Mohan state ? 0 : 1)); 213327a0eafSPuranjay Mohan mutex_unlock(&data->lock); 214327a0eafSPuranjay Mohan 215327a0eafSPuranjay Mohan return ret; 216327a0eafSPuranjay Mohan } 217327a0eafSPuranjay Mohan 21812ed2786SPuranjay Mohan static void adxl355_fill_3db_frequency_table(struct adxl355_data *data) 21912ed2786SPuranjay Mohan { 22012ed2786SPuranjay Mohan u32 multiplier; 22112ed2786SPuranjay Mohan u64 div, rem; 22212ed2786SPuranjay Mohan u64 odr; 22312ed2786SPuranjay Mohan int i; 22412ed2786SPuranjay Mohan 22512ed2786SPuranjay Mohan odr = mul_u64_u32_shr(adxl355_odr_table[data->odr][0], MEGA, 0) + 22612ed2786SPuranjay Mohan adxl355_odr_table[data->odr][1]; 22712ed2786SPuranjay Mohan 22812ed2786SPuranjay Mohan for (i = 0; i < ARRAY_SIZE(adxl355_hpf_3db_multipliers); i++) { 22912ed2786SPuranjay Mohan multiplier = adxl355_hpf_3db_multipliers[i]; 23012ed2786SPuranjay Mohan div = div64_u64_rem(mul_u64_u32_shr(odr, multiplier, 0), 23112ed2786SPuranjay Mohan TERA * 100, &rem); 23212ed2786SPuranjay Mohan 23312ed2786SPuranjay Mohan data->adxl355_hpf_3db_table[i][0] = div; 23412ed2786SPuranjay Mohan data->adxl355_hpf_3db_table[i][1] = div_u64(rem, MEGA * 100); 23512ed2786SPuranjay Mohan } 23612ed2786SPuranjay Mohan } 23712ed2786SPuranjay Mohan 23812ed2786SPuranjay Mohan static int adxl355_setup(struct adxl355_data *data) 23912ed2786SPuranjay Mohan { 24012ed2786SPuranjay Mohan unsigned int regval; 24112ed2786SPuranjay Mohan int ret; 24212ed2786SPuranjay Mohan 24312ed2786SPuranjay Mohan ret = regmap_read(data->regmap, ADXL355_DEVID_AD_REG, ®val); 24412ed2786SPuranjay Mohan if (ret) 24512ed2786SPuranjay Mohan return ret; 24612ed2786SPuranjay Mohan 24712ed2786SPuranjay Mohan if (regval != ADXL355_DEVID_AD_VAL) { 24812ed2786SPuranjay Mohan dev_err(data->dev, "Invalid ADI ID 0x%02x\n", regval); 24912ed2786SPuranjay Mohan return -ENODEV; 25012ed2786SPuranjay Mohan } 25112ed2786SPuranjay Mohan 25212ed2786SPuranjay Mohan ret = regmap_read(data->regmap, ADXL355_DEVID_MST_REG, ®val); 25312ed2786SPuranjay Mohan if (ret) 25412ed2786SPuranjay Mohan return ret; 25512ed2786SPuranjay Mohan 25612ed2786SPuranjay Mohan if (regval != ADXL355_DEVID_MST_VAL) { 25712ed2786SPuranjay Mohan dev_err(data->dev, "Invalid MEMS ID 0x%02x\n", regval); 25812ed2786SPuranjay Mohan return -ENODEV; 25912ed2786SPuranjay Mohan } 26012ed2786SPuranjay Mohan 26112ed2786SPuranjay Mohan ret = regmap_read(data->regmap, ADXL355_PARTID_REG, ®val); 26212ed2786SPuranjay Mohan if (ret) 26312ed2786SPuranjay Mohan return ret; 26412ed2786SPuranjay Mohan 26512ed2786SPuranjay Mohan if (regval != ADXL355_PARTID_VAL) { 26612ed2786SPuranjay Mohan dev_err(data->dev, "Invalid DEV ID 0x%02x\n", regval); 26712ed2786SPuranjay Mohan return -ENODEV; 26812ed2786SPuranjay Mohan } 26912ed2786SPuranjay Mohan 27012ed2786SPuranjay Mohan /* 27112ed2786SPuranjay Mohan * Perform a software reset to make sure the device is in a consistent 27212ed2786SPuranjay Mohan * state after start-up. 27312ed2786SPuranjay Mohan */ 27412ed2786SPuranjay Mohan ret = regmap_write(data->regmap, ADXL355_RESET_REG, ADXL355_RESET_CODE); 27512ed2786SPuranjay Mohan if (ret) 27612ed2786SPuranjay Mohan return ret; 27712ed2786SPuranjay Mohan 278327a0eafSPuranjay Mohan ret = regmap_update_bits(data->regmap, ADXL355_POWER_CTL_REG, 279327a0eafSPuranjay Mohan ADXL355_POWER_CTL_DRDY_MSK, 280327a0eafSPuranjay Mohan FIELD_PREP(ADXL355_POWER_CTL_DRDY_MSK, 1)); 281327a0eafSPuranjay Mohan if (ret) 282327a0eafSPuranjay Mohan return ret; 283327a0eafSPuranjay Mohan 28412ed2786SPuranjay Mohan adxl355_fill_3db_frequency_table(data); 28512ed2786SPuranjay Mohan 28612ed2786SPuranjay Mohan return adxl355_set_op_mode(data, ADXL355_MEASUREMENT); 28712ed2786SPuranjay Mohan } 28812ed2786SPuranjay Mohan 28912ed2786SPuranjay Mohan static int adxl355_get_temp_data(struct adxl355_data *data, u8 addr) 29012ed2786SPuranjay Mohan { 29112ed2786SPuranjay Mohan return regmap_bulk_read(data->regmap, addr, data->transf_buf, 2); 29212ed2786SPuranjay Mohan } 29312ed2786SPuranjay Mohan 29412ed2786SPuranjay Mohan static int adxl355_read_axis(struct adxl355_data *data, u8 addr) 29512ed2786SPuranjay Mohan { 29612ed2786SPuranjay Mohan int ret; 29712ed2786SPuranjay Mohan 29812ed2786SPuranjay Mohan ret = regmap_bulk_read(data->regmap, addr, data->transf_buf, 29912ed2786SPuranjay Mohan ARRAY_SIZE(data->transf_buf)); 30086ff6cb1SPuranjay Mohan if (ret) 30112ed2786SPuranjay Mohan return ret; 30212ed2786SPuranjay Mohan 30312ed2786SPuranjay Mohan return get_unaligned_be24(data->transf_buf); 30412ed2786SPuranjay Mohan } 30512ed2786SPuranjay Mohan 30612ed2786SPuranjay Mohan static int adxl355_find_match(const int (*freq_tbl)[2], const int n, 30712ed2786SPuranjay Mohan const int val, const int val2) 30812ed2786SPuranjay Mohan { 30912ed2786SPuranjay Mohan int i; 31012ed2786SPuranjay Mohan 31112ed2786SPuranjay Mohan for (i = 0; i < n; i++) { 31212ed2786SPuranjay Mohan if (freq_tbl[i][0] == val && freq_tbl[i][1] == val2) 31312ed2786SPuranjay Mohan return i; 31412ed2786SPuranjay Mohan } 31512ed2786SPuranjay Mohan 31612ed2786SPuranjay Mohan return -EINVAL; 31712ed2786SPuranjay Mohan } 31812ed2786SPuranjay Mohan 31912ed2786SPuranjay Mohan static int adxl355_set_odr(struct adxl355_data *data, 32012ed2786SPuranjay Mohan enum adxl355_odr odr) 32112ed2786SPuranjay Mohan { 32212ed2786SPuranjay Mohan int ret; 32312ed2786SPuranjay Mohan 32412ed2786SPuranjay Mohan mutex_lock(&data->lock); 32512ed2786SPuranjay Mohan 32612ed2786SPuranjay Mohan if (data->odr == odr) { 32712ed2786SPuranjay Mohan mutex_unlock(&data->lock); 32812ed2786SPuranjay Mohan return 0; 32912ed2786SPuranjay Mohan } 33012ed2786SPuranjay Mohan 33112ed2786SPuranjay Mohan ret = adxl355_set_op_mode(data, ADXL355_STANDBY); 33286ff6cb1SPuranjay Mohan if (ret) 33312ed2786SPuranjay Mohan goto err_unlock; 33412ed2786SPuranjay Mohan 33512ed2786SPuranjay Mohan ret = regmap_update_bits(data->regmap, ADXL355_FILTER_REG, 33612ed2786SPuranjay Mohan ADXL355_FILTER_ODR_MSK, 33712ed2786SPuranjay Mohan FIELD_PREP(ADXL355_FILTER_ODR_MSK, odr)); 33886ff6cb1SPuranjay Mohan if (ret) 33912ed2786SPuranjay Mohan goto err_set_opmode; 34012ed2786SPuranjay Mohan 34112ed2786SPuranjay Mohan data->odr = odr; 34212ed2786SPuranjay Mohan adxl355_fill_3db_frequency_table(data); 34312ed2786SPuranjay Mohan 34412ed2786SPuranjay Mohan ret = adxl355_set_op_mode(data, ADXL355_MEASUREMENT); 34512ed2786SPuranjay Mohan if (ret) 34612ed2786SPuranjay Mohan goto err_set_opmode; 34712ed2786SPuranjay Mohan 34812ed2786SPuranjay Mohan mutex_unlock(&data->lock); 34912ed2786SPuranjay Mohan return 0; 35012ed2786SPuranjay Mohan 35112ed2786SPuranjay Mohan err_set_opmode: 35212ed2786SPuranjay Mohan adxl355_set_op_mode(data, ADXL355_MEASUREMENT); 35312ed2786SPuranjay Mohan err_unlock: 35412ed2786SPuranjay Mohan mutex_unlock(&data->lock); 35512ed2786SPuranjay Mohan return ret; 35612ed2786SPuranjay Mohan } 35712ed2786SPuranjay Mohan 35812ed2786SPuranjay Mohan static int adxl355_set_hpf_3db(struct adxl355_data *data, 35912ed2786SPuranjay Mohan enum adxl355_hpf_3db hpf) 36012ed2786SPuranjay Mohan { 36112ed2786SPuranjay Mohan int ret; 36212ed2786SPuranjay Mohan 36312ed2786SPuranjay Mohan mutex_lock(&data->lock); 36412ed2786SPuranjay Mohan 36512ed2786SPuranjay Mohan if (data->hpf_3db == hpf) { 36612ed2786SPuranjay Mohan mutex_unlock(&data->lock); 36712ed2786SPuranjay Mohan return 0; 36812ed2786SPuranjay Mohan } 36912ed2786SPuranjay Mohan 37012ed2786SPuranjay Mohan ret = adxl355_set_op_mode(data, ADXL355_STANDBY); 37186ff6cb1SPuranjay Mohan if (ret) 37212ed2786SPuranjay Mohan goto err_unlock; 37312ed2786SPuranjay Mohan 37412ed2786SPuranjay Mohan ret = regmap_update_bits(data->regmap, ADXL355_FILTER_REG, 37512ed2786SPuranjay Mohan ADXL355_FILTER_HPF_MSK, 37612ed2786SPuranjay Mohan FIELD_PREP(ADXL355_FILTER_HPF_MSK, hpf)); 37712ed2786SPuranjay Mohan if (ret) 37812ed2786SPuranjay Mohan goto err_set_opmode; 37912ed2786SPuranjay Mohan 38012ed2786SPuranjay Mohan data->hpf_3db = hpf; 38112ed2786SPuranjay Mohan 38212ed2786SPuranjay Mohan ret = adxl355_set_op_mode(data, ADXL355_MEASUREMENT); 38312ed2786SPuranjay Mohan if (ret) 38412ed2786SPuranjay Mohan goto err_set_opmode; 38512ed2786SPuranjay Mohan 38612ed2786SPuranjay Mohan mutex_unlock(&data->lock); 38712ed2786SPuranjay Mohan return 0; 38812ed2786SPuranjay Mohan 38912ed2786SPuranjay Mohan err_set_opmode: 39012ed2786SPuranjay Mohan adxl355_set_op_mode(data, ADXL355_MEASUREMENT); 39112ed2786SPuranjay Mohan err_unlock: 39212ed2786SPuranjay Mohan mutex_unlock(&data->lock); 39312ed2786SPuranjay Mohan return ret; 39412ed2786SPuranjay Mohan } 39512ed2786SPuranjay Mohan 39612ed2786SPuranjay Mohan static int adxl355_set_calibbias(struct adxl355_data *data, 39712ed2786SPuranjay Mohan enum adxl355_chans chan, int calibbias) 39812ed2786SPuranjay Mohan { 39912ed2786SPuranjay Mohan int ret; 40012ed2786SPuranjay Mohan 40112ed2786SPuranjay Mohan mutex_lock(&data->lock); 40212ed2786SPuranjay Mohan 40312ed2786SPuranjay Mohan ret = adxl355_set_op_mode(data, ADXL355_STANDBY); 40486ff6cb1SPuranjay Mohan if (ret) 40512ed2786SPuranjay Mohan goto err_unlock; 40612ed2786SPuranjay Mohan 40712ed2786SPuranjay Mohan put_unaligned_be16(calibbias, data->transf_buf); 40812ed2786SPuranjay Mohan ret = regmap_bulk_write(data->regmap, 40912ed2786SPuranjay Mohan adxl355_chans[chan].offset_reg, 41012ed2786SPuranjay Mohan data->transf_buf, 2); 41112ed2786SPuranjay Mohan if (ret) 41212ed2786SPuranjay Mohan goto err_set_opmode; 41312ed2786SPuranjay Mohan 41412ed2786SPuranjay Mohan data->calibbias[chan] = calibbias; 41512ed2786SPuranjay Mohan 41612ed2786SPuranjay Mohan ret = adxl355_set_op_mode(data, ADXL355_MEASUREMENT); 41712ed2786SPuranjay Mohan if (ret) 41812ed2786SPuranjay Mohan goto err_set_opmode; 41912ed2786SPuranjay Mohan 42012ed2786SPuranjay Mohan mutex_unlock(&data->lock); 42112ed2786SPuranjay Mohan return 0; 42212ed2786SPuranjay Mohan 42312ed2786SPuranjay Mohan err_set_opmode: 42412ed2786SPuranjay Mohan adxl355_set_op_mode(data, ADXL355_MEASUREMENT); 42512ed2786SPuranjay Mohan err_unlock: 42612ed2786SPuranjay Mohan mutex_unlock(&data->lock); 42712ed2786SPuranjay Mohan return ret; 42812ed2786SPuranjay Mohan } 42912ed2786SPuranjay Mohan 43012ed2786SPuranjay Mohan static int adxl355_read_raw(struct iio_dev *indio_dev, 43112ed2786SPuranjay Mohan struct iio_chan_spec const *chan, 43212ed2786SPuranjay Mohan int *val, int *val2, long mask) 43312ed2786SPuranjay Mohan { 43412ed2786SPuranjay Mohan struct adxl355_data *data = iio_priv(indio_dev); 43512ed2786SPuranjay Mohan int ret; 43612ed2786SPuranjay Mohan 43712ed2786SPuranjay Mohan switch (mask) { 43812ed2786SPuranjay Mohan case IIO_CHAN_INFO_RAW: 43912ed2786SPuranjay Mohan switch (chan->type) { 44012ed2786SPuranjay Mohan case IIO_TEMP: 44112ed2786SPuranjay Mohan ret = adxl355_get_temp_data(data, chan->address); 44212ed2786SPuranjay Mohan if (ret < 0) 44312ed2786SPuranjay Mohan return ret; 44412ed2786SPuranjay Mohan *val = get_unaligned_be16(data->transf_buf); 44512ed2786SPuranjay Mohan 44612ed2786SPuranjay Mohan return IIO_VAL_INT; 44712ed2786SPuranjay Mohan case IIO_ACCEL: 44812ed2786SPuranjay Mohan ret = adxl355_read_axis(data, adxl355_chans[ 44912ed2786SPuranjay Mohan chan->address].data_reg); 45012ed2786SPuranjay Mohan if (ret < 0) 45112ed2786SPuranjay Mohan return ret; 45212ed2786SPuranjay Mohan *val = sign_extend32(ret >> chan->scan_type.shift, 45312ed2786SPuranjay Mohan chan->scan_type.realbits - 1); 45412ed2786SPuranjay Mohan return IIO_VAL_INT; 45512ed2786SPuranjay Mohan default: 45612ed2786SPuranjay Mohan return -EINVAL; 45712ed2786SPuranjay Mohan } 45812ed2786SPuranjay Mohan 45912ed2786SPuranjay Mohan case IIO_CHAN_INFO_SCALE: 46012ed2786SPuranjay Mohan switch (chan->type) { 46112ed2786SPuranjay Mohan /* 46212ed2786SPuranjay Mohan * The datasheet defines an intercept of 1885 LSB at 25 degC 46312ed2786SPuranjay Mohan * and a slope of -9.05 LSB/C. The following formula can be used 46412ed2786SPuranjay Mohan * to find the temperature: 46512ed2786SPuranjay Mohan * Temp = ((RAW - 1885)/(-9.05)) + 25 but this doesn't follow 46612ed2786SPuranjay Mohan * the format of the IIO which is Temp = (RAW + OFFSET) * SCALE. 46712ed2786SPuranjay Mohan * Hence using some rearranging we get the scale as -110.497238 46812ed2786SPuranjay Mohan * and offset as -2111.25. 46912ed2786SPuranjay Mohan */ 47012ed2786SPuranjay Mohan case IIO_TEMP: 47112ed2786SPuranjay Mohan *val = -110; 47212ed2786SPuranjay Mohan *val2 = 497238; 47312ed2786SPuranjay Mohan return IIO_VAL_INT_PLUS_MICRO; 47412ed2786SPuranjay Mohan /* 47512ed2786SPuranjay Mohan * At +/- 2g with 20-bit resolution, scale is given in datasheet 47612ed2786SPuranjay Mohan * as 3.9ug/LSB = 0.0000039 * 9.80665 = 0.00003824593 m/s^2. 47712ed2786SPuranjay Mohan */ 47812ed2786SPuranjay Mohan case IIO_ACCEL: 47912ed2786SPuranjay Mohan *val = 0; 48012ed2786SPuranjay Mohan *val2 = 38245; 48112ed2786SPuranjay Mohan return IIO_VAL_INT_PLUS_NANO; 48212ed2786SPuranjay Mohan default: 48312ed2786SPuranjay Mohan return -EINVAL; 48412ed2786SPuranjay Mohan } 48512ed2786SPuranjay Mohan case IIO_CHAN_INFO_OFFSET: 48612ed2786SPuranjay Mohan *val = -2111; 48712ed2786SPuranjay Mohan *val2 = 250000; 48812ed2786SPuranjay Mohan return IIO_VAL_INT_PLUS_MICRO; 48912ed2786SPuranjay Mohan case IIO_CHAN_INFO_CALIBBIAS: 49012ed2786SPuranjay Mohan *val = sign_extend32(data->calibbias[chan->address], 15); 49112ed2786SPuranjay Mohan return IIO_VAL_INT; 49212ed2786SPuranjay Mohan case IIO_CHAN_INFO_SAMP_FREQ: 49312ed2786SPuranjay Mohan *val = adxl355_odr_table[data->odr][0]; 49412ed2786SPuranjay Mohan *val2 = adxl355_odr_table[data->odr][1]; 49512ed2786SPuranjay Mohan return IIO_VAL_INT_PLUS_MICRO; 49612ed2786SPuranjay Mohan case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: 49712ed2786SPuranjay Mohan *val = data->adxl355_hpf_3db_table[data->hpf_3db][0]; 49812ed2786SPuranjay Mohan *val2 = data->adxl355_hpf_3db_table[data->hpf_3db][1]; 49912ed2786SPuranjay Mohan return IIO_VAL_INT_PLUS_MICRO; 50012ed2786SPuranjay Mohan default: 50112ed2786SPuranjay Mohan return -EINVAL; 50212ed2786SPuranjay Mohan } 50312ed2786SPuranjay Mohan } 50412ed2786SPuranjay Mohan 50512ed2786SPuranjay Mohan static int adxl355_write_raw(struct iio_dev *indio_dev, 50612ed2786SPuranjay Mohan struct iio_chan_spec const *chan, 50712ed2786SPuranjay Mohan int val, int val2, long mask) 50812ed2786SPuranjay Mohan { 50912ed2786SPuranjay Mohan struct adxl355_data *data = iio_priv(indio_dev); 51012ed2786SPuranjay Mohan int odr_idx, hpf_idx, calibbias; 51112ed2786SPuranjay Mohan 51212ed2786SPuranjay Mohan switch (mask) { 51312ed2786SPuranjay Mohan case IIO_CHAN_INFO_SAMP_FREQ: 51412ed2786SPuranjay Mohan odr_idx = adxl355_find_match(adxl355_odr_table, 51512ed2786SPuranjay Mohan ARRAY_SIZE(adxl355_odr_table), 51612ed2786SPuranjay Mohan val, val2); 51712ed2786SPuranjay Mohan if (odr_idx < 0) 51812ed2786SPuranjay Mohan return odr_idx; 51912ed2786SPuranjay Mohan 52012ed2786SPuranjay Mohan return adxl355_set_odr(data, odr_idx); 52112ed2786SPuranjay Mohan case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: 52212ed2786SPuranjay Mohan hpf_idx = adxl355_find_match(data->adxl355_hpf_3db_table, 52312ed2786SPuranjay Mohan ARRAY_SIZE(data->adxl355_hpf_3db_table), 52412ed2786SPuranjay Mohan val, val2); 52512ed2786SPuranjay Mohan if (hpf_idx < 0) 52612ed2786SPuranjay Mohan return hpf_idx; 52712ed2786SPuranjay Mohan 52812ed2786SPuranjay Mohan return adxl355_set_hpf_3db(data, hpf_idx); 52912ed2786SPuranjay Mohan case IIO_CHAN_INFO_CALIBBIAS: 53012ed2786SPuranjay Mohan calibbias = clamp_t(int, val, S16_MIN, S16_MAX); 53112ed2786SPuranjay Mohan 53212ed2786SPuranjay Mohan return adxl355_set_calibbias(data, chan->address, calibbias); 53312ed2786SPuranjay Mohan default: 53412ed2786SPuranjay Mohan return -EINVAL; 53512ed2786SPuranjay Mohan } 53612ed2786SPuranjay Mohan } 53712ed2786SPuranjay Mohan 53812ed2786SPuranjay Mohan static int adxl355_read_avail(struct iio_dev *indio_dev, 53912ed2786SPuranjay Mohan struct iio_chan_spec const *chan, 54012ed2786SPuranjay Mohan const int **vals, int *type, int *length, 54112ed2786SPuranjay Mohan long mask) 54212ed2786SPuranjay Mohan { 54312ed2786SPuranjay Mohan struct adxl355_data *data = iio_priv(indio_dev); 54412ed2786SPuranjay Mohan 54512ed2786SPuranjay Mohan switch (mask) { 54612ed2786SPuranjay Mohan case IIO_CHAN_INFO_SAMP_FREQ: 54712ed2786SPuranjay Mohan *vals = (const int *)adxl355_odr_table; 54812ed2786SPuranjay Mohan *type = IIO_VAL_INT_PLUS_MICRO; 54912ed2786SPuranjay Mohan /* Values are stored in a 2D matrix */ 55012ed2786SPuranjay Mohan *length = ARRAY_SIZE(adxl355_odr_table) * 2; 55112ed2786SPuranjay Mohan 55212ed2786SPuranjay Mohan return IIO_AVAIL_LIST; 55312ed2786SPuranjay Mohan case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: 55412ed2786SPuranjay Mohan *vals = (const int *)data->adxl355_hpf_3db_table; 55512ed2786SPuranjay Mohan *type = IIO_VAL_INT_PLUS_MICRO; 55612ed2786SPuranjay Mohan /* Values are stored in a 2D matrix */ 55712ed2786SPuranjay Mohan *length = ARRAY_SIZE(data->adxl355_hpf_3db_table) * 2; 55812ed2786SPuranjay Mohan 55912ed2786SPuranjay Mohan return IIO_AVAIL_LIST; 56012ed2786SPuranjay Mohan default: 56112ed2786SPuranjay Mohan return -EINVAL; 56212ed2786SPuranjay Mohan } 56312ed2786SPuranjay Mohan } 56412ed2786SPuranjay Mohan 565327a0eafSPuranjay Mohan static const unsigned long adxl355_avail_scan_masks[] = { 566327a0eafSPuranjay Mohan GENMASK(3, 0), 567327a0eafSPuranjay Mohan 0 568327a0eafSPuranjay Mohan }; 569327a0eafSPuranjay Mohan 57012ed2786SPuranjay Mohan static const struct iio_info adxl355_info = { 57112ed2786SPuranjay Mohan .read_raw = adxl355_read_raw, 57212ed2786SPuranjay Mohan .write_raw = adxl355_write_raw, 57312ed2786SPuranjay Mohan .read_avail = &adxl355_read_avail, 57412ed2786SPuranjay Mohan }; 57512ed2786SPuranjay Mohan 576327a0eafSPuranjay Mohan static const struct iio_trigger_ops adxl355_trigger_ops = { 577327a0eafSPuranjay Mohan .set_trigger_state = &adxl355_data_rdy_trigger_set_state, 578327a0eafSPuranjay Mohan .validate_device = &iio_trigger_validate_own_device, 579327a0eafSPuranjay Mohan }; 580327a0eafSPuranjay Mohan 581327a0eafSPuranjay Mohan static irqreturn_t adxl355_trigger_handler(int irq, void *p) 582327a0eafSPuranjay Mohan { 583327a0eafSPuranjay Mohan struct iio_poll_func *pf = p; 584327a0eafSPuranjay Mohan struct iio_dev *indio_dev = pf->indio_dev; 585327a0eafSPuranjay Mohan struct adxl355_data *data = iio_priv(indio_dev); 586327a0eafSPuranjay Mohan int ret; 587327a0eafSPuranjay Mohan 588327a0eafSPuranjay Mohan mutex_lock(&data->lock); 589327a0eafSPuranjay Mohan 590327a0eafSPuranjay Mohan /* 591327a0eafSPuranjay Mohan * data->buffer is used both for triggered buffer support 592327a0eafSPuranjay Mohan * and read/write_raw(), hence, it has to be zeroed here before usage. 593327a0eafSPuranjay Mohan */ 594327a0eafSPuranjay Mohan data->buffer.buf[0] = 0; 595327a0eafSPuranjay Mohan 596327a0eafSPuranjay Mohan /* 597327a0eafSPuranjay Mohan * The acceleration data is 24 bits and big endian. It has to be saved 598327a0eafSPuranjay Mohan * in 32 bits, hence, it is saved in the 2nd byte of the 4 byte buffer. 599327a0eafSPuranjay Mohan * The buf array is 14 bytes as it includes 3x4=12 bytes for 600327a0eafSPuranjay Mohan * accelaration data of x, y, and z axis. It also includes 2 bytes for 601327a0eafSPuranjay Mohan * temperature data. 602327a0eafSPuranjay Mohan */ 603327a0eafSPuranjay Mohan ret = regmap_bulk_read(data->regmap, ADXL355_XDATA3_REG, 604327a0eafSPuranjay Mohan &data->buffer.buf[1], 3); 605327a0eafSPuranjay Mohan if (ret) 606327a0eafSPuranjay Mohan goto out_unlock_notify; 607327a0eafSPuranjay Mohan 608327a0eafSPuranjay Mohan ret = regmap_bulk_read(data->regmap, ADXL355_YDATA3_REG, 609327a0eafSPuranjay Mohan &data->buffer.buf[5], 3); 610327a0eafSPuranjay Mohan if (ret) 611327a0eafSPuranjay Mohan goto out_unlock_notify; 612327a0eafSPuranjay Mohan 613327a0eafSPuranjay Mohan ret = regmap_bulk_read(data->regmap, ADXL355_ZDATA3_REG, 614327a0eafSPuranjay Mohan &data->buffer.buf[9], 3); 615327a0eafSPuranjay Mohan if (ret) 616327a0eafSPuranjay Mohan goto out_unlock_notify; 617327a0eafSPuranjay Mohan 618327a0eafSPuranjay Mohan ret = regmap_bulk_read(data->regmap, ADXL355_TEMP2_REG, 619327a0eafSPuranjay Mohan &data->buffer.buf[12], 2); 620327a0eafSPuranjay Mohan if (ret) 621327a0eafSPuranjay Mohan goto out_unlock_notify; 622327a0eafSPuranjay Mohan 623327a0eafSPuranjay Mohan iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer, 624327a0eafSPuranjay Mohan pf->timestamp); 625327a0eafSPuranjay Mohan 626327a0eafSPuranjay Mohan out_unlock_notify: 627327a0eafSPuranjay Mohan mutex_unlock(&data->lock); 628327a0eafSPuranjay Mohan iio_trigger_notify_done(indio_dev->trig); 629327a0eafSPuranjay Mohan 630327a0eafSPuranjay Mohan return IRQ_HANDLED; 631327a0eafSPuranjay Mohan } 632327a0eafSPuranjay Mohan 63312ed2786SPuranjay Mohan #define ADXL355_ACCEL_CHANNEL(index, reg, axis) { \ 63412ed2786SPuranjay Mohan .type = IIO_ACCEL, \ 63512ed2786SPuranjay Mohan .address = reg, \ 63612ed2786SPuranjay Mohan .modified = 1, \ 63712ed2786SPuranjay Mohan .channel2 = IIO_MOD_##axis, \ 63812ed2786SPuranjay Mohan .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 63912ed2786SPuranjay Mohan BIT(IIO_CHAN_INFO_CALIBBIAS), \ 64012ed2786SPuranjay Mohan .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 64112ed2786SPuranjay Mohan BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 64212ed2786SPuranjay Mohan BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \ 64312ed2786SPuranjay Mohan .info_mask_shared_by_type_available = \ 64412ed2786SPuranjay Mohan BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 64512ed2786SPuranjay Mohan BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \ 646327a0eafSPuranjay Mohan .scan_index = index, \ 64712ed2786SPuranjay Mohan .scan_type = { \ 64812ed2786SPuranjay Mohan .sign = 's', \ 64912ed2786SPuranjay Mohan .realbits = 20, \ 65012ed2786SPuranjay Mohan .storagebits = 32, \ 65112ed2786SPuranjay Mohan .shift = 4, \ 65212ed2786SPuranjay Mohan .endianness = IIO_BE, \ 65312ed2786SPuranjay Mohan } \ 65412ed2786SPuranjay Mohan } 65512ed2786SPuranjay Mohan 65612ed2786SPuranjay Mohan static const struct iio_chan_spec adxl355_channels[] = { 65712ed2786SPuranjay Mohan ADXL355_ACCEL_CHANNEL(0, chan_x, X), 65812ed2786SPuranjay Mohan ADXL355_ACCEL_CHANNEL(1, chan_y, Y), 65912ed2786SPuranjay Mohan ADXL355_ACCEL_CHANNEL(2, chan_z, Z), 66012ed2786SPuranjay Mohan { 66112ed2786SPuranjay Mohan .type = IIO_TEMP, 66212ed2786SPuranjay Mohan .address = ADXL355_TEMP2_REG, 66312ed2786SPuranjay Mohan .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 66412ed2786SPuranjay Mohan BIT(IIO_CHAN_INFO_SCALE) | 66512ed2786SPuranjay Mohan BIT(IIO_CHAN_INFO_OFFSET), 666327a0eafSPuranjay Mohan .scan_index = 3, 66712ed2786SPuranjay Mohan .scan_type = { 66812ed2786SPuranjay Mohan .sign = 's', 66912ed2786SPuranjay Mohan .realbits = 12, 67012ed2786SPuranjay Mohan .storagebits = 16, 67112ed2786SPuranjay Mohan .endianness = IIO_BE, 67212ed2786SPuranjay Mohan }, 67312ed2786SPuranjay Mohan }, 674327a0eafSPuranjay Mohan IIO_CHAN_SOFT_TIMESTAMP(4), 67512ed2786SPuranjay Mohan }; 67612ed2786SPuranjay Mohan 677327a0eafSPuranjay Mohan static int adxl355_probe_trigger(struct iio_dev *indio_dev, int irq) 678327a0eafSPuranjay Mohan { 679327a0eafSPuranjay Mohan struct adxl355_data *data = iio_priv(indio_dev); 680327a0eafSPuranjay Mohan int ret; 681327a0eafSPuranjay Mohan 682327a0eafSPuranjay Mohan data->dready_trig = devm_iio_trigger_alloc(data->dev, "%s-dev%d", 683327a0eafSPuranjay Mohan indio_dev->name, 684327a0eafSPuranjay Mohan iio_device_id(indio_dev)); 685327a0eafSPuranjay Mohan if (!data->dready_trig) 686327a0eafSPuranjay Mohan return -ENOMEM; 687327a0eafSPuranjay Mohan 688327a0eafSPuranjay Mohan data->dready_trig->ops = &adxl355_trigger_ops; 689327a0eafSPuranjay Mohan iio_trigger_set_drvdata(data->dready_trig, indio_dev); 690327a0eafSPuranjay Mohan 691327a0eafSPuranjay Mohan ret = devm_request_irq(data->dev, irq, 692327a0eafSPuranjay Mohan &iio_trigger_generic_data_rdy_poll, 693327a0eafSPuranjay Mohan IRQF_ONESHOT, "adxl355_irq", data->dready_trig); 694327a0eafSPuranjay Mohan if (ret) 695327a0eafSPuranjay Mohan return dev_err_probe(data->dev, ret, "request irq %d failed\n", 696327a0eafSPuranjay Mohan irq); 697327a0eafSPuranjay Mohan 698327a0eafSPuranjay Mohan ret = devm_iio_trigger_register(data->dev, data->dready_trig); 699327a0eafSPuranjay Mohan if (ret) { 700327a0eafSPuranjay Mohan dev_err(data->dev, "iio trigger register failed\n"); 701327a0eafSPuranjay Mohan return ret; 702327a0eafSPuranjay Mohan } 703327a0eafSPuranjay Mohan 704327a0eafSPuranjay Mohan indio_dev->trig = iio_trigger_get(data->dready_trig); 705327a0eafSPuranjay Mohan 706327a0eafSPuranjay Mohan return 0; 707327a0eafSPuranjay Mohan } 708327a0eafSPuranjay Mohan 70912ed2786SPuranjay Mohan int adxl355_core_probe(struct device *dev, struct regmap *regmap, 71012ed2786SPuranjay Mohan const char *name) 71112ed2786SPuranjay Mohan { 71212ed2786SPuranjay Mohan struct adxl355_data *data; 71312ed2786SPuranjay Mohan struct iio_dev *indio_dev; 71412ed2786SPuranjay Mohan int ret; 715327a0eafSPuranjay Mohan int irq; 71612ed2786SPuranjay Mohan 71712ed2786SPuranjay Mohan indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 71812ed2786SPuranjay Mohan if (!indio_dev) 71912ed2786SPuranjay Mohan return -ENOMEM; 72012ed2786SPuranjay Mohan 72112ed2786SPuranjay Mohan data = iio_priv(indio_dev); 72212ed2786SPuranjay Mohan data->regmap = regmap; 72312ed2786SPuranjay Mohan data->dev = dev; 72412ed2786SPuranjay Mohan data->op_mode = ADXL355_STANDBY; 72512ed2786SPuranjay Mohan mutex_init(&data->lock); 72612ed2786SPuranjay Mohan 72712ed2786SPuranjay Mohan indio_dev->name = name; 72812ed2786SPuranjay Mohan indio_dev->info = &adxl355_info; 72912ed2786SPuranjay Mohan indio_dev->modes = INDIO_DIRECT_MODE; 73012ed2786SPuranjay Mohan indio_dev->channels = adxl355_channels; 73112ed2786SPuranjay Mohan indio_dev->num_channels = ARRAY_SIZE(adxl355_channels); 732327a0eafSPuranjay Mohan indio_dev->available_scan_masks = adxl355_avail_scan_masks; 73312ed2786SPuranjay Mohan 73412ed2786SPuranjay Mohan ret = adxl355_setup(data); 73586ff6cb1SPuranjay Mohan if (ret) { 73612ed2786SPuranjay Mohan dev_err(dev, "ADXL355 setup failed\n"); 73712ed2786SPuranjay Mohan return ret; 73812ed2786SPuranjay Mohan } 73912ed2786SPuranjay Mohan 740327a0eafSPuranjay Mohan ret = devm_iio_triggered_buffer_setup(dev, indio_dev, 741327a0eafSPuranjay Mohan &iio_pollfunc_store_time, 742327a0eafSPuranjay Mohan &adxl355_trigger_handler, NULL); 743327a0eafSPuranjay Mohan if (ret) { 744327a0eafSPuranjay Mohan dev_err(dev, "iio triggered buffer setup failed\n"); 745327a0eafSPuranjay Mohan return ret; 746327a0eafSPuranjay Mohan } 747327a0eafSPuranjay Mohan 748d1100dd9SPuranjay Mohan irq = fwnode_irq_get_byname(dev_fwnode(dev), "DRDY"); 749327a0eafSPuranjay Mohan if (irq > 0) { 750327a0eafSPuranjay Mohan ret = adxl355_probe_trigger(indio_dev, irq); 751327a0eafSPuranjay Mohan if (ret) 752327a0eafSPuranjay Mohan return ret; 753327a0eafSPuranjay Mohan } 754327a0eafSPuranjay Mohan 75512ed2786SPuranjay Mohan return devm_iio_device_register(dev, indio_dev); 75612ed2786SPuranjay Mohan } 757fe2fe330SJonathan Cameron EXPORT_SYMBOL_NS_GPL(adxl355_core_probe, IIO_ADXL355); 75812ed2786SPuranjay Mohan 75912ed2786SPuranjay Mohan MODULE_AUTHOR("Puranjay Mohan <puranjay12@gmail.com>"); 76012ed2786SPuranjay Mohan MODULE_DESCRIPTION("ADXL355 3-Axis Digital Accelerometer core driver"); 76112ed2786SPuranjay Mohan MODULE_LICENSE("GPL v2"); 762