cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

adxl355_core.c (18895B)


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