brintos

brintos / linux-shallow public Read only

0
0
Text · 45.9 KiB · f80527d Raw
1906 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * ADXL380 3-Axis Digital Accelerometer core driver4 *5 * Copyright 2024 Analog Devices Inc.6 */7 8#include <linux/bitfield.h>9#include <linux/interrupt.h>10#include <linux/irq.h>11#include <linux/module.h>12#include <linux/property.h>13#include <linux/regmap.h>14#include <linux/units.h>15 16#include <linux/unaligned.h>17 18#include <linux/iio/buffer.h>19#include <linux/iio/events.h>20#include <linux/iio/iio.h>21#include <linux/iio/kfifo_buf.h>22#include <linux/iio/sysfs.h>23 24#include <linux/regulator/consumer.h>25 26#include "adxl380.h"27 28#define ADXL380_ID_VAL				38029#define ADXL382_ID_VAL				38230 31#define ADXL380_DEVID_AD_REG			0x0032#define ADLX380_PART_ID_REG			0x0233 34#define ADXL380_X_DATA_H_REG			0x1535#define ADXL380_Y_DATA_H_REG			0x1736#define ADXL380_Z_DATA_H_REG			0x1937#define ADXL380_T_DATA_H_REG			0x1B38 39#define ADXL380_MISC_0_REG			0x2040#define ADXL380_XL382_MSK			BIT(7)41 42#define ADXL380_MISC_1_REG			0x2143 44#define ADXL380_X_DSM_OFFSET_REG		0x4D45 46#define ADXL380_ACT_INACT_CTL_REG		0x3747#define ADXL380_INACT_EN_MSK			BIT(2)48#define ADXL380_ACT_EN_MSK			BIT(0)49 50#define ADXL380_SNSR_AXIS_EN_REG		0x3851#define ADXL380_ACT_INACT_AXIS_EN_MSK		GENMASK(2, 0)52 53#define ADXL380_THRESH_ACT_H_REG		0x3954#define ADXL380_TIME_ACT_H_REG			0x3B55#define ADXL380_THRESH_INACT_H_REG		0x3E56#define ADXL380_TIME_INACT_H_REG		0x4057#define ADXL380_THRESH_MAX			GENMASK(12, 0)58#define ADXL380_TIME_MAX			GENMASK(24, 0)59 60#define ADXL380_FIFO_CONFIG_0_REG		0x3061#define ADXL380_FIFO_SAMPLES_8_MSK		BIT(0)62#define ADXL380_FIFO_MODE_MSK			GENMASK(5, 4)63 64#define ADXL380_FIFO_DISABLED			065#define ADXL380_FIFO_NORMAL			166#define ADXL380_FIFO_STREAMED			267#define ADXL380_FIFO_TRIGGERED			368 69#define ADXL380_FIFO_CONFIG_1_REG		0x3170#define ADXL380_FIFO_STATUS_0_REG		0x1E71 72#define ADXL380_TAP_THRESH_REG			0x4373#define ADXL380_TAP_DUR_REG			0x4474#define ADXL380_TAP_LATENT_REG			0x4575#define ADXL380_TAP_WINDOW_REG			0x4676#define ADXL380_TAP_TIME_MAX			GENMASK(7, 0)77 78#define ADXL380_TAP_CFG_REG			0x4779#define ADXL380_TAP_AXIS_MSK			GENMASK(1, 0)80 81#define ADXL380_TRIG_CFG_REG			0x4982#define ADXL380_TRIG_CFG_DEC_2X_MSK		BIT(7)83#define ADXL380_TRIG_CFG_SINC_RATE_MSK		BIT(6)84 85#define ADXL380_FILTER_REG			0x5086#define ADXL380_FILTER_EQ_FILT_MSK		BIT(6)87#define ADXL380_FILTER_LPF_MODE_MSK		GENMASK(5, 4)88#define ADXL380_FILTER_HPF_PATH_MSK		BIT(3)89#define ADXL380_FILTER_HPF_CORNER_MSK		GENMASK(2, 0)90 91#define ADXL380_OP_MODE_REG			0x2692#define ADXL380_OP_MODE_RANGE_MSK		GENMASK(7, 6)93#define ADXL380_OP_MODE_MSK			GENMASK(3, 0)94#define ADXL380_OP_MODE_STANDBY			095#define ADXL380_OP_MODE_HEART_SOUND		196#define ADXL380_OP_MODE_ULP			297#define ADXL380_OP_MODE_VLP			398#define ADXL380_OP_MODE_LP			499#define ADXL380_OP_MODE_LP_ULP			6100#define ADXL380_OP_MODE_LP_VLP			7101#define ADXL380_OP_MODE_RBW			8102#define ADXL380_OP_MODE_RBW_ULP			10103#define ADXL380_OP_MODE_RBW_VLP			11104#define ADXL380_OP_MODE_HP			12105#define ADXL380_OP_MODE_HP_ULP			14106#define ADXL380_OP_MODE_HP_VLP			15107 108#define ADXL380_OP_MODE_4G_RANGE		0109#define ADXL382_OP_MODE_15G_RANGE		0110#define ADXL380_OP_MODE_8G_RANGE		1111#define ADXL382_OP_MODE_30G_RANGE		1112#define ADXL380_OP_MODE_16G_RANGE		2113#define ADXL382_OP_MODE_60G_RANGE		2114 115#define ADXL380_DIG_EN_REG			0x27116#define ADXL380_CHAN_EN_MSK(chan)		BIT(4 + (chan))117#define ADXL380_FIFO_EN_MSK			BIT(3)118 119#define ADXL380_INT0_MAP0_REG			0x2B120#define ADXL380_INT1_MAP0_REG			0x2D121#define ADXL380_INT_MAP0_INACT_INT0_MSK		BIT(6)122#define ADXL380_INT_MAP0_ACT_INT0_MSK		BIT(5)123#define ADXL380_INT_MAP0_FIFO_WM_INT0_MSK	BIT(3)124 125#define ADXL380_INT0_MAP1_REG			0x2C126#define ADXL380_INT1_MAP1_REG			0x2E127#define ADXL380_INT_MAP1_DOUBLE_TAP_INT0_MSK	BIT(1)128#define ADXL380_INT_MAP1_SINGLE_TAP_INT0_MSK	BIT(0)129 130#define ADXL380_INT0_REG			0x5D131#define ADXL380_INT0_POL_MSK			BIT(7)132 133#define ADXL380_RESET_REG			0x2A134#define ADXL380_FIFO_DATA			0x1D135 136#define ADXL380_DEVID_AD_VAL			0xAD137#define ADXL380_RESET_CODE			0x52138 139#define ADXL380_STATUS_0_REG			0x11140#define ADXL380_STATUS_0_FIFO_FULL_MSK		BIT(1)141#define ADXL380_STATUS_0_FIFO_WM_MSK		BIT(3)142 143#define ADXL380_STATUS_1_INACT_MSK		BIT(6)144#define ADXL380_STATUS_1_ACT_MSK		BIT(5)145#define ADXL380_STATUS_1_DOUBLE_TAP_MSK		BIT(1)146#define ADXL380_STATUS_1_SINGLE_TAP_MSK		BIT(0)147 148#define ADXL380_FIFO_SAMPLES			315UL149 150enum adxl380_channels {151	ADXL380_ACCEL_X,152	ADXL380_ACCEL_Y,153	ADXL380_ACCEL_Z,154	ADXL380_TEMP,155	ADXL380_CH_NUM156};157 158enum adxl380_axis {159	ADXL380_X_AXIS,160	ADXL380_Y_AXIS,161	ADXL380_Z_AXIS,162};163 164enum adxl380_activity_type {165	ADXL380_ACTIVITY,166	ADXL380_INACTIVITY,167};168 169enum adxl380_tap_type {170	ADXL380_SINGLE_TAP,171	ADXL380_DOUBLE_TAP,172};173 174enum adxl380_tap_time_type {175	ADXL380_TAP_TIME_LATENT,176	ADXL380_TAP_TIME_WINDOW,177};178 179static const int adxl380_range_scale_factor_tbl[] = { 1, 2, 4 };180 181const struct adxl380_chip_info adxl380_chip_info = {182	.name = "adxl380",183	.chip_id = ADXL380_ID_VAL,184	.scale_tbl = {185		[ADXL380_OP_MODE_4G_RANGE] = { 0, 1307226 },186		[ADXL380_OP_MODE_8G_RANGE] = { 0, 2615434 },187		[ADXL380_OP_MODE_16G_RANGE] = { 0, 5229886 },188	},189	.samp_freq_tbl = { 8000, 16000, 32000 },190	/*191	 * The datasheet defines an intercept of 470 LSB at 25 degC192	 * and a sensitivity of 10.2 LSB/C.193	 */194	.temp_offset =  25 * 102 / 10 - 470,195 196};197EXPORT_SYMBOL_NS_GPL(adxl380_chip_info, IIO_ADXL380);198 199const struct adxl380_chip_info adxl382_chip_info = {200	.name = "adxl382",201	.chip_id = ADXL382_ID_VAL,202	.scale_tbl = {203		[ADXL382_OP_MODE_15G_RANGE] = { 0, 4903325 },204		[ADXL382_OP_MODE_30G_RANGE] = { 0, 9806650 },205		[ADXL382_OP_MODE_60G_RANGE] = { 0, 19613300 },206	},207	.samp_freq_tbl = { 16000, 32000, 64000 },208	/*209	 * The datasheet defines an intercept of 570 LSB at 25 degC210	 * and a sensitivity of 10.2 LSB/C.211	 */212	.temp_offset =  25 * 102 / 10 - 570,213};214EXPORT_SYMBOL_NS_GPL(adxl382_chip_info, IIO_ADXL380);215 216static const unsigned int adxl380_th_reg_high_addr[2] = {217	[ADXL380_ACTIVITY] = ADXL380_THRESH_ACT_H_REG,218	[ADXL380_INACTIVITY] = ADXL380_THRESH_INACT_H_REG,219};220 221static const unsigned int adxl380_time_reg_high_addr[2] = {222	[ADXL380_ACTIVITY] = ADXL380_TIME_ACT_H_REG,223	[ADXL380_INACTIVITY] = ADXL380_TIME_INACT_H_REG,224};225 226static const unsigned int adxl380_tap_time_reg[2] = {227	[ADXL380_TAP_TIME_LATENT] = ADXL380_TAP_LATENT_REG,228	[ADXL380_TAP_TIME_WINDOW] = ADXL380_TAP_WINDOW_REG,229};230 231struct adxl380_state {232	struct regmap *regmap;233	struct device *dev;234	const struct adxl380_chip_info *chip_info;235	/*236	 * Synchronize access to members of driver state, and ensure atomicity237	 * of consecutive regmap operations.238	 */239	struct mutex lock;240	enum adxl380_axis tap_axis_en;241	u8 range;242	u8 odr;243	u8 fifo_set_size;244	u8 transf_buf[3];245	u16 watermark;246	u32 act_time_ms;247	u32 act_threshold;248	u32 inact_time_ms;249	u32 inact_threshold;250	u32 tap_latent_us;251	u32 tap_window_us;252	u32 tap_duration_us;253	u32 tap_threshold;254	int irq;255	int int_map[2];256	int lpf_tbl[4];257	int hpf_tbl[7][2];258 259	__be16 fifo_buf[ADXL380_FIFO_SAMPLES] __aligned(IIO_DMA_MINALIGN);260};261 262bool adxl380_readable_noinc_reg(struct device *dev, unsigned int reg)263{264	return reg == ADXL380_FIFO_DATA;265}266EXPORT_SYMBOL_NS_GPL(adxl380_readable_noinc_reg, IIO_ADXL380);267 268static int adxl380_set_measure_en(struct adxl380_state *st, bool en)269{270	int ret;271	unsigned int act_inact_ctl;272	u8 op_mode = ADXL380_OP_MODE_STANDBY;273 274	if (en) {275		ret = regmap_read(st->regmap, ADXL380_ACT_INACT_CTL_REG, &act_inact_ctl);276		if (ret)277			return ret;278 279		/* Activity/ Inactivity detection available only in VLP/ULP mode */280		if (FIELD_GET(ADXL380_ACT_EN_MSK, act_inact_ctl) ||281		    FIELD_GET(ADXL380_INACT_EN_MSK, act_inact_ctl))282			op_mode = ADXL380_OP_MODE_VLP;283		else284			op_mode = ADXL380_OP_MODE_HP;285	}286 287	return regmap_update_bits(st->regmap, ADXL380_OP_MODE_REG,288				 ADXL380_OP_MODE_MSK,289				 FIELD_PREP(ADXL380_OP_MODE_MSK, op_mode));290}291 292static void adxl380_scale_act_inact_thresholds(struct adxl380_state *st,293					       u8 old_range,294					       u8 new_range)295{296	st->act_threshold = mult_frac(st->act_threshold,297				      adxl380_range_scale_factor_tbl[old_range],298				      adxl380_range_scale_factor_tbl[new_range]);299	st->inact_threshold = mult_frac(st->inact_threshold,300					adxl380_range_scale_factor_tbl[old_range],301					adxl380_range_scale_factor_tbl[new_range]);302}303 304static int adxl380_write_act_inact_threshold(struct adxl380_state *st,305					     enum adxl380_activity_type act,306					     unsigned int th)307{308	int ret;309	u8 reg = adxl380_th_reg_high_addr[act];310 311	if (th > ADXL380_THRESH_MAX)312		return -EINVAL;313 314	ret = regmap_write(st->regmap, reg + 1, th & GENMASK(7, 0));315	if (ret)316		return ret;317 318	ret = regmap_update_bits(st->regmap, reg, GENMASK(2, 0), th >> 8);319	if (ret)320		return ret;321 322	if (act == ADXL380_ACTIVITY)323		st->act_threshold = th;324	else325		st->inact_threshold = th;326 327	return 0;328}329 330static int adxl380_set_act_inact_threshold(struct iio_dev *indio_dev,331					   enum adxl380_activity_type act,332					   u16 th)333{334	struct adxl380_state *st = iio_priv(indio_dev);335	int ret;336 337	guard(mutex)(&st->lock);338 339	ret = adxl380_set_measure_en(st, false);340	if (ret)341		return ret;342 343	ret = adxl380_write_act_inact_threshold(st, act, th);344	if (ret)345		return ret;346 347	return adxl380_set_measure_en(st, true);348}349 350static int adxl380_set_tap_threshold_value(struct iio_dev *indio_dev, u8 th)351{352	int ret;353	struct adxl380_state *st = iio_priv(indio_dev);354 355	guard(mutex)(&st->lock);356 357	ret = adxl380_set_measure_en(st, false);358	if (ret)359		return ret;360 361	ret = regmap_write(st->regmap, ADXL380_TAP_THRESH_REG, th);362	if (ret)363		return ret;364 365	st->tap_threshold = th;366 367	return adxl380_set_measure_en(st, true);368}369 370static int _adxl380_write_tap_time_us(struct adxl380_state *st,371				      enum adxl380_tap_time_type tap_time_type,372				      u32 us)373{374	u8 reg = adxl380_tap_time_reg[tap_time_type];375	unsigned int reg_val;376	int ret;377 378	/* scale factor for tap window is 1250us / LSB */379	reg_val = DIV_ROUND_CLOSEST(us, 1250);380	if (reg_val > ADXL380_TAP_TIME_MAX)381		reg_val = ADXL380_TAP_TIME_MAX;382 383	ret = regmap_write(st->regmap, reg, reg_val);384	if (ret)385		return ret;386 387	if (tap_time_type == ADXL380_TAP_TIME_WINDOW)388		st->tap_window_us = us;389	else390		st->tap_latent_us = us;391 392	return 0;393}394 395static int adxl380_write_tap_time_us(struct adxl380_state *st,396				     enum adxl380_tap_time_type tap_time_type, u32 us)397{398	int ret;399 400	guard(mutex)(&st->lock);401 402	ret = adxl380_set_measure_en(st, false);403	if (ret)404		return ret;405 406	ret = _adxl380_write_tap_time_us(st, tap_time_type, us);407	if (ret)408		return ret;409 410	return adxl380_set_measure_en(st, true);411}412 413static int adxl380_write_tap_dur_us(struct iio_dev *indio_dev, u32 us)414{415	int ret;416	unsigned int reg_val;417	struct adxl380_state *st = iio_priv(indio_dev);418 419	/* 625us per code is the scale factor of TAP_DUR register */420	reg_val = DIV_ROUND_CLOSEST(us, 625);421 422	ret = adxl380_set_measure_en(st, false);423	if (ret)424		return ret;425 426	ret = regmap_write(st->regmap, ADXL380_TAP_DUR_REG, reg_val);427	if (ret)428		return ret;429 430	return adxl380_set_measure_en(st, true);431}432 433static int adxl380_read_chn(struct adxl380_state *st, u8 addr)434{435	int ret;436 437	guard(mutex)(&st->lock);438 439	ret = regmap_bulk_read(st->regmap, addr, &st->transf_buf, 2);440	if (ret)441		return ret;442 443	return get_unaligned_be16(st->transf_buf);444}445 446static int adxl380_get_odr(struct adxl380_state *st, int *odr)447{448	int ret;449	unsigned int trig_cfg, odr_idx;450 451	ret = regmap_read(st->regmap, ADXL380_TRIG_CFG_REG, &trig_cfg);452	if (ret)453		return ret;454 455	odr_idx = (FIELD_GET(ADXL380_TRIG_CFG_SINC_RATE_MSK, trig_cfg) << 1) |456		  (FIELD_GET(ADXL380_TRIG_CFG_DEC_2X_MSK, trig_cfg) & 1);457 458	*odr = st->chip_info->samp_freq_tbl[odr_idx];459 460	return 0;461}462 463static const int adxl380_lpf_div[] = {464	1, 4, 8, 16,465};466 467static int adxl380_fill_lpf_tbl(struct adxl380_state *st)468{469	int ret, i;470	int odr;471 472	ret = adxl380_get_odr(st, &odr);473	if (ret)474		return ret;475 476	for (i = 0; i < ARRAY_SIZE(st->lpf_tbl); i++)477		st->lpf_tbl[i] = DIV_ROUND_CLOSEST(odr, adxl380_lpf_div[i]);478 479	return 0;480}481 482static const int adxl380_hpf_mul[] = {483	0, 247000, 62084, 15545, 3862, 954, 238,484};485 486static int adxl380_fill_hpf_tbl(struct adxl380_state *st)487{488	int i, ret, odr_hz;489	u32 multiplier;490	u64 div, rem, odr;491 492	ret =  adxl380_get_odr(st, &odr_hz);493	if (ret)494		return ret;495 496	for (i = 0; i < ARRAY_SIZE(adxl380_hpf_mul); i++) {497		odr = mul_u64_u32_shr(odr_hz, MEGA, 0);498		multiplier = adxl380_hpf_mul[i];499		div = div64_u64_rem(mul_u64_u32_shr(odr, multiplier, 0),500				    TERA * 100, &rem);501 502		st->hpf_tbl[i][0] = div;503		st->hpf_tbl[i][1] = div_u64(rem, MEGA * 100);504	}505 506	return 0;507}508 509static int adxl380_set_odr(struct adxl380_state *st, u8 odr)510{511	int ret;512 513	guard(mutex)(&st->lock);514 515	ret = adxl380_set_measure_en(st, false);516	if (ret)517		return ret;518 519	ret = regmap_update_bits(st->regmap, ADXL380_TRIG_CFG_REG,520				 ADXL380_TRIG_CFG_DEC_2X_MSK,521				 FIELD_PREP(ADXL380_TRIG_CFG_DEC_2X_MSK, odr & 1));522	if (ret)523		return ret;524 525	ret = regmap_update_bits(st->regmap, ADXL380_TRIG_CFG_REG,526				 ADXL380_TRIG_CFG_SINC_RATE_MSK,527				 FIELD_PREP(ADXL380_TRIG_CFG_SINC_RATE_MSK, odr >> 1));528	if (ret)529		return ret;530 531	ret = adxl380_set_measure_en(st, true);532	if (ret)533		return ret;534 535	ret = adxl380_fill_lpf_tbl(st);536	if (ret)537		return ret;538 539	return adxl380_fill_hpf_tbl(st);540}541 542static int adxl380_find_match_1d_tbl(const int *array, unsigned int size,543				     int val)544{545	int i;546 547	for (i = 0; i < size; i++) {548		if (val == array[i])549			return i;550	}551 552	return size - 1;553}554 555static int adxl380_find_match_2d_tbl(const int (*freq_tbl)[2], int n, int val, int val2)556{557	int i;558 559	for (i = 0; i < n; i++) {560		if (freq_tbl[i][0] == val && freq_tbl[i][1] == val2)561			return i;562	}563 564	return -EINVAL;565}566 567static int adxl380_get_lpf(struct adxl380_state *st, int *lpf)568{569	int ret;570	unsigned int trig_cfg, lpf_idx;571 572	guard(mutex)(&st->lock);573 574	ret = regmap_read(st->regmap, ADXL380_FILTER_REG, &trig_cfg);575	if (ret)576		return ret;577 578	lpf_idx = FIELD_GET(ADXL380_FILTER_LPF_MODE_MSK, trig_cfg);579 580	*lpf = st->lpf_tbl[lpf_idx];581 582	return 0;583}584 585static int adxl380_set_lpf(struct adxl380_state *st, u8 lpf)586{587	int ret;588	u8 eq_bypass = 0;589 590	guard(mutex)(&st->lock);591 592	ret = adxl380_set_measure_en(st, false);593	if (ret)594		return ret;595 596	if (lpf)597		eq_bypass = 1;598 599	ret = regmap_update_bits(st->regmap, ADXL380_FILTER_REG,600				 ADXL380_FILTER_EQ_FILT_MSK,601				 FIELD_PREP(ADXL380_FILTER_EQ_FILT_MSK, eq_bypass));602	if (ret)603		return ret;604 605	ret = regmap_update_bits(st->regmap, ADXL380_FILTER_REG,606				 ADXL380_FILTER_LPF_MODE_MSK,607				 FIELD_PREP(ADXL380_FILTER_LPF_MODE_MSK, lpf));608	if (ret)609		return ret;610 611	return adxl380_set_measure_en(st, true);612}613 614static int adxl380_get_hpf(struct adxl380_state *st, int *hpf_int, int *hpf_frac)615{616	int ret;617	unsigned int trig_cfg, hpf_idx;618 619	guard(mutex)(&st->lock);620 621	ret = regmap_read(st->regmap, ADXL380_FILTER_REG, &trig_cfg);622	if (ret)623		return ret;624 625	hpf_idx = FIELD_GET(ADXL380_FILTER_HPF_CORNER_MSK, trig_cfg);626 627	*hpf_int = st->hpf_tbl[hpf_idx][0];628	*hpf_frac = st->hpf_tbl[hpf_idx][1];629 630	return 0;631}632 633static int adxl380_set_hpf(struct adxl380_state *st, u8 hpf)634{635	int ret;636	u8 hpf_path = 0;637 638	guard(mutex)(&st->lock);639 640	ret = adxl380_set_measure_en(st, false);641	if (ret)642		return ret;643 644	if (hpf)645		hpf_path = 1;646 647	ret = regmap_update_bits(st->regmap, ADXL380_FILTER_REG,648				 ADXL380_FILTER_HPF_PATH_MSK,649				 FIELD_PREP(ADXL380_FILTER_HPF_PATH_MSK, hpf_path));650	if (ret)651		return ret;652 653	ret = regmap_update_bits(st->regmap, ADXL380_FILTER_REG,654				 ADXL380_FILTER_HPF_CORNER_MSK,655				 FIELD_PREP(ADXL380_FILTER_HPF_CORNER_MSK, hpf));656	if (ret)657		return ret;658 659	return adxl380_set_measure_en(st, true);660}661 662static int _adxl380_set_act_inact_time_ms(struct adxl380_state *st,663					  enum adxl380_activity_type act,664					  u32 ms)665{666	u8 reg = adxl380_time_reg_high_addr[act];667	unsigned int reg_val;668	int ret;669 670	/* 500us per code is the scale factor of TIME_ACT / TIME_INACT registers */671	reg_val = min(DIV_ROUND_CLOSEST(ms * 1000, 500), ADXL380_TIME_MAX);672 673	put_unaligned_be24(reg_val, &st->transf_buf[0]);674 675	ret = regmap_bulk_write(st->regmap, reg, st->transf_buf, sizeof(st->transf_buf));676	if (ret)677		return ret;678 679	if (act == ADXL380_ACTIVITY)680		st->act_time_ms = ms;681	else682		st->inact_time_ms = ms;683 684	return 0;685}686 687static int adxl380_set_act_inact_time_ms(struct adxl380_state *st,688					 enum adxl380_activity_type act,689					 u32 ms)690{691	int ret;692 693	guard(mutex)(&st->lock);694 695	ret = adxl380_set_measure_en(st, false);696	if (ret)697		return ret;698 699	ret = _adxl380_set_act_inact_time_ms(st, act, ms);700	if (ret)701		return ret;702 703	return adxl380_set_measure_en(st, true);704}705 706static int adxl380_set_range(struct adxl380_state *st, u8 range)707{708	int ret;709 710	guard(mutex)(&st->lock);711 712	ret = adxl380_set_measure_en(st, false);713	if (ret)714		return ret;715 716	ret = regmap_update_bits(st->regmap, ADXL380_OP_MODE_REG,717				 ADXL380_OP_MODE_RANGE_MSK,718				 FIELD_PREP(ADXL380_OP_MODE_RANGE_MSK, range));719 720	if (ret)721		return ret;722 723	adxl380_scale_act_inact_thresholds(st, st->range, range);724 725	/* Activity thresholds depend on range */726	ret = adxl380_write_act_inact_threshold(st, ADXL380_ACTIVITY,727						st->act_threshold);728	if (ret)729		return ret;730 731	ret = adxl380_write_act_inact_threshold(st, ADXL380_INACTIVITY,732						st->inact_threshold);733	if (ret)734		return ret;735 736	st->range = range;737 738	return adxl380_set_measure_en(st, true);739}740 741static int adxl380_write_act_inact_en(struct adxl380_state *st,742				      enum adxl380_activity_type type,743				      bool en)744{745	if (type == ADXL380_ACTIVITY)746		return regmap_update_bits(st->regmap, ADXL380_ACT_INACT_CTL_REG,747					  ADXL380_ACT_EN_MSK,748					  FIELD_PREP(ADXL380_ACT_EN_MSK, en));749 750	return regmap_update_bits(st->regmap, ADXL380_ACT_INACT_CTL_REG,751				  ADXL380_INACT_EN_MSK,752				  FIELD_PREP(ADXL380_INACT_EN_MSK, en));753}754 755static int adxl380_read_act_inact_int(struct adxl380_state *st,756				      enum adxl380_activity_type type,757				      bool *en)758{759	int ret;760	unsigned int reg_val;761 762	guard(mutex)(&st->lock);763 764	ret = regmap_read(st->regmap, st->int_map[0], &reg_val);765	if (ret)766		return ret;767 768	if (type == ADXL380_ACTIVITY)769		*en = FIELD_GET(ADXL380_INT_MAP0_ACT_INT0_MSK, reg_val);770	else771		*en = FIELD_GET(ADXL380_INT_MAP0_INACT_INT0_MSK, reg_val);772 773	return 0;774}775 776static int adxl380_write_act_inact_int(struct adxl380_state *st,777				       enum adxl380_activity_type act,778				       bool en)779{780	if (act == ADXL380_ACTIVITY)781		return regmap_update_bits(st->regmap, st->int_map[0],782					  ADXL380_INT_MAP0_ACT_INT0_MSK,783					  FIELD_PREP(ADXL380_INT_MAP0_ACT_INT0_MSK, en));784 785	return regmap_update_bits(st->regmap, st->int_map[0],786				  ADXL380_INT_MAP0_INACT_INT0_MSK,787				  FIELD_PREP(ADXL380_INT_MAP0_INACT_INT0_MSK, en));788}789 790static int adxl380_act_inact_config(struct adxl380_state *st,791				    enum adxl380_activity_type type,792				    bool en)793{794	int ret;795 796	guard(mutex)(&st->lock);797 798	ret = adxl380_set_measure_en(st, false);799	if (ret)800		return ret;801 802	ret = adxl380_write_act_inact_en(st, type, en);803	if (ret)804		return ret;805 806	ret = adxl380_write_act_inact_int(st, type, en);807	if (ret)808		return ret;809 810	return adxl380_set_measure_en(st, true);811}812 813static int adxl380_write_tap_axis(struct adxl380_state *st,814				  enum adxl380_axis axis)815{816	int ret;817 818	ret = regmap_update_bits(st->regmap, ADXL380_TAP_CFG_REG,819				 ADXL380_TAP_AXIS_MSK,820				 FIELD_PREP(ADXL380_TAP_AXIS_MSK, axis));821 822	if (ret)823		return ret;824 825	st->tap_axis_en = axis;826 827	return 0;828}829 830static int adxl380_read_tap_int(struct adxl380_state *st, enum adxl380_tap_type type, bool *en)831{832	int ret;833	unsigned int reg_val;834 835	ret = regmap_read(st->regmap, st->int_map[1], &reg_val);836	if (ret)837		return ret;838 839	if (type == ADXL380_SINGLE_TAP)840		*en = FIELD_GET(ADXL380_INT_MAP1_SINGLE_TAP_INT0_MSK, reg_val);841	else842		*en = FIELD_GET(ADXL380_INT_MAP1_DOUBLE_TAP_INT0_MSK, reg_val);843 844	return 0;845}846 847static int adxl380_write_tap_int(struct adxl380_state *st, enum adxl380_tap_type type, bool en)848{849	if (type == ADXL380_SINGLE_TAP)850		return regmap_update_bits(st->regmap, st->int_map[1],851					  ADXL380_INT_MAP1_SINGLE_TAP_INT0_MSK,852					  FIELD_PREP(ADXL380_INT_MAP1_SINGLE_TAP_INT0_MSK, en));853 854	return regmap_update_bits(st->regmap, st->int_map[1],855				  ADXL380_INT_MAP1_DOUBLE_TAP_INT0_MSK,856				  FIELD_PREP(ADXL380_INT_MAP1_DOUBLE_TAP_INT0_MSK, en));857}858 859static int adxl380_tap_config(struct adxl380_state *st,860			      enum adxl380_axis axis,861			      enum adxl380_tap_type type,862			      bool en)863{864	int ret;865 866	guard(mutex)(&st->lock);867 868	ret = adxl380_set_measure_en(st, false);869	if (ret)870		return ret;871 872	ret = adxl380_write_tap_axis(st, axis);873	if (ret)874		return ret;875 876	ret = adxl380_write_tap_int(st, type, en);877	if (ret)878		return ret;879 880	return adxl380_set_measure_en(st, true);881}882 883static int adxl380_set_fifo_samples(struct adxl380_state *st)884{885	int ret;886	u16 fifo_samples = st->watermark * st->fifo_set_size;887 888	ret = regmap_update_bits(st->regmap, ADXL380_FIFO_CONFIG_0_REG,889				 ADXL380_FIFO_SAMPLES_8_MSK,890				 FIELD_PREP(ADXL380_FIFO_SAMPLES_8_MSK,891					    (fifo_samples & BIT(8))));892	if (ret)893		return ret;894 895	return regmap_write(st->regmap, ADXL380_FIFO_CONFIG_1_REG,896			    fifo_samples & 0xFF);897}898 899static int adxl380_get_status(struct adxl380_state *st, u8 *status0, u8 *status1)900{901	int ret;902 903	/* STATUS0, STATUS1 are adjacent regs */904	ret = regmap_bulk_read(st->regmap, ADXL380_STATUS_0_REG,905			       &st->transf_buf, 2);906	if (ret)907		return ret;908 909	*status0 = st->transf_buf[0];910	*status1 = st->transf_buf[1];911 912	return 0;913}914 915static int adxl380_get_fifo_entries(struct adxl380_state *st, u16 *fifo_entries)916{917	int ret;918 919	ret = regmap_bulk_read(st->regmap, ADXL380_FIFO_STATUS_0_REG,920			       &st->transf_buf, 2);921	if (ret)922		return ret;923 924	*fifo_entries = st->transf_buf[0] | ((BIT(0) & st->transf_buf[1]) << 8);925 926	return 0;927}928 929static void adxl380_push_event(struct iio_dev *indio_dev, s64 timestamp,930			       u8 status1)931{932	if (FIELD_GET(ADXL380_STATUS_1_ACT_MSK, status1))933		iio_push_event(indio_dev,934			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z,935						  IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),936			       timestamp);937 938	if (FIELD_GET(ADXL380_STATUS_1_INACT_MSK, status1))939		iio_push_event(indio_dev,940			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z,941						  IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),942			       timestamp);943	if (FIELD_GET(ADXL380_STATUS_1_SINGLE_TAP_MSK, status1))944		iio_push_event(indio_dev,945			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z,946						  IIO_EV_TYPE_GESTURE, IIO_EV_DIR_SINGLETAP),947			       timestamp);948 949	if (FIELD_GET(ADXL380_STATUS_1_DOUBLE_TAP_MSK, status1))950		iio_push_event(indio_dev,951			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z,952						  IIO_EV_TYPE_GESTURE, IIO_EV_DIR_DOUBLETAP),953			       timestamp);954}955 956static irqreturn_t adxl380_irq_handler(int irq, void  *p)957{958	struct iio_dev *indio_dev = p;959	struct adxl380_state *st = iio_priv(indio_dev);960	u8 status0, status1;961	u16 fifo_entries;962	int i;963	int ret;964 965	guard(mutex)(&st->lock);966 967	ret = adxl380_get_status(st, &status0, &status1);968	if (ret)969		return IRQ_HANDLED;970 971	adxl380_push_event(indio_dev, iio_get_time_ns(indio_dev), status1);972 973	if (!FIELD_GET(ADXL380_STATUS_0_FIFO_WM_MSK, status0))974		return IRQ_HANDLED;975 976	ret = adxl380_get_fifo_entries(st, &fifo_entries);977	if (ret)978		return IRQ_HANDLED;979 980	for (i = 0; i < fifo_entries; i += st->fifo_set_size) {981		ret = regmap_noinc_read(st->regmap, ADXL380_FIFO_DATA,982					&st->fifo_buf[i],983					2 * st->fifo_set_size);984		if (ret)985			return IRQ_HANDLED;986		iio_push_to_buffers(indio_dev, &st->fifo_buf[i]);987	}988 989	return IRQ_HANDLED;990}991 992static int adxl380_write_calibbias_value(struct adxl380_state *st,993					 unsigned long chan_addr,994					 s8 calibbias)995{996	int ret;997 998	guard(mutex)(&st->lock);999 1000	ret = adxl380_set_measure_en(st, false);1001	if (ret)1002		return ret;1003 1004	ret = regmap_write(st->regmap, ADXL380_X_DSM_OFFSET_REG + chan_addr, calibbias);1005	if (ret)1006		return ret;1007 1008	return adxl380_set_measure_en(st, true);1009}1010 1011static int adxl380_read_calibbias_value(struct adxl380_state *st,1012					unsigned long chan_addr,1013					int *calibbias)1014{1015	int ret;1016	unsigned int reg_val;1017 1018	guard(mutex)(&st->lock);1019 1020	ret = regmap_read(st->regmap, ADXL380_X_DSM_OFFSET_REG + chan_addr, &reg_val);1021	if (ret)1022		return ret;1023 1024	*calibbias = sign_extend32(reg_val, 7);1025 1026	return 0;1027}1028 1029static ssize_t hwfifo_watermark_min_show(struct device *dev,1030					 struct device_attribute *attr,1031					 char *buf)1032{1033	return sysfs_emit(buf, "1\n");1034}1035 1036static ssize_t hwfifo_watermark_max_show(struct device *dev,1037					 struct device_attribute *attr,1038					 char *buf)1039{1040	return sysfs_emit(buf, "%lu\n", ADXL380_FIFO_SAMPLES);1041}1042 1043static ssize_t adxl380_get_fifo_watermark(struct device *dev,1044					  struct device_attribute *attr,1045					  char *buf)1046{1047	struct iio_dev *indio_dev = dev_to_iio_dev(dev);1048	struct adxl380_state *st = iio_priv(indio_dev);1049 1050	return sysfs_emit(buf, "%d\n", st->watermark);1051}1052 1053static ssize_t adxl380_get_fifo_enabled(struct device *dev,1054					struct device_attribute *attr,1055					char *buf)1056{1057	struct iio_dev *indio_dev = dev_to_iio_dev(dev);1058	struct adxl380_state *st = iio_priv(indio_dev);1059	int ret;1060	unsigned int reg_val;1061 1062	ret = regmap_read(st->regmap, ADXL380_DIG_EN_REG, &reg_val);1063	if (ret)1064		return ret;1065 1066	return sysfs_emit(buf, "%lu\n",1067			  FIELD_GET(ADXL380_FIFO_EN_MSK, reg_val));1068}1069 1070static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);1071static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);1072static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,1073		       adxl380_get_fifo_watermark, NULL, 0);1074static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,1075		       adxl380_get_fifo_enabled, NULL, 0);1076 1077static const struct iio_dev_attr *adxl380_fifo_attributes[] = {1078	&iio_dev_attr_hwfifo_watermark_min,1079	&iio_dev_attr_hwfifo_watermark_max,1080	&iio_dev_attr_hwfifo_watermark,1081	&iio_dev_attr_hwfifo_enabled,1082	NULL1083};1084 1085static int adxl380_buffer_postenable(struct iio_dev *indio_dev)1086{1087	struct adxl380_state *st = iio_priv(indio_dev);1088	int i;1089	int ret;1090 1091	guard(mutex)(&st->lock);1092 1093	ret = adxl380_set_measure_en(st, false);1094	if (ret)1095		return ret;1096 1097	ret = regmap_update_bits(st->regmap,1098				 st->int_map[0],1099				 ADXL380_INT_MAP0_FIFO_WM_INT0_MSK,1100				 FIELD_PREP(ADXL380_INT_MAP0_FIFO_WM_INT0_MSK, 1));1101	if (ret)1102		return ret;1103 1104	for_each_clear_bit(i, indio_dev->active_scan_mask, ADXL380_CH_NUM) {1105		ret = regmap_update_bits(st->regmap, ADXL380_DIG_EN_REG,1106					 ADXL380_CHAN_EN_MSK(i),1107					 0 << (4 + i));1108		if (ret)1109			return ret;1110	}1111 1112	st->fifo_set_size = bitmap_weight(indio_dev->active_scan_mask,1113					  iio_get_masklength(indio_dev));1114 1115	if ((st->watermark * st->fifo_set_size) > ADXL380_FIFO_SAMPLES)1116		st->watermark = (ADXL380_FIFO_SAMPLES  / st->fifo_set_size);1117 1118	ret = adxl380_set_fifo_samples(st);1119	if (ret)1120		return ret;1121 1122	ret = regmap_update_bits(st->regmap, ADXL380_DIG_EN_REG, ADXL380_FIFO_EN_MSK,1123				 FIELD_PREP(ADXL380_FIFO_EN_MSK, 1));1124	if (ret)1125		return ret;1126 1127	return adxl380_set_measure_en(st, true);1128}1129 1130static int adxl380_buffer_predisable(struct iio_dev *indio_dev)1131{1132	struct adxl380_state *st = iio_priv(indio_dev);1133	int ret, i;1134 1135	guard(mutex)(&st->lock);1136 1137	ret = adxl380_set_measure_en(st, false);1138	if (ret)1139		return ret;1140 1141	ret = regmap_update_bits(st->regmap,1142				 st->int_map[0],1143				 ADXL380_INT_MAP0_FIFO_WM_INT0_MSK,1144				 FIELD_PREP(ADXL380_INT_MAP0_FIFO_WM_INT0_MSK, 0));1145	if (ret)1146		return ret;1147 1148	for (i = 0; i < indio_dev->num_channels; i++) {1149		ret = regmap_update_bits(st->regmap, ADXL380_DIG_EN_REG,1150					 ADXL380_CHAN_EN_MSK(i),1151					 1 << (4 + i));1152		if (ret)1153			return ret;1154	}1155 1156	ret = regmap_update_bits(st->regmap, ADXL380_DIG_EN_REG, ADXL380_FIFO_EN_MSK,1157				 FIELD_PREP(ADXL380_FIFO_EN_MSK, 0));1158	if (ret)1159		return ret;1160 1161	return adxl380_set_measure_en(st, true);1162}1163 1164static const struct iio_buffer_setup_ops adxl380_buffer_ops = {1165	.postenable = adxl380_buffer_postenable,1166	.predisable = adxl380_buffer_predisable,1167};1168 1169static int adxl380_read_raw(struct iio_dev *indio_dev,1170			    struct iio_chan_spec const *chan,1171			    int *val, int *val2, long info)1172{1173	struct adxl380_state *st = iio_priv(indio_dev);1174	int ret;1175 1176	switch (info) {1177	case IIO_CHAN_INFO_RAW:1178		ret = iio_device_claim_direct_mode(indio_dev);1179		if (ret)1180			return ret;1181 1182		ret = adxl380_read_chn(st, chan->address);1183		iio_device_release_direct_mode(indio_dev);1184		if (ret)1185			return ret;1186 1187		*val = sign_extend32(ret >> chan->scan_type.shift,1188				     chan->scan_type.realbits - 1);1189		return IIO_VAL_INT;1190	case IIO_CHAN_INFO_SCALE:1191		switch (chan->type) {1192		case IIO_ACCEL:1193			scoped_guard(mutex, &st->lock) {1194				*val = st->chip_info->scale_tbl[st->range][0];1195				*val2 = st->chip_info->scale_tbl[st->range][1];1196			}1197			return IIO_VAL_INT_PLUS_NANO;1198		case IIO_TEMP:1199			/* 10.2 LSB / Degree Celsius */1200			*val = 10000;1201			*val2 = 102;1202			return IIO_VAL_FRACTIONAL;1203		default:1204			return -EINVAL;1205		}1206	case IIO_CHAN_INFO_OFFSET:1207		switch (chan->type) {1208		case IIO_TEMP:1209			*val = st->chip_info->temp_offset;1210			return IIO_VAL_INT;1211		default:1212			return -EINVAL;1213		}1214	case IIO_CHAN_INFO_CALIBBIAS:1215		switch (chan->type) {1216		case IIO_ACCEL:1217			ret = adxl380_read_calibbias_value(st, chan->scan_index, val);1218			if (ret)1219				return ret;1220			return IIO_VAL_INT;1221		default:1222			return -EINVAL;1223		}1224	case IIO_CHAN_INFO_SAMP_FREQ:1225		ret = adxl380_get_odr(st, val);1226		if (ret)1227			return ret;1228		return IIO_VAL_INT;1229	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:1230		ret =  adxl380_get_lpf(st, val);1231		if (ret)1232			return ret;1233		return IIO_VAL_INT;1234	case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:1235		ret =  adxl380_get_hpf(st, val, val2);1236		if (ret)1237			return ret;1238		return IIO_VAL_INT_PLUS_MICRO;1239	}1240 1241	return -EINVAL;1242}1243 1244static int adxl380_read_avail(struct iio_dev *indio_dev,1245			      struct iio_chan_spec const *chan,1246			      const int **vals, int *type, int *length,1247			      long mask)1248{1249	struct adxl380_state *st = iio_priv(indio_dev);1250 1251	if (chan->type != IIO_ACCEL)1252		return -EINVAL;1253 1254	switch (mask) {1255	case IIO_CHAN_INFO_SCALE:1256		*vals = (const int *)st->chip_info->scale_tbl;1257		*type = IIO_VAL_INT_PLUS_NANO;1258		*length = ARRAY_SIZE(st->chip_info->scale_tbl) * 2;1259		return IIO_AVAIL_LIST;1260	case IIO_CHAN_INFO_SAMP_FREQ:1261		*vals = (const int *)st->chip_info->samp_freq_tbl;1262		*type = IIO_VAL_INT;1263		*length = ARRAY_SIZE(st->chip_info->samp_freq_tbl);1264		return IIO_AVAIL_LIST;1265	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:1266		*vals = (const int *)st->lpf_tbl;1267		*type = IIO_VAL_INT;1268		*length = ARRAY_SIZE(st->lpf_tbl);1269		return IIO_AVAIL_LIST;1270	case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:1271		*vals = (const int *)st->hpf_tbl;1272		*type = IIO_VAL_INT_PLUS_MICRO;1273		/* Values are stored in a 2D matrix */1274		*length = ARRAY_SIZE(st->hpf_tbl) * 2;1275		return IIO_AVAIL_LIST;1276	default:1277		return -EINVAL;1278	}1279}1280 1281static int adxl380_write_raw(struct iio_dev *indio_dev,1282			     struct iio_chan_spec const *chan,1283			     int val, int val2, long info)1284{1285	struct adxl380_state *st = iio_priv(indio_dev);1286	int odr_index, lpf_index, hpf_index, range_index;1287 1288	switch (info) {1289	case IIO_CHAN_INFO_SAMP_FREQ:1290		odr_index = adxl380_find_match_1d_tbl(st->chip_info->samp_freq_tbl,1291						      ARRAY_SIZE(st->chip_info->samp_freq_tbl),1292						      val);1293		return adxl380_set_odr(st, odr_index);1294	case IIO_CHAN_INFO_CALIBBIAS:1295		return adxl380_write_calibbias_value(st, chan->scan_index, val);1296	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:1297		lpf_index = adxl380_find_match_1d_tbl(st->lpf_tbl,1298						      ARRAY_SIZE(st->lpf_tbl),1299						      val);1300		return adxl380_set_lpf(st, lpf_index);1301	case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:1302		hpf_index = adxl380_find_match_2d_tbl(st->hpf_tbl,1303						      ARRAY_SIZE(st->hpf_tbl),1304						      val, val2);1305		if (hpf_index < 0)1306			return hpf_index;1307		return adxl380_set_hpf(st, hpf_index);1308	case IIO_CHAN_INFO_SCALE:1309		range_index = adxl380_find_match_2d_tbl(st->chip_info->scale_tbl,1310							ARRAY_SIZE(st->chip_info->scale_tbl),1311							val, val2);1312		if (range_index < 0)1313			return range_index;1314		return adxl380_set_range(st, range_index);1315	default:1316		return -EINVAL;1317	}1318}1319 1320static int adxl380_write_raw_get_fmt(struct iio_dev *indio_dev,1321				     struct iio_chan_spec const *chan,1322				     long info)1323{1324	switch (info) {1325	case IIO_CHAN_INFO_SCALE:1326		if (chan->type != IIO_ACCEL)1327			return -EINVAL;1328 1329		return IIO_VAL_INT_PLUS_NANO;1330	default:1331		return IIO_VAL_INT_PLUS_MICRO;1332	}1333}1334 1335static int adxl380_read_event_config(struct iio_dev *indio_dev,1336				     const struct iio_chan_spec *chan,1337				     enum iio_event_type type,1338				     enum iio_event_direction dir)1339{1340	struct adxl380_state *st = iio_priv(indio_dev);1341	int ret;1342	bool int_en;1343	bool tap_axis_en = false;1344 1345	switch (chan->channel2) {1346	case IIO_MOD_X:1347		tap_axis_en = st->tap_axis_en == ADXL380_X_AXIS;1348		break;1349	case IIO_MOD_Y:1350		tap_axis_en = st->tap_axis_en == ADXL380_Y_AXIS;1351		break;1352	case IIO_MOD_Z:1353		tap_axis_en = st->tap_axis_en == ADXL380_Z_AXIS;1354		break;1355	default:1356		return -EINVAL;1357	}1358 1359	switch (dir) {1360	case IIO_EV_DIR_RISING:1361		ret = adxl380_read_act_inact_int(st, ADXL380_ACTIVITY, &int_en);1362		if (ret)1363			return ret;1364		return int_en;1365	case IIO_EV_DIR_FALLING:1366		ret = adxl380_read_act_inact_int(st, ADXL380_INACTIVITY, &int_en);1367		if (ret)1368			return ret;1369		return int_en;1370	case IIO_EV_DIR_SINGLETAP:1371		ret = adxl380_read_tap_int(st, ADXL380_SINGLE_TAP, &int_en);1372		if (ret)1373			return ret;1374		return int_en && tap_axis_en;1375	case IIO_EV_DIR_DOUBLETAP:1376		ret = adxl380_read_tap_int(st, ADXL380_DOUBLE_TAP, &int_en);1377		if (ret)1378			return ret;1379		return int_en && tap_axis_en;1380	default:1381		return -EINVAL;1382	}1383}1384 1385static int adxl380_write_event_config(struct iio_dev *indio_dev,1386				      const struct iio_chan_spec *chan,1387				      enum iio_event_type type,1388				      enum iio_event_direction dir,1389				      int state)1390{1391	struct adxl380_state *st = iio_priv(indio_dev);1392	enum adxl380_axis axis;1393 1394	switch (chan->channel2) {1395	case IIO_MOD_X:1396		axis = ADXL380_X_AXIS;1397		break;1398	case IIO_MOD_Y:1399		axis = ADXL380_Y_AXIS;1400		break;1401	case IIO_MOD_Z:1402		axis = ADXL380_Z_AXIS;1403		break;1404	default:1405		return -EINVAL;1406	}1407 1408	switch (dir) {1409	case IIO_EV_DIR_RISING:1410		return adxl380_act_inact_config(st, ADXL380_ACTIVITY, state);1411	case IIO_EV_DIR_FALLING:1412		return adxl380_act_inact_config(st, ADXL380_INACTIVITY, state);1413	case IIO_EV_DIR_SINGLETAP:1414		return adxl380_tap_config(st, axis, ADXL380_SINGLE_TAP, state);1415	case IIO_EV_DIR_DOUBLETAP:1416		return adxl380_tap_config(st, axis, ADXL380_DOUBLE_TAP, state);1417	default:1418		return -EINVAL;1419	}1420}1421 1422static int adxl380_read_event_value(struct iio_dev *indio_dev,1423				    const struct iio_chan_spec *chan,1424				    enum iio_event_type type,1425				    enum iio_event_direction dir,1426				    enum iio_event_info info,1427				    int *val, int *val2)1428{1429	struct adxl380_state *st = iio_priv(indio_dev);1430 1431	guard(mutex)(&st->lock);1432 1433	switch (type) {1434	case IIO_EV_TYPE_THRESH:1435		switch (info) {1436		case IIO_EV_INFO_VALUE: {1437			switch (dir) {1438			case IIO_EV_DIR_RISING:1439				*val = st->act_threshold;1440				return IIO_VAL_INT;1441			case IIO_EV_DIR_FALLING:1442				*val = st->inact_threshold;1443				return IIO_VAL_INT;1444			default:1445				return -EINVAL;1446			}1447		}1448		case IIO_EV_INFO_PERIOD:1449			switch (dir) {1450			case IIO_EV_DIR_RISING:1451				*val = st->act_time_ms;1452				*val2 = 1000;1453				return IIO_VAL_FRACTIONAL;1454			case IIO_EV_DIR_FALLING:1455				*val = st->inact_time_ms;1456				*val2 = 1000;1457				return IIO_VAL_FRACTIONAL;1458			default:1459				return -EINVAL;1460			}1461		default:1462			return -EINVAL;1463		}1464	case IIO_EV_TYPE_GESTURE:1465		switch (info) {1466		case IIO_EV_INFO_VALUE:1467			*val = st->tap_threshold;1468			return IIO_VAL_INT;1469		case IIO_EV_INFO_RESET_TIMEOUT:1470			*val = st->tap_window_us;1471			*val2 = 1000000;1472			return IIO_VAL_FRACTIONAL;1473		case IIO_EV_INFO_TAP2_MIN_DELAY:1474			*val = st->tap_latent_us;1475			*val2 = 1000000;1476			return IIO_VAL_FRACTIONAL;1477		default:1478			return -EINVAL;1479		}1480	default:1481		return -EINVAL;1482	}1483}1484 1485static int adxl380_write_event_value(struct iio_dev *indio_dev,1486				     const struct iio_chan_spec *chan,1487				     enum iio_event_type type, enum iio_event_direction dir,1488				     enum iio_event_info info, int val, int val2)1489{1490	struct adxl380_state *st = iio_priv(indio_dev);1491	u32 val_ms, val_us;1492 1493	if (chan->type != IIO_ACCEL)1494		return -EINVAL;1495 1496	switch (type) {1497	case IIO_EV_TYPE_THRESH:1498		switch (info) {1499		case IIO_EV_INFO_VALUE:1500			switch (dir) {1501			case IIO_EV_DIR_RISING:1502				return adxl380_set_act_inact_threshold(indio_dev,1503								       ADXL380_ACTIVITY, val);1504			case IIO_EV_DIR_FALLING:1505				return adxl380_set_act_inact_threshold(indio_dev,1506								       ADXL380_INACTIVITY, val);1507			default:1508				return -EINVAL;1509			}1510		case IIO_EV_INFO_PERIOD:1511			val_ms = val * 1000 + DIV_ROUND_UP(val2, 1000);1512			switch (dir) {1513			case IIO_EV_DIR_RISING:1514				return adxl380_set_act_inact_time_ms(st,1515								     ADXL380_ACTIVITY, val_ms);1516			case IIO_EV_DIR_FALLING:1517				return adxl380_set_act_inact_time_ms(st,1518								     ADXL380_INACTIVITY, val_ms);1519			default:1520				return -EINVAL;1521			}1522 1523		default:1524			return -EINVAL;1525		}1526	case IIO_EV_TYPE_GESTURE:1527		switch (info) {1528		case IIO_EV_INFO_VALUE:1529			return adxl380_set_tap_threshold_value(indio_dev, val);1530		case IIO_EV_INFO_RESET_TIMEOUT:1531			val_us = val * 1000000 + val2;1532			return adxl380_write_tap_time_us(st,1533							 ADXL380_TAP_TIME_WINDOW,1534							 val_us);1535		case IIO_EV_INFO_TAP2_MIN_DELAY:1536			val_us = val * 1000000 + val2;1537			return adxl380_write_tap_time_us(st,1538							 ADXL380_TAP_TIME_LATENT,1539							 val_us);1540		default:1541			return -EINVAL;1542		}1543	default:1544		return -EINVAL;1545	}1546}1547 1548static ssize_t in_accel_gesture_tap_maxtomin_time_show(struct device *dev,1549						       struct device_attribute *attr,1550						       char *buf)1551{1552	int vals[2];1553	struct iio_dev *indio_dev = dev_to_iio_dev(dev);1554	struct adxl380_state *st = iio_priv(indio_dev);1555 1556	guard(mutex)(&st->lock);1557 1558	vals[0] = st->tap_duration_us;1559	vals[1] = MICRO;1560 1561	return iio_format_value(buf, IIO_VAL_FRACTIONAL, 2, vals);1562}1563 1564static ssize_t in_accel_gesture_tap_maxtomin_time_store(struct device *dev,1565							struct device_attribute *attr,1566							const char *buf, size_t len)1567{1568	struct iio_dev *indio_dev = dev_to_iio_dev(dev);1569	struct adxl380_state *st = iio_priv(indio_dev);1570	int ret, val_int, val_fract_us;1571 1572	guard(mutex)(&st->lock);1573 1574	ret = iio_str_to_fixpoint(buf, 100000, &val_int, &val_fract_us);1575	if (ret)1576		return ret;1577 1578	/* maximum value is 255 * 625 us = 0.159375 seconds */1579	if (val_int || val_fract_us > 159375 || val_fract_us < 0)1580		return -EINVAL;1581 1582	ret = adxl380_write_tap_dur_us(indio_dev, val_fract_us);1583	if (ret)1584		return ret;1585 1586	return len;1587}1588 1589static IIO_DEVICE_ATTR_RW(in_accel_gesture_tap_maxtomin_time, 0);1590 1591static struct attribute *adxl380_event_attributes[] = {1592	&iio_dev_attr_in_accel_gesture_tap_maxtomin_time.dev_attr.attr,1593	NULL1594};1595 1596static const struct attribute_group adxl380_event_attribute_group = {1597	.attrs = adxl380_event_attributes,1598};1599 1600static int adxl380_reg_access(struct iio_dev *indio_dev,1601			      unsigned int reg,1602			      unsigned int writeval,1603			      unsigned int *readval)1604{1605	struct adxl380_state *st = iio_priv(indio_dev);1606 1607	if (readval)1608		return regmap_read(st->regmap, reg, readval);1609 1610	return regmap_write(st->regmap, reg, writeval);1611}1612 1613static int adxl380_set_watermark(struct iio_dev *indio_dev, unsigned int val)1614{1615	struct adxl380_state *st  = iio_priv(indio_dev);1616 1617	st->watermark = min(val, ADXL380_FIFO_SAMPLES);1618 1619	return 0;1620}1621 1622static const struct iio_info adxl380_info = {1623	.read_raw = adxl380_read_raw,1624	.read_avail = &adxl380_read_avail,1625	.write_raw = adxl380_write_raw,1626	.write_raw_get_fmt = adxl380_write_raw_get_fmt,1627	.read_event_config = adxl380_read_event_config,1628	.write_event_config = adxl380_write_event_config,1629	.read_event_value = adxl380_read_event_value,1630	.write_event_value = adxl380_write_event_value,1631	.event_attrs = &adxl380_event_attribute_group,1632	.debugfs_reg_access = &adxl380_reg_access,1633	.hwfifo_set_watermark = adxl380_set_watermark,1634};1635 1636static const struct iio_event_spec adxl380_events[] = {1637	{1638		.type = IIO_EV_TYPE_THRESH,1639		.dir = IIO_EV_DIR_RISING,1640		.mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |1641				       BIT(IIO_EV_INFO_VALUE) |1642				       BIT(IIO_EV_INFO_PERIOD),1643	},1644	{1645		.type = IIO_EV_TYPE_THRESH,1646		.dir = IIO_EV_DIR_FALLING,1647		.mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |1648				       BIT(IIO_EV_INFO_VALUE) |1649				       BIT(IIO_EV_INFO_PERIOD),1650	},1651	{1652		.type = IIO_EV_TYPE_GESTURE,1653		.dir = IIO_EV_DIR_SINGLETAP,1654		.mask_separate = BIT(IIO_EV_INFO_ENABLE),1655		.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |1656				       BIT(IIO_EV_INFO_RESET_TIMEOUT),1657	},1658	{1659		.type = IIO_EV_TYPE_GESTURE,1660		.dir = IIO_EV_DIR_DOUBLETAP,1661		.mask_separate = BIT(IIO_EV_INFO_ENABLE),1662		.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |1663				       BIT(IIO_EV_INFO_RESET_TIMEOUT) |1664				       BIT(IIO_EV_INFO_TAP2_MIN_DELAY),1665	},1666};1667 1668#define ADXL380_ACCEL_CHANNEL(index, reg, axis) {			\1669	.type = IIO_ACCEL,						\1670	.address = reg,							\1671	.modified = 1,							\1672	.channel2 = IIO_MOD_##axis,					\1673	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |			\1674			      BIT(IIO_CHAN_INFO_CALIBBIAS),		\1675	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),	\1676	.info_mask_shared_by_all_available =				\1677		BIT(IIO_CHAN_INFO_SAMP_FREQ),				\1678	.info_mask_shared_by_type =					\1679		BIT(IIO_CHAN_INFO_SCALE) |				\1680		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) |	\1681		BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY),	\1682	.info_mask_shared_by_type_available =				\1683		BIT(IIO_CHAN_INFO_SCALE) |				\1684		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) |	\1685		BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY),	\1686	.scan_index = index,						\1687	.scan_type = {							\1688		.sign = 's',						\1689		.realbits = 16,						\1690		.storagebits = 16,					\1691		.endianness = IIO_BE,					\1692	},								\1693	.event_spec = adxl380_events,					\1694	.num_event_specs = ARRAY_SIZE(adxl380_events)			\1695}1696 1697static const struct iio_chan_spec adxl380_channels[] = {1698	ADXL380_ACCEL_CHANNEL(0, ADXL380_X_DATA_H_REG, X),1699	ADXL380_ACCEL_CHANNEL(1, ADXL380_Y_DATA_H_REG, Y),1700	ADXL380_ACCEL_CHANNEL(2, ADXL380_Z_DATA_H_REG, Z),1701	{1702		.type = IIO_TEMP,1703		.address = ADXL380_T_DATA_H_REG,1704		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |1705				      BIT(IIO_CHAN_INFO_SCALE) |1706				      BIT(IIO_CHAN_INFO_OFFSET),1707		.scan_index = 3,1708		.scan_type = {1709			.sign = 's',1710			.realbits = 12,1711			.storagebits = 16,1712			.shift = 4,1713			.endianness = IIO_BE,1714		},1715	},1716};1717 1718static int adxl380_config_irq(struct iio_dev *indio_dev)1719{1720	struct adxl380_state *st = iio_priv(indio_dev);1721	unsigned long irq_flag;1722	struct irq_data *desc;1723	u32 irq_type;1724	u8 polarity;1725	int ret;1726 1727	st->irq = fwnode_irq_get_byname(dev_fwnode(st->dev), "INT0");1728	if (st->irq > 0) {1729		st->int_map[0] = ADXL380_INT0_MAP0_REG;1730		st->int_map[1] = ADXL380_INT0_MAP1_REG;1731	} else {1732		st->irq = fwnode_irq_get_byname(dev_fwnode(st->dev), "INT1");1733		if (st->irq > 0)1734			return dev_err_probe(st->dev, -ENODEV,1735					     "no interrupt name specified");1736		st->int_map[0] = ADXL380_INT1_MAP0_REG;1737		st->int_map[1] = ADXL380_INT1_MAP1_REG;1738	}1739 1740	desc = irq_get_irq_data(st->irq);1741	if (!desc)1742		return dev_err_probe(st->dev, -EINVAL, "Could not find IRQ %d\n", st->irq);1743 1744	irq_type = irqd_get_trigger_type(desc);1745	if (irq_type == IRQ_TYPE_LEVEL_HIGH) {1746		polarity = 0;1747		irq_flag = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;1748	} else if (irq_type == IRQ_TYPE_LEVEL_LOW) {1749		polarity = 1;1750		irq_flag = IRQF_TRIGGER_LOW | IRQF_ONESHOT;1751	} else {1752		return dev_err_probe(st->dev, -EINVAL,1753				     "Invalid interrupt 0x%x. Only level interrupts supported\n",1754				     irq_type);1755	}1756 1757	ret = regmap_update_bits(st->regmap, ADXL380_INT0_REG,1758				 ADXL380_INT0_POL_MSK,1759				 FIELD_PREP(ADXL380_INT0_POL_MSK, polarity));1760	if (ret)1761		return ret;1762 1763	return devm_request_threaded_irq(st->dev, st->irq, NULL,1764					 adxl380_irq_handler, irq_flag,1765					 indio_dev->name, indio_dev);1766}1767 1768static int adxl380_setup(struct iio_dev *indio_dev)1769{1770	unsigned int reg_val;1771	u16 part_id, chip_id;1772	int ret, i;1773	struct adxl380_state *st = iio_priv(indio_dev);1774 1775	ret = regmap_read(st->regmap, ADXL380_DEVID_AD_REG, &reg_val);1776	if (ret)1777		return ret;1778 1779	if (reg_val != ADXL380_DEVID_AD_VAL)1780		dev_warn(st->dev, "Unknown chip id %x\n", reg_val);1781 1782	ret = regmap_bulk_read(st->regmap, ADLX380_PART_ID_REG,1783			       &st->transf_buf, 2);1784	if (ret)1785		return ret;1786 1787	part_id = get_unaligned_be16(st->transf_buf);1788	part_id >>= 4;1789 1790	if (part_id != ADXL380_ID_VAL)1791		dev_warn(st->dev, "Unknown part id %x\n", part_id);1792 1793	ret = regmap_read(st->regmap, ADXL380_MISC_0_REG, &reg_val);1794	if (ret)1795		return ret;1796 1797	/* Bit to differentiate between ADXL380/382. */1798	if (reg_val & ADXL380_XL382_MSK)1799		chip_id = ADXL382_ID_VAL;1800	else1801		chip_id = ADXL380_ID_VAL;1802 1803	if (chip_id != st->chip_info->chip_id)1804		dev_warn(st->dev, "Unknown chip id %x\n", chip_id);1805 1806	ret = regmap_write(st->regmap, ADXL380_RESET_REG, ADXL380_RESET_CODE);1807	if (ret)1808		return ret;1809 1810	/*1811	 * A latency of approximately 0.5 ms is required after soft reset.1812	 * Stated in the register REG_RESET description.1813	 */1814	fsleep(500);1815 1816	for (i = 0; i < indio_dev->num_channels; i++) {1817		ret = regmap_update_bits(st->regmap, ADXL380_DIG_EN_REG,1818					 ADXL380_CHAN_EN_MSK(i),1819					 1 << (4 + i));1820		if (ret)1821			return ret;1822	}1823 1824	ret = regmap_update_bits(st->regmap, ADXL380_FIFO_CONFIG_0_REG,1825				 ADXL380_FIFO_MODE_MSK,1826				 FIELD_PREP(ADXL380_FIFO_MODE_MSK, ADXL380_FIFO_STREAMED));1827	if (ret)1828		return ret;1829 1830	/* Select all 3 axis for act/inact detection. */1831	ret = regmap_update_bits(st->regmap, ADXL380_SNSR_AXIS_EN_REG,1832				 ADXL380_ACT_INACT_AXIS_EN_MSK,1833				 FIELD_PREP(ADXL380_ACT_INACT_AXIS_EN_MSK,1834					    ADXL380_ACT_INACT_AXIS_EN_MSK));1835	if (ret)1836		return ret;1837 1838	ret = adxl380_config_irq(indio_dev);1839	if (ret)1840		return ret;1841 1842	ret = adxl380_fill_lpf_tbl(st);1843	if (ret)1844		return ret;1845 1846	ret = adxl380_fill_hpf_tbl(st);1847	if (ret)1848		return ret;1849 1850	return adxl380_set_measure_en(st, true);1851}1852 1853int adxl380_probe(struct device *dev, struct regmap *regmap,1854		  const struct adxl380_chip_info *chip_info)1855{1856	struct iio_dev *indio_dev;1857	struct adxl380_state *st;1858	int ret;1859 1860	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));1861	if (!indio_dev)1862		return -ENOMEM;1863 1864	st = iio_priv(indio_dev);1865 1866	st->dev = dev;1867	st->regmap = regmap;1868	st->chip_info = chip_info;1869 1870	mutex_init(&st->lock);1871 1872	indio_dev->channels = adxl380_channels;1873	indio_dev->num_channels = ARRAY_SIZE(adxl380_channels);1874	indio_dev->name = chip_info->name;1875	indio_dev->info = &adxl380_info;1876	indio_dev->modes = INDIO_DIRECT_MODE;1877 1878	ret = devm_regulator_get_enable(dev, "vddio");1879	if (ret)1880		return dev_err_probe(st->dev, ret,1881				     "Failed to get vddio regulator\n");1882 1883	ret = devm_regulator_get_enable(st->dev, "vsupply");1884	if (ret)1885		return dev_err_probe(st->dev, ret,1886				     "Failed to get vsupply regulator\n");1887 1888	ret = adxl380_setup(indio_dev);1889	if (ret)1890		return ret;1891 1892	ret = devm_iio_kfifo_buffer_setup_ext(st->dev, indio_dev,1893					      &adxl380_buffer_ops,1894					      adxl380_fifo_attributes);1895	if (ret)1896		return ret;1897 1898	return devm_iio_device_register(dev, indio_dev);1899}1900EXPORT_SYMBOL_NS_GPL(adxl380_probe, IIO_ADXL380);1901 1902MODULE_AUTHOR("Ramona Gradinariu <ramona.gradinariu@analog.com>");1903MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");1904MODULE_DESCRIPTION("Analog Devices ADXL380 3-axis accelerometer driver");1905MODULE_LICENSE("GPL");1906