809 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ADXL355 3-Axis Digital Accelerometer IIO core driver4 *5 * Copyright (c) 2021 Puranjay Mohan <puranjay12@gmail.com>6 *7 * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/adxl354_adxl355.pdf8 */9 10#include <linux/bits.h>11#include <linux/bitfield.h>12#include <linux/iio/buffer.h>13#include <linux/iio/iio.h>14#include <linux/iio/trigger.h>15#include <linux/iio/triggered_buffer.h>16#include <linux/iio/trigger_consumer.h>17#include <linux/limits.h>18#include <linux/math64.h>19#include <linux/module.h>20#include <linux/mod_devicetable.h>21#include <linux/property.h>22#include <linux/regmap.h>23#include <linux/units.h>24 25#include <linux/unaligned.h>26 27#include "adxl355.h"28 29/* ADXL355 Register Definitions */30#define ADXL355_DEVID_AD_REG 0x0031#define ADXL355_DEVID_MST_REG 0x0132#define ADXL355_PARTID_REG 0x0233#define ADXL355_STATUS_REG 0x0434#define ADXL355_FIFO_ENTRIES_REG 0x0535#define ADXL355_TEMP2_REG 0x0636#define ADXL355_XDATA3_REG 0x0837#define ADXL355_YDATA3_REG 0x0B38#define ADXL355_ZDATA3_REG 0x0E39#define ADXL355_FIFO_DATA_REG 0x1140#define ADXL355_OFFSET_X_H_REG 0x1E41#define ADXL355_OFFSET_Y_H_REG 0x2042#define ADXL355_OFFSET_Z_H_REG 0x2243#define ADXL355_ACT_EN_REG 0x2444#define ADXL355_ACT_THRESH_H_REG 0x2545#define ADXL355_ACT_THRESH_L_REG 0x2646#define ADXL355_ACT_COUNT_REG 0x2747#define ADXL355_FILTER_REG 0x2848#define ADXL355_FILTER_ODR_MSK GENMASK(3, 0)49#define ADXL355_FILTER_HPF_MSK GENMASK(6, 4)50#define ADXL355_FIFO_SAMPLES_REG 0x2951#define ADXL355_INT_MAP_REG 0x2A52#define ADXL355_SYNC_REG 0x2B53#define ADXL355_RANGE_REG 0x2C54#define ADXL355_POWER_CTL_REG 0x2D55#define ADXL355_POWER_CTL_MODE_MSK GENMASK(1, 0)56#define ADXL355_POWER_CTL_DRDY_MSK BIT(2)57#define ADXL355_SELF_TEST_REG 0x2E58#define ADXL355_RESET_REG 0x2F59 60#define ADXL355_DEVID_AD_VAL 0xAD61#define ADXL355_DEVID_MST_VAL 0x1D62#define ADXL355_PARTID_VAL 0xED63#define ADXL359_PARTID_VAL 0xE964#define ADXL355_RESET_CODE 0x5265 66static const struct regmap_range adxl355_read_reg_range[] = {67 regmap_reg_range(ADXL355_DEVID_AD_REG, ADXL355_FIFO_DATA_REG),68 regmap_reg_range(ADXL355_OFFSET_X_H_REG, ADXL355_SELF_TEST_REG),69};70 71const struct regmap_access_table adxl355_readable_regs_tbl = {72 .yes_ranges = adxl355_read_reg_range,73 .n_yes_ranges = ARRAY_SIZE(adxl355_read_reg_range),74};75EXPORT_SYMBOL_NS_GPL(adxl355_readable_regs_tbl, IIO_ADXL355);76 77static const struct regmap_range adxl355_write_reg_range[] = {78 regmap_reg_range(ADXL355_OFFSET_X_H_REG, ADXL355_RESET_REG),79};80 81const struct regmap_access_table adxl355_writeable_regs_tbl = {82 .yes_ranges = adxl355_write_reg_range,83 .n_yes_ranges = ARRAY_SIZE(adxl355_write_reg_range),84};85EXPORT_SYMBOL_NS_GPL(adxl355_writeable_regs_tbl, IIO_ADXL355);86 87const struct adxl355_chip_info adxl35x_chip_info[] = {88 [ADXL355] = {89 .name = "adxl355",90 .part_id = ADXL355_PARTID_VAL,91 /*92 * At +/- 2g with 20-bit resolution, scale is given in datasheet93 * as 3.9ug/LSB = 0.0000039 * 9.80665 = 0.00003824593 m/s^2.94 */95 .accel_scale = {96 .integer = 0,97 .decimal = 38245,98 },99 /*100 * The datasheet defines an intercept of 1885 LSB at 25 degC101 * and a slope of -9.05 LSB/C. The following formula can be used102 * to find the temperature:103 * Temp = ((RAW - 1885)/(-9.05)) + 25 but this doesn't follow104 * the format of the IIO which is Temp = (RAW + OFFSET) * SCALE.105 * Hence using some rearranging we get the scale as -110.497238106 * and offset as -2111.25.107 */108 .temp_offset = {109 .integer = -2111,110 .decimal = 250000,111 },112 },113 [ADXL359] = {114 .name = "adxl359",115 .part_id = ADXL359_PARTID_VAL,116 /*117 * At +/- 10g with 20-bit resolution, scale is given in datasheet118 * as 19.5ug/LSB = 0.0000195 * 9.80665 = 0.0.00019122967 m/s^2.119 */120 .accel_scale = {121 .integer = 0,122 .decimal = 191229,123 },124 /*125 * The datasheet defines an intercept of 1852 LSB at 25 degC126 * and a slope of -9.05 LSB/C. The following formula can be used127 * to find the temperature:128 * Temp = ((RAW - 1852)/(-9.05)) + 25 but this doesn't follow129 * the format of the IIO which is Temp = (RAW + OFFSET) * SCALE.130 * Hence using some rearranging we get the scale as -110.497238131 * and offset as -2079.25.132 */133 .temp_offset = {134 .integer = -2079,135 .decimal = 250000,136 },137 },138};139EXPORT_SYMBOL_NS_GPL(adxl35x_chip_info, IIO_ADXL355);140 141enum adxl355_op_mode {142 ADXL355_MEASUREMENT,143 ADXL355_STANDBY,144 ADXL355_TEMP_OFF,145};146 147enum adxl355_odr {148 ADXL355_ODR_4000HZ,149 ADXL355_ODR_2000HZ,150 ADXL355_ODR_1000HZ,151 ADXL355_ODR_500HZ,152 ADXL355_ODR_250HZ,153 ADXL355_ODR_125HZ,154 ADXL355_ODR_62_5HZ,155 ADXL355_ODR_31_25HZ,156 ADXL355_ODR_15_625HZ,157 ADXL355_ODR_7_813HZ,158 ADXL355_ODR_3_906HZ,159};160 161enum adxl355_hpf_3db {162 ADXL355_HPF_OFF,163 ADXL355_HPF_24_7,164 ADXL355_HPF_6_2084,165 ADXL355_HPF_1_5545,166 ADXL355_HPF_0_3862,167 ADXL355_HPF_0_0954,168 ADXL355_HPF_0_0238,169};170 171static const int adxl355_odr_table[][2] = {172 [0] = {4000, 0},173 [1] = {2000, 0},174 [2] = {1000, 0},175 [3] = {500, 0},176 [4] = {250, 0},177 [5] = {125, 0},178 [6] = {62, 500000},179 [7] = {31, 250000},180 [8] = {15, 625000},181 [9] = {7, 813000},182 [10] = {3, 906000},183};184 185static const int adxl355_hpf_3db_multipliers[] = {186 0,187 247000,188 62084,189 15545,190 3862,191 954,192 238,193};194 195enum adxl355_chans {196 chan_x, chan_y, chan_z,197};198 199struct adxl355_chan_info {200 u8 data_reg;201 u8 offset_reg;202};203 204static const struct adxl355_chan_info adxl355_chans[] = {205 [chan_x] = {206 .data_reg = ADXL355_XDATA3_REG,207 .offset_reg = ADXL355_OFFSET_X_H_REG208 },209 [chan_y] = {210 .data_reg = ADXL355_YDATA3_REG,211 .offset_reg = ADXL355_OFFSET_Y_H_REG212 },213 [chan_z] = {214 .data_reg = ADXL355_ZDATA3_REG,215 .offset_reg = ADXL355_OFFSET_Z_H_REG216 },217};218 219struct adxl355_data {220 const struct adxl355_chip_info *chip_info;221 struct regmap *regmap;222 struct device *dev;223 struct mutex lock; /* lock to protect op_mode */224 enum adxl355_op_mode op_mode;225 enum adxl355_odr odr;226 enum adxl355_hpf_3db hpf_3db;227 int calibbias[3];228 int adxl355_hpf_3db_table[7][2];229 struct iio_trigger *dready_trig;230 union {231 u8 transf_buf[3];232 struct {233 u8 buf[14];234 s64 ts;235 } buffer;236 } __aligned(IIO_DMA_MINALIGN);237};238 239static int adxl355_set_op_mode(struct adxl355_data *data,240 enum adxl355_op_mode op_mode)241{242 int ret;243 244 if (data->op_mode == op_mode)245 return 0;246 247 ret = regmap_update_bits(data->regmap, ADXL355_POWER_CTL_REG,248 ADXL355_POWER_CTL_MODE_MSK, op_mode);249 if (ret)250 return ret;251 252 data->op_mode = op_mode;253 254 return ret;255}256 257static int adxl355_data_rdy_trigger_set_state(struct iio_trigger *trig,258 bool state)259{260 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);261 struct adxl355_data *data = iio_priv(indio_dev);262 int ret;263 264 mutex_lock(&data->lock);265 ret = regmap_update_bits(data->regmap, ADXL355_POWER_CTL_REG,266 ADXL355_POWER_CTL_DRDY_MSK,267 FIELD_PREP(ADXL355_POWER_CTL_DRDY_MSK,268 state ? 0 : 1));269 mutex_unlock(&data->lock);270 271 return ret;272}273 274static void adxl355_fill_3db_frequency_table(struct adxl355_data *data)275{276 u32 multiplier;277 u64 div, rem;278 u64 odr;279 int i;280 281 odr = mul_u64_u32_shr(adxl355_odr_table[data->odr][0], MEGA, 0) +282 adxl355_odr_table[data->odr][1];283 284 for (i = 0; i < ARRAY_SIZE(adxl355_hpf_3db_multipliers); i++) {285 multiplier = adxl355_hpf_3db_multipliers[i];286 div = div64_u64_rem(mul_u64_u32_shr(odr, multiplier, 0),287 TERA * 100, &rem);288 289 data->adxl355_hpf_3db_table[i][0] = div;290 data->adxl355_hpf_3db_table[i][1] = div_u64(rem, MEGA * 100);291 }292}293 294static int adxl355_setup(struct adxl355_data *data)295{296 unsigned int regval;297 int ret;298 299 ret = regmap_read(data->regmap, ADXL355_DEVID_AD_REG, ®val);300 if (ret)301 return ret;302 303 if (regval != ADXL355_DEVID_AD_VAL) {304 dev_err(data->dev, "Invalid ADI ID 0x%02x\n", regval);305 return -ENODEV;306 }307 308 ret = regmap_read(data->regmap, ADXL355_DEVID_MST_REG, ®val);309 if (ret)310 return ret;311 312 if (regval != ADXL355_DEVID_MST_VAL) {313 dev_err(data->dev, "Invalid MEMS ID 0x%02x\n", regval);314 return -ENODEV;315 }316 317 ret = regmap_read(data->regmap, ADXL355_PARTID_REG, ®val);318 if (ret)319 return ret;320 321 if (regval != ADXL355_PARTID_VAL)322 dev_warn(data->dev, "Invalid DEV ID 0x%02x\n", regval);323 324 /*325 * Perform a software reset to make sure the device is in a consistent326 * state after start-up.327 */328 ret = regmap_write(data->regmap, ADXL355_RESET_REG, ADXL355_RESET_CODE);329 if (ret)330 return ret;331 332 ret = regmap_update_bits(data->regmap, ADXL355_POWER_CTL_REG,333 ADXL355_POWER_CTL_DRDY_MSK,334 FIELD_PREP(ADXL355_POWER_CTL_DRDY_MSK, 1));335 if (ret)336 return ret;337 338 adxl355_fill_3db_frequency_table(data);339 340 return adxl355_set_op_mode(data, ADXL355_MEASUREMENT);341}342 343static int adxl355_get_temp_data(struct adxl355_data *data, u8 addr)344{345 return regmap_bulk_read(data->regmap, addr, data->transf_buf, 2);346}347 348static int adxl355_read_axis(struct adxl355_data *data, u8 addr)349{350 int ret;351 352 ret = regmap_bulk_read(data->regmap, addr, data->transf_buf,353 ARRAY_SIZE(data->transf_buf));354 if (ret)355 return ret;356 357 return get_unaligned_be24(data->transf_buf);358}359 360static int adxl355_find_match(const int (*freq_tbl)[2], const int n,361 const int val, const int val2)362{363 int i;364 365 for (i = 0; i < n; i++) {366 if (freq_tbl[i][0] == val && freq_tbl[i][1] == val2)367 return i;368 }369 370 return -EINVAL;371}372 373static int adxl355_set_odr(struct adxl355_data *data,374 enum adxl355_odr odr)375{376 int ret;377 378 mutex_lock(&data->lock);379 380 if (data->odr == odr) {381 mutex_unlock(&data->lock);382 return 0;383 }384 385 ret = adxl355_set_op_mode(data, ADXL355_STANDBY);386 if (ret)387 goto err_unlock;388 389 ret = regmap_update_bits(data->regmap, ADXL355_FILTER_REG,390 ADXL355_FILTER_ODR_MSK,391 FIELD_PREP(ADXL355_FILTER_ODR_MSK, odr));392 if (ret)393 goto err_set_opmode;394 395 data->odr = odr;396 adxl355_fill_3db_frequency_table(data);397 398 ret = adxl355_set_op_mode(data, ADXL355_MEASUREMENT);399 if (ret)400 goto err_set_opmode;401 402 mutex_unlock(&data->lock);403 return 0;404 405err_set_opmode:406 adxl355_set_op_mode(data, ADXL355_MEASUREMENT);407err_unlock:408 mutex_unlock(&data->lock);409 return ret;410}411 412static int adxl355_set_hpf_3db(struct adxl355_data *data,413 enum adxl355_hpf_3db hpf)414{415 int ret;416 417 mutex_lock(&data->lock);418 419 if (data->hpf_3db == hpf) {420 mutex_unlock(&data->lock);421 return 0;422 }423 424 ret = adxl355_set_op_mode(data, ADXL355_STANDBY);425 if (ret)426 goto err_unlock;427 428 ret = regmap_update_bits(data->regmap, ADXL355_FILTER_REG,429 ADXL355_FILTER_HPF_MSK,430 FIELD_PREP(ADXL355_FILTER_HPF_MSK, hpf));431 if (ret)432 goto err_set_opmode;433 434 data->hpf_3db = hpf;435 436 ret = adxl355_set_op_mode(data, ADXL355_MEASUREMENT);437 if (ret)438 goto err_set_opmode;439 440 mutex_unlock(&data->lock);441 return 0;442 443err_set_opmode:444 adxl355_set_op_mode(data, ADXL355_MEASUREMENT);445err_unlock:446 mutex_unlock(&data->lock);447 return ret;448}449 450static int adxl355_set_calibbias(struct adxl355_data *data,451 enum adxl355_chans chan, int calibbias)452{453 int ret;454 455 mutex_lock(&data->lock);456 457 ret = adxl355_set_op_mode(data, ADXL355_STANDBY);458 if (ret)459 goto err_unlock;460 461 put_unaligned_be16(calibbias, data->transf_buf);462 ret = regmap_bulk_write(data->regmap,463 adxl355_chans[chan].offset_reg,464 data->transf_buf, 2);465 if (ret)466 goto err_set_opmode;467 468 data->calibbias[chan] = calibbias;469 470 ret = adxl355_set_op_mode(data, ADXL355_MEASUREMENT);471 if (ret)472 goto err_set_opmode;473 474 mutex_unlock(&data->lock);475 return 0;476 477err_set_opmode:478 adxl355_set_op_mode(data, ADXL355_MEASUREMENT);479err_unlock:480 mutex_unlock(&data->lock);481 return ret;482}483 484static int adxl355_read_raw(struct iio_dev *indio_dev,485 struct iio_chan_spec const *chan,486 int *val, int *val2, long mask)487{488 struct adxl355_data *data = iio_priv(indio_dev);489 int ret;490 491 switch (mask) {492 case IIO_CHAN_INFO_RAW:493 switch (chan->type) {494 case IIO_TEMP:495 ret = adxl355_get_temp_data(data, chan->address);496 if (ret < 0)497 return ret;498 *val = get_unaligned_be16(data->transf_buf);499 500 return IIO_VAL_INT;501 case IIO_ACCEL:502 ret = adxl355_read_axis(data, adxl355_chans[503 chan->address].data_reg);504 if (ret < 0)505 return ret;506 *val = sign_extend32(ret >> chan->scan_type.shift,507 chan->scan_type.realbits - 1);508 return IIO_VAL_INT;509 default:510 return -EINVAL;511 }512 513 case IIO_CHAN_INFO_SCALE:514 switch (chan->type) {515 case IIO_TEMP:516 /*517 * Temperature scale is -110.497238.518 * See the detailed explanation in adxl35x_chip_info519 * definition above.520 */521 *val = -110;522 *val2 = 497238;523 return IIO_VAL_INT_PLUS_MICRO;524 case IIO_ACCEL:525 *val = data->chip_info->accel_scale.integer;526 *val2 = data->chip_info->accel_scale.decimal;527 return IIO_VAL_INT_PLUS_NANO;528 default:529 return -EINVAL;530 }531 case IIO_CHAN_INFO_OFFSET:532 *val = data->chip_info->temp_offset.integer;533 *val2 = data->chip_info->temp_offset.decimal;534 return IIO_VAL_INT_PLUS_MICRO;535 case IIO_CHAN_INFO_CALIBBIAS:536 *val = sign_extend32(data->calibbias[chan->address], 15);537 return IIO_VAL_INT;538 case IIO_CHAN_INFO_SAMP_FREQ:539 *val = adxl355_odr_table[data->odr][0];540 *val2 = adxl355_odr_table[data->odr][1];541 return IIO_VAL_INT_PLUS_MICRO;542 case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:543 *val = data->adxl355_hpf_3db_table[data->hpf_3db][0];544 *val2 = data->adxl355_hpf_3db_table[data->hpf_3db][1];545 return IIO_VAL_INT_PLUS_MICRO;546 default:547 return -EINVAL;548 }549}550 551static int adxl355_write_raw(struct iio_dev *indio_dev,552 struct iio_chan_spec const *chan,553 int val, int val2, long mask)554{555 struct adxl355_data *data = iio_priv(indio_dev);556 int odr_idx, hpf_idx, calibbias;557 558 switch (mask) {559 case IIO_CHAN_INFO_SAMP_FREQ:560 odr_idx = adxl355_find_match(adxl355_odr_table,561 ARRAY_SIZE(adxl355_odr_table),562 val, val2);563 if (odr_idx < 0)564 return odr_idx;565 566 return adxl355_set_odr(data, odr_idx);567 case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:568 hpf_idx = adxl355_find_match(data->adxl355_hpf_3db_table,569 ARRAY_SIZE(data->adxl355_hpf_3db_table),570 val, val2);571 if (hpf_idx < 0)572 return hpf_idx;573 574 return adxl355_set_hpf_3db(data, hpf_idx);575 case IIO_CHAN_INFO_CALIBBIAS:576 calibbias = clamp_t(int, val, S16_MIN, S16_MAX);577 578 return adxl355_set_calibbias(data, chan->address, calibbias);579 default:580 return -EINVAL;581 }582}583 584static int adxl355_read_avail(struct iio_dev *indio_dev,585 struct iio_chan_spec const *chan,586 const int **vals, int *type, int *length,587 long mask)588{589 struct adxl355_data *data = iio_priv(indio_dev);590 591 switch (mask) {592 case IIO_CHAN_INFO_SAMP_FREQ:593 *vals = (const int *)adxl355_odr_table;594 *type = IIO_VAL_INT_PLUS_MICRO;595 /* Values are stored in a 2D matrix */596 *length = ARRAY_SIZE(adxl355_odr_table) * 2;597 598 return IIO_AVAIL_LIST;599 case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:600 *vals = (const int *)data->adxl355_hpf_3db_table;601 *type = IIO_VAL_INT_PLUS_MICRO;602 /* Values are stored in a 2D matrix */603 *length = ARRAY_SIZE(data->adxl355_hpf_3db_table) * 2;604 605 return IIO_AVAIL_LIST;606 default:607 return -EINVAL;608 }609}610 611static const unsigned long adxl355_avail_scan_masks[] = {612 GENMASK(3, 0),613 0614};615 616static const struct iio_info adxl355_info = {617 .read_raw = adxl355_read_raw,618 .write_raw = adxl355_write_raw,619 .read_avail = &adxl355_read_avail,620};621 622static const struct iio_trigger_ops adxl355_trigger_ops = {623 .set_trigger_state = &adxl355_data_rdy_trigger_set_state,624 .validate_device = &iio_trigger_validate_own_device,625};626 627static irqreturn_t adxl355_trigger_handler(int irq, void *p)628{629 struct iio_poll_func *pf = p;630 struct iio_dev *indio_dev = pf->indio_dev;631 struct adxl355_data *data = iio_priv(indio_dev);632 int ret;633 634 mutex_lock(&data->lock);635 636 /*637 * data->buffer is used both for triggered buffer support638 * and read/write_raw(), hence, it has to be zeroed here before usage.639 */640 data->buffer.buf[0] = 0;641 642 /*643 * The acceleration data is 24 bits and big endian. It has to be saved644 * in 32 bits, hence, it is saved in the 2nd byte of the 4 byte buffer.645 * The buf array is 14 bytes as it includes 3x4=12 bytes for646 * accelaration data of x, y, and z axis. It also includes 2 bytes for647 * temperature data.648 */649 ret = regmap_bulk_read(data->regmap, ADXL355_XDATA3_REG,650 &data->buffer.buf[1], 3);651 if (ret)652 goto out_unlock_notify;653 654 ret = regmap_bulk_read(data->regmap, ADXL355_YDATA3_REG,655 &data->buffer.buf[5], 3);656 if (ret)657 goto out_unlock_notify;658 659 ret = regmap_bulk_read(data->regmap, ADXL355_ZDATA3_REG,660 &data->buffer.buf[9], 3);661 if (ret)662 goto out_unlock_notify;663 664 ret = regmap_bulk_read(data->regmap, ADXL355_TEMP2_REG,665 &data->buffer.buf[12], 2);666 if (ret)667 goto out_unlock_notify;668 669 iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,670 pf->timestamp);671 672out_unlock_notify:673 mutex_unlock(&data->lock);674 iio_trigger_notify_done(indio_dev->trig);675 676 return IRQ_HANDLED;677}678 679#define ADXL355_ACCEL_CHANNEL(index, reg, axis) { \680 .type = IIO_ACCEL, \681 .address = reg, \682 .modified = 1, \683 .channel2 = IIO_MOD_##axis, \684 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \685 BIT(IIO_CHAN_INFO_CALIBBIAS), \686 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \687 BIT(IIO_CHAN_INFO_SAMP_FREQ) | \688 BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \689 .info_mask_shared_by_type_available = \690 BIT(IIO_CHAN_INFO_SAMP_FREQ) | \691 BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \692 .scan_index = index, \693 .scan_type = { \694 .sign = 's', \695 .realbits = 20, \696 .storagebits = 32, \697 .shift = 4, \698 .endianness = IIO_BE, \699 } \700}701 702static const struct iio_chan_spec adxl355_channels[] = {703 ADXL355_ACCEL_CHANNEL(0, chan_x, X),704 ADXL355_ACCEL_CHANNEL(1, chan_y, Y),705 ADXL355_ACCEL_CHANNEL(2, chan_z, Z),706 {707 .type = IIO_TEMP,708 .address = ADXL355_TEMP2_REG,709 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |710 BIT(IIO_CHAN_INFO_SCALE) |711 BIT(IIO_CHAN_INFO_OFFSET),712 .scan_index = 3,713 .scan_type = {714 .sign = 's',715 .realbits = 12,716 .storagebits = 16,717 .endianness = IIO_BE,718 },719 },720 IIO_CHAN_SOFT_TIMESTAMP(4),721};722 723static int adxl355_probe_trigger(struct iio_dev *indio_dev, int irq)724{725 struct adxl355_data *data = iio_priv(indio_dev);726 int ret;727 728 data->dready_trig = devm_iio_trigger_alloc(data->dev, "%s-dev%d",729 indio_dev->name,730 iio_device_id(indio_dev));731 if (!data->dready_trig)732 return -ENOMEM;733 734 data->dready_trig->ops = &adxl355_trigger_ops;735 iio_trigger_set_drvdata(data->dready_trig, indio_dev);736 737 ret = devm_request_irq(data->dev, irq,738 &iio_trigger_generic_data_rdy_poll,739 IRQF_ONESHOT, "adxl355_irq", data->dready_trig);740 if (ret)741 return dev_err_probe(data->dev, ret, "request irq %d failed\n",742 irq);743 744 ret = devm_iio_trigger_register(data->dev, data->dready_trig);745 if (ret) {746 dev_err(data->dev, "iio trigger register failed\n");747 return ret;748 }749 750 indio_dev->trig = iio_trigger_get(data->dready_trig);751 752 return 0;753}754 755int adxl355_core_probe(struct device *dev, struct regmap *regmap,756 const struct adxl355_chip_info *chip_info)757{758 struct adxl355_data *data;759 struct iio_dev *indio_dev;760 int ret;761 int irq;762 763 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));764 if (!indio_dev)765 return -ENOMEM;766 767 data = iio_priv(indio_dev);768 data->regmap = regmap;769 data->dev = dev;770 data->op_mode = ADXL355_STANDBY;771 data->chip_info = chip_info;772 mutex_init(&data->lock);773 774 indio_dev->name = chip_info->name;775 indio_dev->info = &adxl355_info;776 indio_dev->modes = INDIO_DIRECT_MODE;777 indio_dev->channels = adxl355_channels;778 indio_dev->num_channels = ARRAY_SIZE(adxl355_channels);779 indio_dev->available_scan_masks = adxl355_avail_scan_masks;780 781 ret = adxl355_setup(data);782 if (ret) {783 dev_err(dev, "ADXL355 setup failed\n");784 return ret;785 }786 787 ret = devm_iio_triggered_buffer_setup(dev, indio_dev,788 &iio_pollfunc_store_time,789 &adxl355_trigger_handler, NULL);790 if (ret) {791 dev_err(dev, "iio triggered buffer setup failed\n");792 return ret;793 }794 795 irq = fwnode_irq_get_byname(dev_fwnode(dev), "DRDY");796 if (irq > 0) {797 ret = adxl355_probe_trigger(indio_dev, irq);798 if (ret)799 return ret;800 }801 802 return devm_iio_device_register(dev, indio_dev);803}804EXPORT_SYMBOL_NS_GPL(adxl355_core_probe, IIO_ADXL355);805 806MODULE_AUTHOR("Puranjay Mohan <puranjay12@gmail.com>");807MODULE_DESCRIPTION("ADXL355 3-Axis Digital Accelerometer core driver");808MODULE_LICENSE("GPL v2");809